From a0b5b4ae5a24536d333cbce2ea584f2d935c651f Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Thu, 13 Jan 2022 07:55:18 -0500 Subject: interfaces, refactor: Add more block information to block connected notifications Add new interfaces::BlockInfo struct to be able to pass extra block information (file and undo information) to indexes which they are updated to use high level interfaces::Chain notifications. This commit does not change behavior in any way. --- src/Makefile.am | 2 ++ src/interfaces/chain.h | 18 ++++++++++++++++-- src/kernel/chain.cpp | 26 ++++++++++++++++++++++++++ src/kernel/chain.h | 19 +++++++++++++++++++ src/node/interfaces.cpp | 5 +++-- src/wallet/test/fuzz/notifications.cpp | 18 ++++++++++++++---- src/wallet/wallet.cpp | 23 ++++++++++++----------- src/wallet/wallet.h | 4 ++-- 8 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 src/kernel/chain.cpp create mode 100644 src/kernel/chain.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 02ec5c098e..87c7a056b1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -171,6 +171,7 @@ BITCOIN_CORE_H = \ interfaces/ipc.h \ interfaces/node.h \ interfaces/wallet.h \ + kernel/chain.h \ kernel/chainstatemanager_opts.h \ kernel/checks.h \ kernel/coinstats.h \ @@ -365,6 +366,7 @@ libbitcoin_node_a_SOURCES = \ index/coinstatsindex.cpp \ index/txindex.cpp \ init.cpp \ + kernel/chain.cpp \ kernel/checks.cpp \ kernel/coinstats.cpp \ kernel/context.cpp \ diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index ff994b8edc..6396d0d359 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -18,6 +18,7 @@ class ArgsManager; class CBlock; +class CBlockUndo; class CFeeRate; class CRPCCommand; class CScheduler; @@ -67,6 +68,19 @@ public: mutable bool found = false; }; +//! Block data sent with blockConnected, blockDisconnected notifications. +struct BlockInfo { + const uint256& hash; + const uint256* prev_hash = nullptr; + int height = -1; + int file_number = -1; + unsigned data_pos = 0; + const CBlock* data = nullptr; + const CBlockUndo* undo_data = nullptr; + + BlockInfo(const uint256& hash LIFETIMEBOUND) : hash(hash) {} +}; + //! Interface giving clients (wallet processes, maybe other analysis tools in //! the future) ability to access to the chain state, receive notifications, //! estimate fees, and submit transactions. @@ -239,8 +253,8 @@ public: virtual ~Notifications() {} virtual void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) {} virtual void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {} - virtual void blockConnected(const CBlock& block, int height) {} - virtual void blockDisconnected(const CBlock& block, int height) {} + virtual void blockConnected(const BlockInfo& block) {} + virtual void blockDisconnected(const BlockInfo& block) {} virtual void updatedBlockTip() {} virtual void chainStateFlushed(const CBlockLocator& locator) {} }; diff --git a/src/kernel/chain.cpp b/src/kernel/chain.cpp new file mode 100644 index 0000000000..82e77125d7 --- /dev/null +++ b/src/kernel/chain.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include + +class CBlock; + +namespace kernel { +interfaces::BlockInfo MakeBlockInfo(const CBlockIndex* index, const CBlock* data) +{ + interfaces::BlockInfo info{index ? *index->phashBlock : uint256::ZERO}; + if (index) { + info.prev_hash = index->pprev ? index->pprev->phashBlock : nullptr; + info.height = index->nHeight; + LOCK(::cs_main); + info.file_number = index->nFile; + info.data_pos = index->nDataPos; + } + info.data = data; + return info; +} +} // namespace kernel diff --git a/src/kernel/chain.h b/src/kernel/chain.h new file mode 100644 index 0000000000..f0750f8266 --- /dev/null +++ b/src/kernel/chain.h @@ -0,0 +1,19 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_CHAIN_H +#define BITCOIN_KERNEL_CHAIN_H + +class CBlock; +class CBlockIndex; +namespace interfaces { +struct BlockInfo; +} // namespace interfaces + +namespace kernel { +//! Return data from block index. +interfaces::BlockInfo MakeBlockInfo(const CBlockIndex* block_index, const CBlock* data = nullptr); +} // namespace kernel + +#endif // BITCOIN_KERNEL_CHAIN_H diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 46e0efb9b6..2562d81e48 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -426,11 +427,11 @@ public: } void BlockConnected(const std::shared_ptr& block, const CBlockIndex* index) override { - m_notifications->blockConnected(*block, index->nHeight); + m_notifications->blockConnected(kernel::MakeBlockInfo(index, block.get())); } void BlockDisconnected(const std::shared_ptr& block, const CBlockIndex* index) override { - m_notifications->blockDisconnected(*block, index->nHeight); + m_notifications->blockDisconnected(kernel::MakeBlockInfo(index, block.get())); } void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override { diff --git a/src/wallet/test/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp index 816bef6148..5c173773e4 100644 --- a/src/wallet/test/fuzz/notifications.cpp +++ b/src/wallet/test/fuzz/notifications.cpp @@ -137,8 +137,13 @@ FUZZ_TARGET_INIT(wallet_notifications, initialize_setup) block.vtx.emplace_back(MakeTransactionRef(tx)); } // Mine block - a.wallet->blockConnected(block, chain.size()); - b.wallet->blockConnected(block, chain.size()); + const uint256& hash = block.GetHash(); + interfaces::BlockInfo info{hash}; + info.prev_hash = &block.hashPrevBlock; + info.height = chain.size(); + info.data = █ + a.wallet->blockConnected(info); + b.wallet->blockConnected(info); // Store the coins for the next block Coins coins_new; for (const auto& tx : block.vtx) { @@ -154,8 +159,13 @@ FUZZ_TARGET_INIT(wallet_notifications, initialize_setup) auto& [coins, block]{chain.back()}; if (block.vtx.empty()) return; // Can only disconnect if the block was submitted first // Disconnect block - a.wallet->blockDisconnected(block, chain.size() - 1); - b.wallet->blockDisconnected(block, chain.size() - 1); + const uint256& hash = block.GetHash(); + interfaces::BlockInfo info{hash}; + info.prev_hash = &block.hashPrevBlock; + info.height = chain.size() - 1; + info.data = █ + a.wallet->blockDisconnected(info); + b.wallet->blockDisconnected(info); chain.pop_back(); }); auto& [coins, first_block]{chain.front()}; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 890e171913..c8d6ccd48b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1314,30 +1314,31 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe } } -void CWallet::blockConnected(const CBlock& block, int height) +void CWallet::blockConnected(const interfaces::BlockInfo& block) { - const uint256& block_hash = block.GetHash(); + assert(block.data); LOCK(cs_wallet); - m_last_block_processed_height = height; - m_last_block_processed = block_hash; - for (size_t index = 0; index < block.vtx.size(); index++) { - SyncTransaction(block.vtx[index], TxStateConfirmed{block_hash, height, static_cast(index)}); - transactionRemovedFromMempool(block.vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */); + m_last_block_processed_height = block.height; + m_last_block_processed = block.hash; + for (size_t index = 0; index < block.data->vtx.size(); index++) { + SyncTransaction(block.data->vtx[index], TxStateConfirmed{block.hash, block.height, static_cast(index)}); + transactionRemovedFromMempool(block.data->vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */); } } -void CWallet::blockDisconnected(const CBlock& block, int height) +void CWallet::blockDisconnected(const interfaces::BlockInfo& block) { + assert(block.data); LOCK(cs_wallet); // At block disconnection, this will change an abandoned transaction to // be unconfirmed, whether or not the transaction is added back to the mempool. // User may have to call abandontransaction again. It may be addressed in the // future with a stickier abandoned state or even removing abandontransaction call. - m_last_block_processed_height = height - 1; - m_last_block_processed = block.hashPrevBlock; - for (const CTransactionRef& ptx : block.vtx) { + m_last_block_processed_height = block.height - 1; + m_last_block_processed = *Assert(block.prev_hash); + for (const CTransactionRef& ptx : Assert(block.data)->vtx) { SyncTransaction(ptx, TxStateInactive{}); } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index e2c3d76438..15f5917040 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -508,8 +508,8 @@ public: CWalletTx* AddToWallet(CTransactionRef tx, const TxState& state, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block = false); bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override; - void blockConnected(const CBlock& block, int height) override; - void blockDisconnected(const CBlock& block, int height) override; + void blockConnected(const interfaces::BlockInfo& block) override; + void blockDisconnected(const interfaces::BlockInfo& block) override; void updatedBlockTip() override; int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update); -- cgit v1.2.3