From 422677963a7b41e340b911b4cd53d29dd8d63f21 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Thu, 18 Apr 2019 08:21:35 -0400 Subject: [PATCH] refactor: replace isPotentialtip/waitForNotifications by higher method Add GUARDED_BY(cs_wallet) annotation to m_last_block_processed, given that its now guarded by cs_wallet instead of cs_main --- src/interfaces/chain.cpp | 17 ++++++++++------- src/interfaces/chain.h | 17 ++++------------- src/wallet/wallet.cpp | 20 ++++---------------- src/wallet/wallet.h | 2 +- 4 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index b61a51b235..ed0c3925f9 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -136,12 +136,6 @@ class LockImpl : public Chain::Lock } return nullopt; } - bool isPotentialTip(const uint256& hash) override - { - if (::chainActive.Tip()->GetBlockHash() == hash) return true; - CBlockIndex* block = LookupBlockIndex(hash); - return block && block->GetAncestor(::chainActive.Height()) == ::chainActive.Tip(); - } CBlockLocator getTipLocator() override { return ::chainActive.GetLocator(); } Optional findLocatorFork(const CBlockLocator& locator) override { @@ -358,7 +352,16 @@ public: { return MakeUnique(*this, notifications); } - void waitForNotifications() override { SyncWithValidationInterfaceQueue(); } + void waitForNotificationsIfNewBlocksConnected(const uint256& old_tip) override + { + if (!old_tip.IsNull()) { + LOCK(::cs_main); + if (old_tip == ::chainActive.Tip()->GetBlockHash()) return; + CBlockIndex* block = LookupBlockIndex(old_tip); + if (block && block->GetAncestor(::chainActive.Height()) == ::chainActive.Tip()) return; + } + SyncWithValidationInterfaceQueue(); + } std::unique_ptr handleRpc(const CRPCCommand& command) override { return MakeUnique(command); diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 17d7b6d8f1..9f975cb92f 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -43,12 +43,6 @@ class Wallet; //! asynchronously //! (https://github.com/bitcoin/bitcoin/pull/10973#issuecomment-380101269). //! -//! * The isPotentialTip() and waitForNotifications() methods are too low-level -//! and should be replaced with a higher level -//! waitForNotificationsUpTo(block_hash) method that the wallet can call -//! instead -//! (https://github.com/bitcoin/bitcoin/pull/10973#discussion_r266995234). -//! //! * The relayTransactions() and submitToMemoryPool() methods could be replaced //! with a higher-level broadcastTransaction method //! (https://github.com/bitcoin/bitcoin/pull/14978#issuecomment-459373984). @@ -132,11 +126,6 @@ public: //! information is desired). virtual Optional findFork(const uint256& hash, Optional* height) = 0; - //! Return true if block hash points to the current chain tip, or to a - //! possible descendant of the current chain tip that isn't currently - //! connected. - virtual bool isPotentialTip(const uint256& hash) = 0; - //! Get locator for the current chain tip. virtual CBlockLocator getTipLocator() = 0; @@ -271,8 +260,10 @@ public: //! Register handler for notifications. virtual std::unique_ptr handleNotifications(Notifications& notifications) = 0; - //! Wait for pending notifications to be handled. - virtual void waitForNotifications() = 0; + //! Wait for pending notifications to be processed unless block hash points to the current + //! chain tip, or to a possible descendant of the current chain tip that isn't currently + //! connected. + virtual void waitForNotificationsIfNewBlocksConnected(const uint256& old_tip) = 0; //! Register handler for RPC. Command is not copied, so reference //! needs to remain valid until Handler is disconnected. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4737e2f6f4..1ff02a129c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1288,24 +1288,12 @@ void CWallet::UpdatedBlockTip() void CWallet::BlockUntilSyncedToCurrentChain() { AssertLockNotHeld(cs_wallet); - - { - // Skip the queue-draining stuff if we know we're caught up with - // chainActive.Tip()... - // We could also take cs_wallet here, and call m_last_block_processed - // protected by cs_wallet instead of cs_main, but as long as we need - // cs_main here anyway, it's easier to just call it cs_main-protected. - auto locked_chain = chain().lock(); - - if (!m_last_block_processed.IsNull() && locked_chain->isPotentialTip(m_last_block_processed)) { - return; - } - } - - // ...otherwise put a callback in the validation interface queue and wait + // Skip the queue-draining stuff if we know we're caught up with + // chainActive.Tip(), otherwise put a callback in the validation interface queue and wait // for the queue to drain enough to execute it (indicating we are caught up // at least with the time we entered this function). - chain().waitForNotifications(); + uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed); + chain().waitForNotificationsIfNewBlocksConnected(last_block_hash); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 62ba0aa962..0d751a6d15 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -720,7 +720,7 @@ private: * to have seen all transactions in the chain, but is only used to track * live BlockConnected callbacks. */ - uint256 m_last_block_processed; + uint256 m_last_block_processed GUARDED_BY(cs_wallet); public: /*