Fixed pruning logic

- Erase an element from m_blocksByHeight only if it's empty
- Remove blocks from unconnected alternative chains too when they get old enough (4xPPLNS window)
This commit is contained in:
SChernykh 2021-08-24 18:34:28 +02:00
parent d4388bf9c0
commit e4be4c1a66
4 changed files with 38 additions and 17 deletions

View file

@ -52,6 +52,7 @@ PoolBlock::PoolBlock()
, m_invalid(false)
, m_broadcasted(false)
, m_wantBroadcast(false)
, m_localTimestamp(time(nullptr))
{
uv_mutex_init_checked(&m_lock);
@ -114,6 +115,8 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b)
m_broadcasted = b.m_broadcasted;
m_wantBroadcast = b.m_wantBroadcast;
m_localTimestamp = time(nullptr);
if (lock_result == 0) {
uv_mutex_unlock(&b.m_lock);
}

View file

@ -131,6 +131,8 @@ struct PoolBlock
bool m_broadcasted;
bool m_wantBroadcast;
time_t m_localTimestamp;
void serialize_mainchain_data(uint32_t nonce, uint32_t extra_nonce, const hash& sidechain_hash);
void serialize_sidechain_data();

View file

@ -343,6 +343,8 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai
m_broadcasted = false;
m_wantBroadcast = false;
m_localTimestamp = time(nullptr);
return 0;
}

View file

@ -1368,6 +1368,9 @@ void SideChain::prune_old_blocks()
// Leave 2 minutes worth of spare blocks in addition to 2xPPLNS window for lagging nodes which need to sync
const uint64_t prune_distance = m_chainWindowSize * 2 + 120 / m_targetBlockTime;
// Remove old blocks from alternative unconnected chains after long enough time
const time_t prune_time = time(nullptr) - m_chainWindowSize * 4 * m_targetBlockTime;
if (m_chainTip->m_sidechainHeight < prune_distance) {
return;
}
@ -1377,24 +1380,35 @@ void SideChain::prune_old_blocks()
uint64_t num_blocks_pruned = 0;
for (auto it = m_blocksByHeight.begin(); (it != m_blocksByHeight.end()) && (it->first <= h);) {
for (PoolBlock* block : it->second) {
if (block->m_depth < prune_distance) {
continue;
}
auto it2 = m_blocksById.find(block->m_sidechainId);
if (it2 != m_blocksById.end()) {
m_blocksById.erase(it2);
delete block;
++num_blocks_pruned;
}
else {
LOGERR(1, "m_blocksByHeight and m_blocksById are inconsistent at height " << it->first << ". Fix the code!");
}
}
const uint64_t height = it->first;
std::vector<PoolBlock*>& v = it->second;
auto old_it = it;
++it;
m_blocksByHeight.erase(old_it);
v.erase(std::remove_if(v.begin(), v.end(),
[this, prune_distance, prune_time, &num_blocks_pruned, height](PoolBlock* block)
{
if ((block->m_depth >= prune_distance) || (block->m_localTimestamp <= prune_time)) {
auto it2 = m_blocksById.find(block->m_sidechainId);
if (it2 != m_blocksById.end()) {
m_blocksById.erase(it2);
delete block;
++num_blocks_pruned;
}
else {
LOGERR(1, "m_blocksByHeight and m_blocksById are inconsistent at height " << height << ". Fix the code!");
}
return true;
}
return false;
}), v.end());
if (v.empty()) {
auto old_it = it;
++it;
m_blocksByHeight.erase(old_it);
}
else {
++it;
}
}
if (num_blocks_pruned) {