From 9d6f232dd118ade1bb16c46467b7a4151348f8c8 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Mon, 29 May 2023 14:13:11 +0200 Subject: [PATCH] Tweaked `block_seen` logic --- src/block_template.cpp | 2 +- src/p2p_server.cpp | 2 +- src/side_chain.cpp | 50 +++++++++++++++++++----------------------- src/side_chain.h | 11 +++++----- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/block_template.cpp b/src/block_template.cpp index e500a02..d9a9bd9 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -1325,7 +1325,7 @@ bool BlockTemplate::submit_sidechain_block(uint32_t template_id, uint32_t nonce, } m_poolBlockTemplate->m_verified = true; - if (!m_sidechain->block_seen(*m_poolBlockTemplate)) { + if (!m_sidechain->incoming_block_seen(*m_poolBlockTemplate)) { m_poolBlockTemplate->m_wantBroadcast = true; const bool result = m_sidechain->add_block(*m_poolBlockTemplate); if (!result) { diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index 80c00cb..53c9023 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -2309,7 +2309,7 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u } } - if (side_chain.block_seen(*block)) { + if (side_chain.incoming_block_seen(*block)) { LOGINFO(6, "block " << block->m_sidechainId << " (nonce " << block->m_nonce << ", extra_nonce " << block->m_extraNonce << ") was received before, skipping it"); return true; } diff --git a/src/side_chain.cpp b/src/side_chain.cpp index c3d2549..ecd0e89 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -92,7 +92,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name) uv_rwlock_init_checked(&m_sidechainLock); uv_mutex_init_checked(&m_seenWalletsLock); - uv_mutex_init_checked(&m_seenBlocksLock); + uv_mutex_init_checked(&m_incomingBlocksLock); uv_rwlock_init_checked(&m_curDifficultyLock); m_difficultyData.reserve(m_chainWindowSize); @@ -209,7 +209,7 @@ SideChain::~SideChain() uv_rwlock_destroy(&m_sidechainLock); uv_mutex_destroy(&m_seenWalletsLock); - uv_mutex_destroy(&m_seenBlocksLock); + uv_mutex_destroy(&m_incomingBlocksLock); uv_rwlock_destroy(&m_curDifficultyLock); for (const auto& it : m_blocksById) { @@ -469,7 +469,7 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector& shares return true; } -bool SideChain::block_seen(const PoolBlock& block) +bool SideChain::incoming_block_seen(const PoolBlock& block) { // Check if it's some old block const PoolBlock* tip = m_chainTip; @@ -479,37 +479,35 @@ bool SideChain::block_seen(const PoolBlock& block) return true; } + const uint64_t cur_time = seconds_since_epoch(); + // Check if it was received before - MutexLock lock(m_seenBlocksLock); - return !m_seenBlocks.insert(block.get_full_id()).second; + MutexLock lock(m_incomingBlocksLock); + return !m_incomingBlocks.emplace(block.get_full_id(), cur_time).second; } -void SideChain::unsee_block(const PoolBlock& block) +void SideChain::forget_incoming_block(const PoolBlock& block) { - MutexLock lock(m_seenBlocksLock); - m_seenBlocks.erase(block.get_full_id()); + MutexLock lock(m_incomingBlocksLock); + m_incomingBlocks.erase(block.get_full_id()); } -size_t SideChain::cleanup_seen_blocks() +void SideChain::cleanup_incoming_blocks() { - size_t n = 0; + const uint64_t cur_time = seconds_since_epoch(); - MutexLock lock(m_seenBlocksLock); + MutexLock lock(m_incomingBlocksLock); - // Forget seen blocks that weren't added for any reason + // Forget seen blocks that were added more than a minute ago hash h; - for (auto i = m_seenBlocks.begin(); i != m_seenBlocks.end();) { - memcpy(h.h, i->data(), HASH_SIZE); - if (m_blocksById.count(h) == 0) { - i = m_seenBlocks.erase(i); - ++n; - } - else { + for (auto i = m_incomingBlocks.begin(); i != m_incomingBlocks.end();) { + if (cur_time < i->second + 60) { ++i; } + else { + i = m_incomingBlocks.erase(i); + } } - - return n; } bool SideChain::add_external_block(PoolBlock& block, std::vector& missing_blocks) @@ -567,14 +565,14 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector& missing_ hash seed; if (!m_pool->get_seed(block.m_txinGenHeight, seed)) { LOGWARN(3, "add_external_block mined by " << block.m_minerWallet << ": couldn't get seed hash for mainchain height " << block.m_txinGenHeight); - unsee_block(block); + forget_incoming_block(block); return false; } hash pow_hash; if (!block.get_pow_hash(m_pool->hasher(), block.m_txinGenHeight, seed, pow_hash)) { LOGWARN(3, "add_external_block: couldn't get PoW hash for height = " << block.m_sidechainHeight << ", mainchain height " << block.m_txinGenHeight << ". Ignoring it."); - unsee_block(block); + forget_incoming_block(block); return true; } @@ -1753,6 +1751,7 @@ void SideChain::update_chain_tip(const PoolBlock* block) } } prune_old_blocks(); + cleanup_incoming_blocks(); } } else if (block->m_sidechainHeight > tip->m_sidechainHeight) { @@ -2056,11 +2055,6 @@ void SideChain::prune_old_blocks() // Pre-calc workers are not needed anymore finish_precalc(); - const size_t n = cleanup_seen_blocks(); - if (n > 0) { - LOGINFO(5, "pruned " << n << " seen blocks"); - } - #ifdef DEV_TEST_SYNC if (m_pool && m_precalcFinished.load() && (cur_time >= m_synchronizedTime + 120)) { LOGINFO(0, log::LightGreen() << "[DEV] Synchronization finished successfully, stopping P2Pool now"); diff --git a/src/side_chain.h b/src/side_chain.h index c9d0551..4ca1f91 100644 --- a/src/side_chain.h +++ b/src/side_chain.h @@ -46,9 +46,9 @@ public: void fill_sidechain_data(PoolBlock& block, std::vector& shares) const; - bool block_seen(const PoolBlock& block); - void unsee_block(const PoolBlock& block); - size_t cleanup_seen_blocks(); + bool incoming_block_seen(const PoolBlock& block); + void forget_incoming_block(const PoolBlock& block); + void cleanup_incoming_blocks(); bool add_external_block(PoolBlock& block, std::vector& missing_blocks); bool add_block(const PoolBlock& block); @@ -118,8 +118,9 @@ private: unordered_map m_seenWallets; uint64_t m_seenWalletsLastPruneTime; - uv_mutex_t m_seenBlocksLock; - unordered_set m_seenBlocks; + // Used to quickly cut off multiple broadcasts of the same block by different peers. Only the first broadcast will be processed. + uv_mutex_t m_incomingBlocksLock; + unordered_map m_incomingBlocks; std::vector m_difficultyData;