diff --git a/src/pool_block.cpp b/src/pool_block.cpp index 00efc0b..2cdf159 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -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); } diff --git a/src/pool_block.h b/src/pool_block.h index 0712063..8a91533 100644 --- a/src/pool_block.h +++ b/src/pool_block.h @@ -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(); diff --git a/src/pool_block_parser.inl b/src/pool_block_parser.inl index 9d8573d..53bebd0 100644 --- a/src/pool_block_parser.inl +++ b/src/pool_block_parser.inl @@ -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; } diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 06ef897..c31f419 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -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& v = it->second; + + 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()); - auto old_it = it; - ++it; - m_blocksByHeight.erase(old_it); + if (v.empty()) { + auto old_it = it; + ++it; + m_blocksByHeight.erase(old_it); + } + else { + ++it; + } } if (num_blocks_pruned) {