From d642ffe2b17e1cd7dd37b0da747b3127b98cf570 Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Sun, 23 Oct 2022 23:05:14 -0400 Subject: [PATCH 1/6] validation, zmq: pass block in UpdatedBlockTip to avoid duplicate read Github-Pull: #26375 Rebased-From: 4a164160b61fa98325384826e67bc05baaa18265 --- src/net_processing.cpp | 4 ++-- src/node/interfaces.cpp | 2 +- src/test/validation_block_tests.cpp | 3 ++- src/validation.cpp | 6 +++++- src/validationinterface.cpp | 6 +++--- src/validationinterface.h | 4 ++-- src/zmq/zmqabstractnotifier.cpp | 2 +- src/zmq/zmqabstractnotifier.h | 3 ++- src/zmq/zmqnotificationinterface.cpp | 8 ++++---- src/zmq/zmqnotificationinterface.h | 2 +- src/zmq/zmqpublishnotifier.cpp | 22 ++++------------------ src/zmq/zmqpublishnotifier.h | 4 ++-- 12 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 3bfb606037..d1d19579f7 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -488,7 +488,7 @@ public: EXCLUSIVE_LOCKS_REQUIRED(!m_recent_confirmed_transactions_mutex); void BlockDisconnected(const std::shared_ptr &block, const CBlockIndex* pindex) override EXCLUSIVE_LOCKS_REQUIRED(!m_recent_confirmed_transactions_mutex); - void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override + void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); void BlockChecked(const CBlock& block, const BlockValidationState& state) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex); @@ -2036,7 +2036,7 @@ void PeerManagerImpl::NewPoWValidBlock(const CBlockIndex *pindex, const std::sha * Update our best height and announce any block hashes which weren't previously * in m_chainman.ActiveChain() to our peers. */ -void PeerManagerImpl::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) +void PeerManagerImpl::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block) { SetBestHeight(pindexNew->nHeight); SetServiceFlagsIBDCache(!fInitialDownload); diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index f6dbe4f008..6a474f8b87 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -442,7 +442,7 @@ public: { m_notifications->blockDisconnected(kernel::MakeBlockInfo(index, block.get())); } - void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override + void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd, const std::shared_ptr& block) override { m_notifications->updatedBlockTip(); } diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 64cb5522eb..ea530a3d67 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -38,9 +38,10 @@ struct TestSubscriber final : public CValidationInterface { explicit TestSubscriber(uint256 tip) : m_expected_tip(tip) {} - void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override + void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload, const std::shared_ptr& block) override { BOOST_CHECK_EQUAL(m_expected_tip, pindexNew->GetBlockHash()); + BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash()); } void BlockConnected(ChainstateRole role, const std::shared_ptr& block, const CBlockIndex* pindex) override diff --git a/src/validation.cpp b/src/validation.cpp index a6cab6b095..fc9a63159a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3203,6 +3203,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< CBlockIndex *pindexMostWork = nullptr; CBlockIndex *pindexNewTip = nullptr; + std::shared_ptr new_tip_block{nullptr}; bool exited_ibd{false}; do { // Block until the validation queue drains. This should largely @@ -3251,6 +3252,9 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) { assert(trace.pblock && trace.pindex); GetMainSignals().BlockConnected(this->GetRole(), trace.pblock, trace.pindex); + if (trace.pindex == pindexNewTip) { + new_tip_block = trace.pblock; + } } // This will have been toggled in @@ -3276,7 +3280,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< // Enqueue while holding cs_main to ensure that UpdatedBlockTip is called in the order in which blocks are connected if (this == &m_chainman.ActiveChainstate() && pindexFork != pindexNewTip) { // Notify ValidationInterface subscribers - GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, still_in_ibd); + GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, still_in_ibd, new_tip_block); // Always notify the UI if a new block tip was connected if (kernel::IsInterrupted(m_chainman.GetNotifications().blockTip(GetSynchronizationState(still_in_ibd), *pindexNewTip))) { diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 9241395ad5..d8c18df92e 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -191,13 +191,13 @@ void SyncWithValidationInterfaceQueue() #define LOG_EVENT(fmt, ...) \ LogPrint(BCLog::VALIDATION, fmt "\n", __VA_ARGS__) -void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { +void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block) { // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which // the chain actually updates. One way to ensure this is for the caller to invoke this signal // in the same critical section where the chain is updated - auto event = [pindexNew, pindexFork, fInitialDownload, this] { - m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); }); + auto event = [pindexNew, pindexFork, fInitialDownload, block, this] { + m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload, block); }); }; ENQUEUE_AND_LOG_EVENT(event, "%s: new block hash=%s fork block hash=%s (in IBD=%s)", __func__, pindexNew->GetBlockHash().ToString(), diff --git a/src/validationinterface.h b/src/validationinterface.h index eb15aa4d5f..c430d8f07e 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -90,7 +90,7 @@ protected: * * Called on a background thread. Only called for the active chainstate. */ - virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} + virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block) {} /** * Notifies listeners of a transaction having been added to mempool. * @@ -199,7 +199,7 @@ public: size_t CallbacksPending(); - void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload); + void UpdatedBlockTip(const CBlockIndex *, const CBlockIndex *, bool fInitialDownload, const std::shared_ptr&); void TransactionAddedToMempool(const CTransactionRef&, uint64_t mempool_sequence); void TransactionRemovedFromMempool(const CTransactionRef&, MemPoolRemovalReason, uint64_t mempool_sequence); void BlockConnected(ChainstateRole, const std::shared_ptr &, const CBlockIndex *pindex); diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index 90aefb0018..3e0fd9b71d 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -13,7 +13,7 @@ CZMQAbstractNotifier::~CZMQAbstractNotifier() assert(!psocket); } -bool CZMQAbstractNotifier::NotifyBlock(const CBlockIndex * /*CBlockIndex*/) +bool CZMQAbstractNotifier::NotifyBlock(const std::shared_ptr& /*CBlock*/) { return true; } diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index 17fa7bbaa9..fb5962af20 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -10,6 +10,7 @@ #include #include +class CBlock; class CBlockIndex; class CTransaction; class CZMQAbstractNotifier; @@ -45,7 +46,7 @@ public: virtual void Shutdown() = 0; // Notifies of ConnectTip result, i.e., new active tip only - virtual bool NotifyBlock(const CBlockIndex *pindex); + virtual bool NotifyBlock(const std::shared_ptr& block); // Notifies of every block connection virtual bool NotifyBlockConnect(const CBlockIndex *pindex); // Notifies of every block disconnection diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 09ca54e183..e9c113ecd7 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -137,13 +137,13 @@ void TryForEachAndRemoveFailed(std::list>& } // anonymous namespace -void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) +void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block) { - if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones + if (fInitialDownload || !block || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones return; - TryForEachAndRemoveFailed(notifiers, [pindexNew](CZMQAbstractNotifier* notifier) { - return notifier->NotifyBlock(pindexNew); + TryForEachAndRemoveFailed(notifiers, [block](CZMQAbstractNotifier* notifier) { + return notifier->NotifyBlock(block); }); } diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index 4246c53bd3..b593e57387 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -35,7 +35,7 @@ protected: void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override; void BlockConnected(ChainstateRole role, const std::shared_ptr& pblock, const CBlockIndex* pindexConnected) override; void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) override; - void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; + void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block) override; private: CZMQNotificationInterface(); diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 0e05412174..807de57051 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -5,13 +5,11 @@ #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -35,10 +33,6 @@ #include #include -namespace Consensus { -struct Params; -} - static std::multimap mapPublishNotifiers; static const char *MSG_HASHBLOCK = "hashblock"; @@ -218,9 +212,9 @@ bool CZMQAbstractPublishNotifier::SendZmqMessage(const char *command, const void return true; } -bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex) +bool CZMQPublishHashBlockNotifier::NotifyBlock(const std::shared_ptr& block) { - uint256 hash = pindex->GetBlockHash(); + uint256 hash = block->GetHash(); LogPrint(BCLog::ZMQ, "Publish hashblock %s to %s\n", hash.GetHex(), this->address); uint8_t data[32]; for (unsigned int i = 0; i < 32; i++) { @@ -240,19 +234,11 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t return SendZmqMessage(MSG_HASHTX, data, 32); } -bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) +bool CZMQPublishRawBlockNotifier::NotifyBlock(const std::shared_ptr& block) { - LogPrint(BCLog::ZMQ, "Publish rawblock %s to %s\n", pindex->GetBlockHash().GetHex(), this->address); - + LogPrint(BCLog::ZMQ, "Publish rawblock %s to %s\n", block->GetHash().GetHex(), this->address); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags()); - CBlock block; - if (!m_get_block_by_index(block, *pindex)) { - LogPrint(BCLog::ZMQ, "Error: Can't read block %s from disk\n", pindex->GetBlockHash().ToString()); - return false; - } - ss << block; - return SendZmqMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size()); } diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index a5cd433761..25105c56dd 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -37,7 +37,7 @@ public: class CZMQPublishHashBlockNotifier : public CZMQAbstractPublishNotifier { public: - bool NotifyBlock(const CBlockIndex *pindex) override; + bool NotifyBlock(const std::shared_ptr& block) override; }; class CZMQPublishHashTransactionNotifier : public CZMQAbstractPublishNotifier @@ -54,7 +54,7 @@ private: public: CZMQPublishRawBlockNotifier(std::function get_block_by_index) : m_get_block_by_index{std::move(get_block_by_index)} {} - bool NotifyBlock(const CBlockIndex *pindex) override; + bool NotifyBlock(const std::shared_ptr& block) override; }; class CZMQPublishRawTransactionNotifier : public CZMQAbstractPublishNotifier From 74568a6d89c89f2e65a347d9c60bd05af8e5d93a Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Mon, 24 Oct 2022 14:42:21 -0400 Subject: [PATCH 2/6] test: check for zmq block announcements with reorgs Github-Pull: #26375 Rebased-From: 7b631dc9b1979afc99d9d1a3996492dcb415d3a3 --- test/functional/interface_zmq.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 2358dd4387..1586a98087 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -283,11 +283,17 @@ class ZMQTest (BitcoinTestFramework): assert_equal(hashtx.receive().hex(), self.nodes[1].getblock(connect_blocks[i])["tx"][0]) # If we do a simple invalidate we announce the disconnected coinbase + # and announce the previous fork tip self.nodes[0].invalidateblock(connect_blocks[1]) + assert_equal(hashblock.receive().hex(), disconnect_block) assert_equal(hashtx.receive().hex(), self.nodes[1].getblock(connect_blocks[1])["tx"][0]) # And the current tip assert_equal(hashtx.receive().hex(), self.nodes[1].getblock(connect_blocks[0])["tx"][0]) + # Reconsider block to make sure we receive the block announcements again + self.nodes[0].reconsiderblock(connect_blocks[1]) + assert_equal(hashblock.receive().hex(), connect_blocks[1]) + def test_sequence(self): """ Sequence zmq notifications give every blockhash and txhash in order From 0f52e9d35c060a0fc248efe126d7406dc2853141 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 2 Aug 2023 00:35:26 +0000 Subject: [PATCH 3/6] Only include full CBlock in UpdatedBlockTip when it will be used Avoid keeping it around (increasing memory usage) when nothing will use it --- src/init.cpp | 1 + src/test/validation_block_tests.cpp | 11 ++++++++++- src/validation.cpp | 3 ++- src/validationinterface.cpp | 2 ++ src/validationinterface.h | 3 +++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 42331d37e8..56ea537b59 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1423,6 +1423,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) }); if (g_zmq_notification_interface) { + CValidationInterface::any_use_tip_block_cache = true; RegisterValidationInterface(g_zmq_notification_interface.get()); } #endif diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index ea530a3d67..961cdc74b1 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -41,7 +41,12 @@ struct TestSubscriber final : public CValidationInterface { void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload, const std::shared_ptr& block) override { BOOST_CHECK_EQUAL(m_expected_tip, pindexNew->GetBlockHash()); - BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash()); + if (CValidationInterface::any_use_tip_block_cache) { + BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash()); + } else { + BOOST_CHECK(!block); + CValidationInterface::any_use_tip_block_cache = true; + } } void BlockConnected(ChainstateRole role, const std::shared_ptr& block, const CBlockIndex* pindex) override @@ -149,6 +154,8 @@ void MinerTestingSetup::BuildChain(const uint256& root, int height, const unsign BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) { + Assert(!CValidationInterface::any_use_tip_block_cache); + // build a large-ish chain that's likely to have some forks std::vector> blocks; while (blocks.size() < 50) { @@ -201,6 +208,8 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) UnregisterSharedValidationInterface(sub); + CValidationInterface::any_use_tip_block_cache = false; + LOCK(cs_main); BOOST_CHECK_EQUAL(sub->m_expected_tip, m_node.chainman->ActiveChain().Tip()->GetBlockHash()); } diff --git a/src/validation.cpp b/src/validation.cpp index fc9a63159a..da90ba95b0 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3252,7 +3252,8 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) { assert(trace.pblock && trace.pindex); GetMainSignals().BlockConnected(this->GetRole(), trace.pblock, trace.pindex); - if (trace.pindex == pindexNewTip) { + // Avoid keeping the CBlock around longer than we have to + if (trace.pindex == pindexNewTip && CValidationInterface::any_use_tip_block_cache) { new_tip_block = trace.pblock; } } diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index d8c18df92e..4a276a305a 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -20,6 +20,8 @@ std::string RemovalReasonToString(const MemPoolRemovalReason& r) noexcept; +bool CValidationInterface::any_use_tip_block_cache{false}; + /** * MainSignalsImpl manages a list of shared_ptr callbacks. * diff --git a/src/validationinterface.h b/src/validationinterface.h index c430d8f07e..f60852c411 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -75,6 +75,9 @@ void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main); * ValidationInterface() subscribers. */ class CValidationInterface { +public: + static bool any_use_tip_block_cache; + protected: /** * Protected destructor so that instances can only be deleted by derived classes. From 02be362ec774ffaaabcf275f59644696cc2d4cc1 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 4 Jul 2023 18:06:08 +0000 Subject: [PATCH 4/6] ZMQ: Fallback to ReadBlockFromDisk if cached CBlock is missing in UpdatedBlockTip event --- src/zmq/zmqnotificationinterface.cpp | 19 +++++++++++++++++-- src/zmq/zmqnotificationinterface.h | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index e9c113ecd7..d9e31d6287 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -69,6 +70,7 @@ std::unique_ptr CZMQNotificationInterface::Create(std { std::unique_ptr notificationInterface(new CZMQNotificationInterface()); notificationInterface->notifiers = std::move(notifiers); + notificationInterface->m_get_block_by_index = get_block_by_index; if (notificationInterface->Initialize()) { return notificationInterface; @@ -137,11 +139,24 @@ void TryForEachAndRemoveFailed(std::list>& } // anonymous namespace -void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block) +void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload, const std::shared_ptr& block_cached) { - if (fInitialDownload || !block || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones + if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones return; + std::shared_ptr block = block_cached; + if (!block) { + // This shouldn't happen, but just in case + LogPrintf("BUG! PLEASE REPORT THIS! Cached CBlock unexpectedly missing in %s\n", __func__); + + std::shared_ptr pblock = std::make_shared(); + if (!m_get_block_by_index(*pblock, *pindexNew)) { + LogPrint(BCLog::ZMQ, "Error: Can't read block %s from disk\n", pindexNew->GetBlockHash().ToString()); + return; + } + block = pblock; + } + TryForEachAndRemoveFailed(notifiers, [block](CZMQAbstractNotifier* notifier) { return notifier->NotifyBlock(block); }); diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index b593e57387..736770834a 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -42,6 +42,7 @@ private: void* pcontext{nullptr}; std::list> notifiers; + std::function m_get_block_by_index; }; extern std::unique_ptr g_zmq_notification_interface; From 7aabdde13cbb48b571669759978552f910d7bff0 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 13 Mar 2024 13:48:26 +0000 Subject: [PATCH 5/6] Ensure new_tip_block cache gets cleared when pindexNewTip is updated --- src/validation.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index da90ba95b0..0c01360c16 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3247,7 +3247,11 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr< // Wipe cache, we may need another branch now. pindexMostWork = nullptr; } - pindexNewTip = m_chain.Tip(); + auto new_tip = m_chain.Tip(); + if (pindexNewTip != new_tip) { + pindexNewTip = new_tip; + new_tip_block = nullptr; + } for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) { assert(trace.pblock && trace.pindex); From 9aa46570fafe53681b72cc5a1856a02c1ea64b3f Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 13 Mar 2024 23:09:51 +0000 Subject: [PATCH 6/6] QA: bitcoin_test/validation_block_tests: Check sanity of CBlock cache, but not behaviour/when it is present --- src/test/validation_block_tests.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 961cdc74b1..16366dd011 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -41,10 +41,9 @@ struct TestSubscriber final : public CValidationInterface { void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload, const std::shared_ptr& block) override { BOOST_CHECK_EQUAL(m_expected_tip, pindexNew->GetBlockHash()); - if (CValidationInterface::any_use_tip_block_cache) { + if (block) { BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash()); } else { - BOOST_CHECK(!block); CValidationInterface::any_use_tip_block_cache = true; } }