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.
This commit is contained in:
Ryan Ofsky 2022-01-13 07:55:18 -05:00
parent 8d4a058ac4
commit a0b5b4ae5a
8 changed files with 94 additions and 21 deletions

View file

@ -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 \

View file

@ -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) {}
};

26
src/kernel/chain.cpp Normal file
View file

@ -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 <chain.h>
#include <interfaces/chain.h>
#include <sync.h>
#include <uint256.h>
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

19
src/kernel/chain.h Normal file
View file

@ -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

View file

@ -19,6 +19,7 @@
#include <netaddress.h>
#include <netbase.h>
#include <node/blockstorage.h>
#include <kernel/chain.h>
#include <node/coin.h>
#include <node/context.h>
#include <node/transaction.h>
@ -426,11 +427,11 @@ public:
}
void BlockConnected(const std::shared_ptr<const CBlock>& 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<const CBlock>& 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
{

View file

@ -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 = &block;
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 = &block;
a.wallet->blockDisconnected(info);
b.wallet->blockDisconnected(info);
chain.pop_back();
});
auto& [coins, first_block]{chain.front()};

View file

@ -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<int>(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<int>(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{});
}
}

View file

@ -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);