refactor: De-globalize g_signals

This commit is contained in:
TheCharlatan committed 2024-02-15 14:37:01 +01:00
1 parent 473dd4b97a
commit 84f5c135b8
30 files changed
+131 -154

No files matched your search

+2 -1
View File
@@ -39,7 +39,8 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
generatetoaddress(test_setup->m_node, address_mine.value_or(ADDRESS_WATCHONLY)); generatetoaddress(test_setup->m_node, address_mine.value_or(ADDRESS_WATCHONLY));
generatetoaddress(test_setup->m_node, ADDRESS_WATCHONLY); generatetoaddress(test_setup->m_node, ADDRESS_WATCHONLY);
} }
SyncWithValidationInterfaceQueue(); // Calls SyncWithValidationInterfaceQueue
wallet.chain().waitForNotificationsIfTipChanged(uint256::ZERO);
auto bal = GetBalance(wallet); // Cache auto bal = GetBalance(wallet); // Cache
+8 -6
View File
@@ -74,10 +74,12 @@ int main(int argc, char* argv[])
// Start the lightweight task scheduler thread // Start the lightweight task scheduler thread
scheduler.m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { scheduler.serviceQueue(); }); scheduler.m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { scheduler.serviceQueue(); });
CMainSignals validation_signals{};
// Gather some entropy once per minute. // Gather some entropy once per minute.
scheduler.scheduleEvery(RandAddPeriodic, std::chrono::minutes{1}); scheduler.scheduleEvery(RandAddPeriodic, std::chrono::minutes{1});
GetMainSignals().RegisterBackgroundSignalScheduler(scheduler); validation_signals.RegisterBackgroundSignalScheduler(scheduler);
class KernelNotifications : public kernel::Notifications class KernelNotifications : public kernel::Notifications
{ {
@@ -118,7 +120,7 @@ int main(int argc, char* argv[])
.chainparams = *chainparams, .chainparams = *chainparams,
.datadir = abs_datadir, .datadir = abs_datadir,
.notifications = *notifications, .notifications = *notifications,
.signals = &GetMainSignals(), .signals = &validation_signals,
}; };
const node::BlockManager::Options blockman_opts{ const node::BlockManager::Options blockman_opts{
.chainparams = chainman_opts.chainparams, .chainparams = chainman_opts.chainparams,
@@ -236,9 +238,9 @@ int main(int argc, char* argv[])
bool new_block; bool new_block;
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash()); auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
RegisterSharedValidationInterface(sc); validation_signals.RegisterSharedValidationInterface(sc);
bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block); bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
UnregisterSharedValidationInterface(sc); validation_signals.UnregisterSharedValidationInterface(sc);
if (!new_block && accepted) { if (!new_block && accepted) {
std::cerr << "duplicate" << std::endl; std::cerr << "duplicate" << std::endl;
break; break;
@@ -291,7 +293,7 @@ epilogue:
scheduler.stop(); scheduler.stop();
if (chainman.m_thread_load.joinable()) chainman.m_thread_load.join(); if (chainman.m_thread_load.joinable()) chainman.m_thread_load.join();
GetMainSignals().FlushBackgroundCallbacks(); validation_signals.FlushBackgroundCallbacks();
{ {
LOCK(cs_main); LOCK(cs_main);
for (Chainstate* chainstate : chainman.GetAll()) { for (Chainstate* chainstate : chainman.GetAll()) {
@@ -301,5 +303,5 @@ epilogue:
} }
} }
} }
GetMainSignals().UnregisterBackgroundSignalScheduler(); validation_signals.UnregisterBackgroundSignalScheduler();
} }
+5 -3
View File
@@ -89,7 +89,7 @@ bool BaseIndex::Init()
return &m_chain->context()->chainman->GetChainstateForIndexing()); return &m_chain->context()->chainman->GetChainstateForIndexing());
// Register to validation interface before setting the 'm_synced' flag, so that // Register to validation interface before setting the 'm_synced' flag, so that
// callbacks are not missed once m_synced is true. // callbacks are not missed once m_synced is true.
RegisterValidationInterface(this); m_chain->context()->validation_signals->RegisterValidationInterface(this);
CBlockLocator locator; CBlockLocator locator;
if (!GetDB().ReadBestBlock(locator)) { if (!GetDB().ReadBestBlock(locator)) {
@@ -380,7 +380,7 @@ bool BaseIndex::BlockUntilSyncedToCurrentChain() const
} }
LogPrintf("%s: %s is catching up on block notifications\n", __func__, GetName()); LogPrintf("%s: %s is catching up on block notifications\n", __func__, GetName());
SyncWithValidationInterfaceQueue(); m_chain->context()->validation_signals->SyncWithValidationInterfaceQueue();
return true; return true;
} }
@@ -399,7 +399,9 @@ bool BaseIndex::StartBackgroundSync()
void BaseIndex::Stop() void BaseIndex::Stop()
{ {
UnregisterValidationInterface(this); if (m_chain->context()->validation_signals) {
m_chain->context()->validation_signals->UnregisterValidationInterface(this);
}
if (m_thread_sync.joinable()) { if (m_thread_sync.joinable()) {
m_thread_sync.join(); m_thread_sync.join();
+21 -13
View File
@@ -291,7 +291,7 @@ void Shutdown(NodeContext& node)
// Because these depend on each-other, we make sure that neither can be // Because these depend on each-other, we make sure that neither can be
// using the other before destroying them. // using the other before destroying them.
if (node.peerman) UnregisterValidationInterface(node.peerman.get()); if (node.peerman && node.validation_signals) node.validation_signals->UnregisterValidationInterface(node.peerman.get());
if (node.connman) node.connman->Stop(); if (node.connman) node.connman->Stop();
StopTorControl(); StopTorControl();
@@ -317,7 +317,9 @@ void Shutdown(NodeContext& node)
// fee estimator from validation interface. // fee estimator from validation interface.
if (node.fee_estimator) { if (node.fee_estimator) {
node.fee_estimator->Flush(); node.fee_estimator->Flush();
UnregisterValidationInterface(node.fee_estimator.get()); if (node.validation_signals) {
node.validation_signals->UnregisterValidationInterface(node.fee_estimator.get());
}
} }
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
@@ -332,7 +334,7 @@ void Shutdown(NodeContext& node)
// After there are no more peers/RPC left to give us new data which may generate // After there are no more peers/RPC left to give us new data which may generate
// CValidationInterface callbacks, flush them... // CValidationInterface callbacks, flush them...
GetMainSignals().FlushBackgroundCallbacks(); if (node.validation_signals) node.validation_signals->FlushBackgroundCallbacks();
// Stop and delete all indexes only after flushing background callbacks. // Stop and delete all indexes only after flushing background callbacks.
if (g_txindex) { if (g_txindex) {
@@ -367,17 +369,20 @@ void Shutdown(NodeContext& node)
#if ENABLE_ZMQ #if ENABLE_ZMQ
if (g_zmq_notification_interface) { if (g_zmq_notification_interface) {
UnregisterValidationInterface(g_zmq_notification_interface.get()); if (node.validation_signals) node.validation_signals->UnregisterValidationInterface(g_zmq_notification_interface.get());
g_zmq_notification_interface.reset(); g_zmq_notification_interface.reset();
} }
#endif #endif
node.chain_clients.clear(); node.chain_clients.clear();
UnregisterAllValidationInterfaces(); if (node.validation_signals) {
GetMainSignals().UnregisterBackgroundSignalScheduler(); node.validation_signals->UnregisterAllValidationInterfaces();
node.validation_signals->UnregisterBackgroundSignalScheduler();
}
node.mempool.reset(); node.mempool.reset();
node.fee_estimator.reset(); node.fee_estimator.reset();
node.chainman.reset(); node.chainman.reset();
node.validation_signals.reset();
node.scheduler.reset(); node.scheduler.reset();
node.kernel.reset(); node.kernel.reset();
@@ -1158,7 +1163,10 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
} }
}, std::chrono::minutes{5}); }, std::chrono::minutes{5});
GetMainSignals().RegisterBackgroundSignalScheduler(*node.scheduler); assert(!node.validation_signals);
node.validation_signals = std::make_unique<CMainSignals>();
auto& validation_signals = *node.validation_signals;
validation_signals.RegisterBackgroundSignalScheduler(*node.scheduler);
// Create client interfaces for wallets that are supposed to be loaded // Create client interfaces for wallets that are supposed to be loaded
// according to -wallet and -disablewallet options. This only constructs // according to -wallet and -disablewallet options. This only constructs
@@ -1264,7 +1272,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// Flush estimates to disk periodically // Flush estimates to disk periodically
CBlockPolicyEstimator* fee_estimator = node.fee_estimator.get(); CBlockPolicyEstimator* fee_estimator = node.fee_estimator.get();
node.scheduler->scheduleEvery([fee_estimator] { fee_estimator->FlushFeeEstimates(); }, FEE_FLUSH_INTERVAL); node.scheduler->scheduleEvery([fee_estimator] { fee_estimator->FlushFeeEstimates(); }, FEE_FLUSH_INTERVAL);
RegisterValidationInterface(fee_estimator); validation_signals.RegisterValidationInterface(fee_estimator);
} }
// Check port numbers // Check port numbers
@@ -1435,7 +1443,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}); });
if (g_zmq_notification_interface) { if (g_zmq_notification_interface) {
RegisterValidationInterface(g_zmq_notification_interface.get()); validation_signals.RegisterValidationInterface(g_zmq_notification_interface.get());
} }
#endif #endif
@@ -1449,7 +1457,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
.chainparams = chainparams, .chainparams = chainparams,
.datadir = args.GetDataDirNet(), .datadir = args.GetDataDirNet(),
.notifications = *node.notifications, .notifications = *node.notifications,
.signals = &GetMainSignals(), .signals = &validation_signals,
}; };
Assert(ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction Assert(ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction
@@ -1479,7 +1487,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
CTxMemPool::Options mempool_opts{ CTxMemPool::Options mempool_opts{
.check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0, .check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
.signals = &GetMainSignals(), .signals = &validation_signals,
}; };
auto result{ApplyArgsManOptions(args, chainparams, mempool_opts)}; auto result{ApplyArgsManOptions(args, chainparams, mempool_opts)};
if (!result) { if (!result) {
@@ -1507,7 +1515,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// Drain the validation interface queue to ensure that the old indexes // Drain the validation interface queue to ensure that the old indexes
// don't have any pending work. // don't have any pending work.
SyncWithValidationInterfaceQueue(); Assert(node.validation_signals)->SyncWithValidationInterfaceQueue();
for (auto* index : node.indexes) { for (auto* index : node.indexes) {
index->Interrupt(); index->Interrupt();
@@ -1596,7 +1604,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
node.peerman = PeerManager::make(*node.connman, *node.addrman, node.peerman = PeerManager::make(*node.connman, *node.addrman,
node.banman.get(), chainman, node.banman.get(), chainman,
*node.mempool, peerman_opts); *node.mempool, peerman_opts);
RegisterValidationInterface(node.peerman.get()); validation_signals.RegisterValidationInterface(node.peerman.get());
// ********************************************************* Step 8: start indexers // ********************************************************* Step 8: start indexers
+4
View File
@@ -20,6 +20,7 @@ class BanMan;
class BaseIndex; class BaseIndex;
class CBlockPolicyEstimator; class CBlockPolicyEstimator;
class CConnman; class CConnman;
class CMainSignals;
class CScheduler; class CScheduler;
class CTxMemPool; class CTxMemPool;
class ChainstateManager; class ChainstateManager;
@@ -70,7 +71,10 @@ struct NodeContext {
interfaces::WalletLoader* wallet_loader{nullptr}; interfaces::WalletLoader* wallet_loader{nullptr};
std::unique_ptr<CScheduler> scheduler; std::unique_ptr<CScheduler> scheduler;
std::function<void()> rpc_interruption_point = [] {}; std::function<void()> rpc_interruption_point = [] {};
//! Issues blocking calls about sync status, errors and warnings
std::unique_ptr<KernelNotifications> notifications; std::unique_ptr<KernelNotifications> notifications;
//! Issues calls about blocks and transactions
std::unique_ptr<CMainSignals> validation_signals;
std::atomic<int> exit_status{EXIT_SUCCESS}; std::atomic<int> exit_status{EXIT_SUCCESS};
//! Declare default constructor and destructor that are not inline, so code //! Declare default constructor and destructor that are not inline, so code
+8 -6
View File
@@ -460,19 +460,20 @@ public:
class NotificationsHandlerImpl : public Handler class NotificationsHandlerImpl : public Handler
{ {
public: public:
explicit NotificationsHandlerImpl(std::shared_ptr<Chain::Notifications> notifications) explicit NotificationsHandlerImpl(CMainSignals& signals, std::shared_ptr<Chain::Notifications> notifications)
: m_proxy(std::make_shared<NotificationsProxy>(std::move(notifications))) : m_signals{signals}, m_proxy{std::make_shared<NotificationsProxy>(std::move(notifications))}
{ {
RegisterSharedValidationInterface(m_proxy); m_signals.RegisterSharedValidationInterface(m_proxy);
} }
~NotificationsHandlerImpl() override { disconnect(); } ~NotificationsHandlerImpl() override { disconnect(); }
void disconnect() override void disconnect() override
{ {
if (m_proxy) { if (m_proxy) {
UnregisterSharedValidationInterface(m_proxy); m_signals.UnregisterSharedValidationInterface(m_proxy);
m_proxy.reset(); m_proxy.reset();
} }
} }
CMainSignals& m_signals;
std::shared_ptr<NotificationsProxy> m_proxy; std::shared_ptr<NotificationsProxy> m_proxy;
}; };
@@ -761,12 +762,12 @@ public:
} }
std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) override std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) override
{ {
return std::make_unique<NotificationsHandlerImpl>(std::move(notifications)); return std::make_unique<NotificationsHandlerImpl>(validation_signals(), std::move(notifications));
} }
void waitForNotificationsIfTipChanged(const uint256& old_tip) override void waitForNotificationsIfTipChanged(const uint256& old_tip) override
{ {
if (!old_tip.IsNull() && old_tip == WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()->GetBlockHash())) return; if (!old_tip.IsNull() && old_tip == WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()->GetBlockHash())) return;
SyncWithValidationInterfaceQueue(); validation_signals().SyncWithValidationInterfaceQueue();
} }
std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
{ {
@@ -822,6 +823,7 @@ public:
NodeContext* context() override { return &m_node; } NodeContext* context() override { return &m_node; }
ArgsManager& args() { return *Assert(m_node.args); } ArgsManager& args() { return *Assert(m_node.args); }
ChainstateManager& chainman() { return *Assert(m_node.chainman); } ChainstateManager& chainman() { return *Assert(m_node.chainman); }
CMainSignals& validation_signals() { return *Assert(m_node.validation_signals); }
NodeContext& m_node; NodeContext& m_node;
}; };
} // namespace } // namespace
+2 -2
View File
@@ -92,7 +92,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
node.mempool->AddUnbroadcastTx(txid); node.mempool->AddUnbroadcastTx(txid);
} }
if (wait_callback) { if (wait_callback && node.validation_signals) {
// For transactions broadcast from outside the wallet, make sure // For transactions broadcast from outside the wallet, make sure
// that the wallet has been notified of the transaction before // that the wallet has been notified of the transaction before
// continuing. // continuing.
@@ -101,7 +101,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
// with a transaction to/from their wallet, immediately call some // with a transaction to/from their wallet, immediately call some
// wallet RPC, and get a stale result because callbacks have not // wallet RPC, and get a stale result because callbacks have not
// yet been processed. // yet been processed.
CallFunctionInValidationInterfaceQueue([&promise] { node.validation_signals->CallFunctionInValidationInterfaceQueue([&promise] {
promise.set_value(); promise.set_value();
}); });
callback_set = true; callback_set = true;
+2 -1
View File
@@ -395,7 +395,8 @@ static RPCHelpMan syncwithvalidationinterfacequeue()
}, },
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
SyncWithValidationInterfaceQueue(); NodeContext& node = EnsureAnyNodeContext(request.context);
CHECK_NONFATAL(node.validation_signals)->SyncWithValidationInterfaceQueue();
return UniValue::VNULL; return UniValue::VNULL;
}, },
}; };
+4 -6
View File
@@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <core_io.h> #include <core_io.h>
#include <node/context.h>
#include <policy/feerate.h> #include <policy/feerate.h>
#include <policy/fees.h> #include <policy/fees.h>
#include <rpc/protocol.h> #include <rpc/protocol.h>
@@ -21,10 +22,6 @@
#include <cmath> #include <cmath>
#include <string> #include <string>
namespace node {
struct NodeContext;
}
using node::NodeContext; using node::NodeContext;
static RPCHelpMan estimatesmartfee() static RPCHelpMan estimatesmartfee()
@@ -68,7 +65,7 @@ static RPCHelpMan estimatesmartfee()
const NodeContext& node = EnsureAnyNodeContext(request.context); const NodeContext& node = EnsureAnyNodeContext(request.context);
const CTxMemPool& mempool = EnsureMemPool(node); const CTxMemPool& mempool = EnsureMemPool(node);
SyncWithValidationInterfaceQueue(); CHECK_NONFATAL(mempool.m_signals)->SyncWithValidationInterfaceQueue();
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target); unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
bool conservative = true; bool conservative = true;
@@ -156,8 +153,9 @@ static RPCHelpMan estimaterawfee()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{ {
CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context); CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
const NodeContext& node = EnsureAnyNodeContext(request.context);
SyncWithValidationInterfaceQueue(); CHECK_NONFATAL(node.validation_signals)->SyncWithValidationInterfaceQueue();
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE); unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target); unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
double threshold = 0.95; double threshold = 0.95;
+2 -2
View File
@@ -1038,9 +1038,9 @@ static RPCHelpMan submitblock()
bool new_block; bool new_block;
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash()); auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
RegisterSharedValidationInterface(sc); CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block); bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
UnregisterSharedValidationInterface(sc); CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
if (!new_block && accepted) { if (!new_block && accepted) {
return "duplicate"; return "duplicate";
} }
+1 -1
View File
@@ -90,7 +90,7 @@ static RPCHelpMan mockscheduler()
const NodeContext& node_context{EnsureAnyNodeContext(request.context)}; const NodeContext& node_context{EnsureAnyNodeContext(request.context)};
CHECK_NONFATAL(node_context.scheduler)->MockForward(std::chrono::seconds{delta_seconds}); CHECK_NONFATAL(node_context.scheduler)->MockForward(std::chrono::seconds{delta_seconds});
SyncWithValidationInterfaceQueue(); CHECK_NONFATAL(node_context.validation_signals)->SyncWithValidationInterfaceQueue();
for (const auto& chain_client : node_context.chain_clients) { for (const auto& chain_client : node_context.chain_clients) {
chain_client->schedulerMockForward(std::chrono::seconds(delta_seconds)); chain_client->schedulerMockForward(std::chrono::seconds(delta_seconds));
} }
+1 -1
View File
@@ -70,7 +70,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
// SyncWithValidationInterfaceQueue() call below is also needed to ensure // SyncWithValidationInterfaceQueue() call below is also needed to ensure
// TSAN always sees the test thread waiting for the notification thread, and // TSAN always sees the test thread waiting for the notification thread, and
// avoid potential false positive reports. // avoid potential false positive reports.
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
// Shutdown sequence (c.f. Shutdown() in init.cpp) // Shutdown sequence (c.f. Shutdown() in init.cpp)
coin_stats_index.Stop(); coin_stats_index.Stop();
+6 -6
View File
@@ -47,7 +47,7 @@ void initialize_tx_pool()
g_outpoints_coinbase_init_mature.push_back(prevout); g_outpoints_coinbase_init_mature.push_back(prevout);
} }
} }
SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }
struct OutpointsUpdater final : public CValidationInterface { struct OutpointsUpdater final : public CValidationInterface {
@@ -147,7 +147,7 @@ FUZZ_TARGET(tx_package_eval, .init = initialize_tx_pool)
} }
auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints); auto outpoints_updater = std::make_shared<OutpointsUpdater>(mempool_outpoints);
RegisterSharedValidationInterface(outpoints_updater); node.validation_signals->RegisterSharedValidationInterface(outpoints_updater);
CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)}; CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_); MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
@@ -269,7 +269,7 @@ FUZZ_TARGET(tx_package_eval, .init = initialize_tx_pool)
// Remember all added transactions // Remember all added transactions
std::set<CTransactionRef> added; std::set<CTransactionRef> added;
auto txr = std::make_shared<TransactionsDelta>(added); auto txr = std::make_shared<TransactionsDelta>(added);
RegisterSharedValidationInterface(txr); node.validation_signals->RegisterSharedValidationInterface(txr);
// When there are multiple transactions in the package, we call ProcessNewPackage(txs, test_accept=false) // When there are multiple transactions in the package, we call ProcessNewPackage(txs, test_accept=false)
// and AcceptToMemoryPool(txs.back(), test_accept=true). When there is only 1 transaction, we might flip it // and AcceptToMemoryPool(txs.back(), test_accept=true). When there is only 1 transaction, we might flip it
@@ -285,8 +285,8 @@ FUZZ_TARGET(tx_package_eval, .init = initialize_tx_pool)
/*bypass_limits=*/false, /*test_accept=*/!single_submit)); /*bypass_limits=*/false, /*test_accept=*/!single_submit));
const bool passed = res.m_result_type == MempoolAcceptResult::ResultType::VALID; const bool passed = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
SyncWithValidationInterfaceQueue(); node.validation_signals->SyncWithValidationInterfaceQueue();
UnregisterSharedValidationInterface(txr); node.validation_signals->UnregisterSharedValidationInterface(txr);
// There is only 1 transaction in the package. We did a test-package-accept and a ATMP // There is only 1 transaction in the package. We did a test-package-accept and a ATMP
if (single_submit) { if (single_submit) {
@@ -310,7 +310,7 @@ FUZZ_TARGET(tx_package_eval, .init = initialize_tx_pool)
CheckMempoolV3Invariants(tx_pool); CheckMempoolV3Invariants(tx_pool);
} }
UnregisterSharedValidationInterface(outpoints_updater); node.validation_signals->UnregisterSharedValidationInterface(outpoints_updater);
WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1)); WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
} }
+2 -2
View File
@@ -47,7 +47,7 @@ void initialize_process_message()
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) { for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
MineBlock(g_setup->m_node, CScript() << OP_TRUE); MineBlock(g_setup->m_node, CScript() << OP_TRUE);
} }
SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }
FUZZ_TARGET(process_message, .init = initialize_process_message) FUZZ_TARGET(process_message, .init = initialize_process_message)
@@ -89,6 +89,6 @@ FUZZ_TARGET(process_message, .init = initialize_process_message)
} }
g_setup->m_node.peerman->SendMessages(&p2p_node); g_setup->m_node.peerman->SendMessages(&p2p_node);
} }
SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
g_setup->m_node.connman->StopNodes(); g_setup->m_node.connman->StopNodes();
} }
+2 -2
View File
@@ -37,7 +37,7 @@ void initialize_process_messages()
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) { for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
MineBlock(g_setup->m_node, CScript() << OP_TRUE); MineBlock(g_setup->m_node, CScript() << OP_TRUE);
} }
SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }
FUZZ_TARGET(process_messages, .init = initialize_process_messages) FUZZ_TARGET(process_messages, .init = initialize_process_messages)
@@ -89,6 +89,6 @@ FUZZ_TARGET(process_messages, .init = initialize_process_messages)
g_setup->m_node.peerman->SendMessages(&random_node); g_setup->m_node.peerman->SendMessages(&random_node);
} }
} }
SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
g_setup->m_node.connman->StopNodes(); g_setup->m_node.connman->StopNodes();
} }
+5 -5
View File
@@ -50,7 +50,7 @@ void initialize_tx_pool()
g_outpoints_coinbase_init_immature; g_outpoints_coinbase_init_immature;
outpoints.push_back(prevout); outpoints.push_back(prevout);
} }
SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }
struct TransactionsDelta final : public CValidationInterface { struct TransactionsDelta final : public CValidationInterface {
@@ -105,7 +105,7 @@ void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, Cha
assert(tx_pool.size() < info_all.size()); assert(tx_pool.size() < info_all.size());
WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1)); WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
} }
SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }
void MockTime(FuzzedDataProvider& fuzzed_data_provider, const Chainstate& chainstate) void MockTime(FuzzedDataProvider& fuzzed_data_provider, const Chainstate& chainstate)
@@ -285,7 +285,7 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
std::set<CTransactionRef> removed; std::set<CTransactionRef> removed;
std::set<CTransactionRef> added; std::set<CTransactionRef> added;
auto txr = std::make_shared<TransactionsDelta>(removed, added); auto txr = std::make_shared<TransactionsDelta>(removed, added);
RegisterSharedValidationInterface(txr); node.validation_signals->RegisterSharedValidationInterface(txr);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool(); const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
// Make sure ProcessNewPackage on one transaction works. // Make sure ProcessNewPackage on one transaction works.
@@ -303,8 +303,8 @@ FUZZ_TARGET(tx_pool_standard, .init = initialize_tx_pool)
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false)); const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID; const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
SyncWithValidationInterfaceQueue(); node.validation_signals->SyncWithValidationInterfaceQueue();
UnregisterSharedValidationInterface(txr); node.validation_signals->UnregisterSharedValidationInterface(txr);
bool txid_in_mempool = tx_pool.exists(GenTxid::Txid(tx->GetHash())); bool txid_in_mempool = tx_pool.exists(GenTxid::Txid(tx->GetHash()));
bool wtxid_in_mempool = tx_pool.exists(GenTxid::Wtxid(tx->GetWitnessHash())); bool wtxid_in_mempool = tx_pool.exists(GenTxid::Wtxid(tx->GetWitnessHash()));
+2 -2
View File
@@ -25,7 +25,7 @@ static void mineBlock(const node::NodeContext& node, std::chrono::seconds block_
block.fChecked = true; // little speedup block.fChecked = true; // little speedup
SetMockTime(curr_time); // process block at current time SetMockTime(curr_time); // process block at current time
Assert(node.chainman->ProcessNewBlock(std::make_shared<const CBlock>(block), /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)); Assert(node.chainman->ProcessNewBlock(std::make_shared<const CBlock>(block), /*force_processing=*/true, /*min_pow_checked=*/true, nullptr));
SyncWithValidationInterfaceQueue(); // drain events queue node.validation_signals->SyncWithValidationInterfaceQueue(); // drain events queue
} }
// Verifying when network-limited peer connections are desirable based on the node's proximity to the tip // Verifying when network-limited peer connections are desirable based on the node's proximity to the tip
@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(connections_desirable_service_flags)
// By now, we tested that the connections desirable services flags change based on the node's time proximity to the tip. // By now, we tested that the connections desirable services flags change based on the node's time proximity to the tip.
// Now, perform the same tests for when the node receives a block. // Now, perform the same tests for when the node receives a block.
RegisterValidationInterface(peerman.get()); m_node.validation_signals->RegisterValidationInterface(peerman.get());
// First, verify a block in the past doesn't enable limited peers connections // First, verify a block in the past doesn't enable limited peers connections
// At this point, our time is (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1) * 10 minutes ahead the tip's time. // At this point, our time is (NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS + 1) * 10 minutes ahead the tip's time.
+10 -10
View File
@@ -20,7 +20,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
{ {
CBlockPolicyEstimator& feeEst = *Assert(m_node.fee_estimator); CBlockPolicyEstimator& feeEst = *Assert(m_node.fee_estimator);
CTxMemPool& mpool = *Assert(m_node.mempool); CTxMemPool& mpool = *Assert(m_node.mempool);
RegisterValidationInterface(&feeEst); m_node.validation_signals->RegisterValidationInterface(&feeEst);
TestMemPoolEntryHelper entry; TestMemPoolEntryHelper entry;
CAmount basefee(2000); CAmount basefee(2000);
CAmount deltaFee(100); CAmount deltaFee(100);
@@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
/*submitted_in_package=*/false, /*submitted_in_package=*/false,
/*chainstate_is_current=*/true, /*chainstate_is_current=*/true,
/*has_no_mempool_parents=*/true)}; /*has_no_mempool_parents=*/true)};
GetMainSignals().TransactionAddedToMempool(tx_info, mpool.GetAndIncrementSequence()); m_node.validation_signals->TransactionAddedToMempool(tx_info, mpool.GetAndIncrementSequence());
} }
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
txHashes[j].push_back(hash); txHashes[j].push_back(hash);
@@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
// Check after just a few txs that combining buckets works as expected // Check after just a few txs that combining buckets works as expected
if (blocknum == 3) { if (blocknum == 3) {
// Wait for fee estimator to catch up // Wait for fee estimator to catch up
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
// At this point we should need to combine 3 buckets to get enough data points // At this point we should need to combine 3 buckets to get enough data points
// So estimateFee(1) should fail and estimateFee(2) should return somewhere around // So estimateFee(1) should fail and estimateFee(2) should return somewhere around
// 9*baserate. estimateFee(2) %'s are 100,100,90 = average 97% // 9*baserate. estimateFee(2) %'s are 100,100,90 = average 97%
@@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
} }
// Wait for fee estimator to catch up // Wait for fee estimator to catch up
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
std::vector<CAmount> origFeeEst; std::vector<CAmount> origFeeEst;
// Highest feerate is 10*baseRate and gets in all blocks, // Highest feerate is 10*baseRate and gets in all blocks,
@@ -146,7 +146,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
} }
// Wait for fee estimator to catch up // Wait for fee estimator to catch up
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0)); BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
for (int i = 2; i < 10;i++) { for (int i = 2; i < 10;i++) {
@@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
/*submitted_in_package=*/false, /*submitted_in_package=*/false,
/*chainstate_is_current=*/true, /*chainstate_is_current=*/true,
/*has_no_mempool_parents=*/true)}; /*has_no_mempool_parents=*/true)};
GetMainSignals().TransactionAddedToMempool(tx_info, mpool.GetAndIncrementSequence()); m_node.validation_signals->TransactionAddedToMempool(tx_info, mpool.GetAndIncrementSequence());
} }
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
txHashes[j].push_back(hash); txHashes[j].push_back(hash);
@@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
} }
// Wait for fee estimator to catch up // Wait for fee estimator to catch up
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
for (int i = 1; i < 10;i++) { for (int i = 1; i < 10;i++) {
BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
@@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
block.clear(); block.clear();
// Wait for fee estimator to catch up // Wait for fee estimator to catch up
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0)); BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
for (int i = 2; i < 10;i++) { for (int i = 2; i < 10;i++) {
@@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
/*submitted_in_package=*/false, /*submitted_in_package=*/false,
/*chainstate_is_current=*/true, /*chainstate_is_current=*/true,
/*has_no_mempool_parents=*/true)}; /*has_no_mempool_parents=*/true)};
GetMainSignals().TransactionAddedToMempool(tx_info, mpool.GetAndIncrementSequence()); m_node.validation_signals->TransactionAddedToMempool(tx_info, mpool.GetAndIncrementSequence());
} }
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
CTransactionRef ptx = mpool.get(hash); CTransactionRef ptx = mpool.get(hash);
@@ -257,7 +257,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
block.clear(); block.clear();
} }
// Wait for fee estimator to catch up // Wait for fee estimator to catch up
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0)); BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
for (int i = 2; i < 9; i++) { // At 9, the original estimate was already at the bottom (b/c scale = 2) for (int i = 2; i < 9; i++) { // At 9, the original estimate was already at the bottom (b/c scale = 2)
BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee); BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee);
+1 -1
View File
@@ -71,7 +71,7 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
// SyncWithValidationInterfaceQueue() call below is also needed to ensure // SyncWithValidationInterfaceQueue() call below is also needed to ensure
// TSAN always sees the test thread waiting for the notification thread, and // TSAN always sees the test thread waiting for the notification thread, and
// avoid potential false positive reports. // avoid potential false positive reports.
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
// shutdown sequence (c.f. Shutdown() in init.cpp) // shutdown sequence (c.f. Shutdown() in init.cpp)
txindex.Stop(); txindex.Stop();
+3 -3
View File
@@ -95,12 +95,12 @@ COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block)
const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()); const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight());
bool new_block; bool new_block;
BlockValidationStateCatcher bvsc{block->GetHash()}; BlockValidationStateCatcher bvsc{block->GetHash()};
RegisterValidationInterface(&bvsc); node.validation_signals->RegisterValidationInterface(&bvsc);
const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)}; const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)};
const bool duplicate{!new_block && processed}; const bool duplicate{!new_block && processed};
assert(!duplicate); assert(!duplicate);
UnregisterValidationInterface(&bvsc); node.validation_signals->UnregisterValidationInterface(&bvsc);
SyncWithValidationInterfaceQueue(); node.validation_signals->SyncWithValidationInterfaceQueue();
const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()}; const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()};
assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight())); assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()));
+6 -4
View File
@@ -171,7 +171,8 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, const std::vecto
// from blocking due to queue overrun. // from blocking due to queue overrun.
m_node.scheduler = std::make_unique<CScheduler>(); m_node.scheduler = std::make_unique<CScheduler>();
m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); }); m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); });
GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler); m_node.validation_signals = std::make_unique<CMainSignals>();
m_node.validation_signals->RegisterBackgroundSignalScheduler(*m_node.scheduler);
m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES); m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES);
m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(m_node)); m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(m_node));
@@ -185,7 +186,7 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, const std::vecto
.datadir = m_args.GetDataDirNet(), .datadir = m_args.GetDataDirNet(),
.check_block_index = true, .check_block_index = true,
.notifications = *m_node.notifications, .notifications = *m_node.notifications,
.signals = &GetMainSignals(), .signals = m_node.validation_signals.get(),
.worker_threads_num = 2, .worker_threads_num = 2,
}; };
const BlockManager::Options blockman_opts{ const BlockManager::Options blockman_opts{
@@ -203,8 +204,8 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, const std::vecto
ChainTestingSetup::~ChainTestingSetup() ChainTestingSetup::~ChainTestingSetup()
{ {
if (m_node.scheduler) m_node.scheduler->stop(); if (m_node.scheduler) m_node.scheduler->stop();
GetMainSignals().FlushBackgroundCallbacks(); m_node.validation_signals->FlushBackgroundCallbacks();
GetMainSignals().UnregisterBackgroundSignalScheduler(); m_node.validation_signals->UnregisterBackgroundSignalScheduler();
m_node.connman.reset(); m_node.connman.reset();
m_node.banman.reset(); m_node.banman.reset();
m_node.addrman.reset(); m_node.addrman.reset();
@@ -213,6 +214,7 @@ ChainTestingSetup::~ChainTestingSetup()
m_node.mempool.reset(); m_node.mempool.reset();
m_node.fee_estimator.reset(); m_node.fee_estimator.reset();
m_node.chainman.reset(); m_node.chainman.reset();
m_node.validation_signals.reset();
m_node.scheduler.reset(); m_node.scheduler.reset();
} }
+1 -2
View File
@@ -13,7 +13,6 @@
#include <util/time.h> #include <util/time.h>
#include <util/translation.h> #include <util/translation.h>
#include <validation.h> #include <validation.h>
#include <validationinterface.h>
using node::NodeContext; using node::NodeContext;
@@ -23,7 +22,7 @@ CTxMemPool::Options MemPoolOptionsForTest(const NodeContext& node)
// Default to always checking mempool regardless of // Default to always checking mempool regardless of
// chainparams.DefaultConsistencyChecks for tests // chainparams.DefaultConsistencyChecks for tests
.check_ratio = 1, .check_ratio = 1,
.signals = &GetMainSignals(), .signals = node.validation_signals.get(),
}; };
const auto result{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)}; const auto result{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)};
Assert(result); Assert(result);
+4 -4
View File
@@ -158,7 +158,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
bool ignored; bool ignored;
// Connect the genesis block and drain any outstanding events // Connect the genesis block and drain any outstanding events
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(std::make_shared<CBlock>(Params().GenesisBlock()), true, true, &ignored)); BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(std::make_shared<CBlock>(Params().GenesisBlock()), true, true, &ignored));
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
// subscribe to events (this subscriber will validate event ordering) // subscribe to events (this subscriber will validate event ordering)
const CBlockIndex* initial_tip = nullptr; const CBlockIndex* initial_tip = nullptr;
@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
initial_tip = m_node.chainman->ActiveChain().Tip(); initial_tip = m_node.chainman->ActiveChain().Tip();
} }
auto sub = std::make_shared<TestSubscriber>(initial_tip->GetBlockHash()); auto sub = std::make_shared<TestSubscriber>(initial_tip->GetBlockHash());
RegisterSharedValidationInterface(sub); m_node.validation_signals->RegisterSharedValidationInterface(sub);
// create a bunch of threads that repeatedly process a block generated above at random // create a bunch of threads that repeatedly process a block generated above at random
// this will create parallelism and randomness inside validation - the ValidationInterface // this will create parallelism and randomness inside validation - the ValidationInterface
@@ -196,9 +196,9 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
for (auto& t : threads) { for (auto& t : threads) {
t.join(); t.join();
} }
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
UnregisterSharedValidationInterface(sub); m_node.validation_signals->UnregisterSharedValidationInterface(sub);
LOCK(cs_main); LOCK(cs_main);
BOOST_CHECK_EQUAL(sub->m_expected_tip, m_node.chainman->ActiveChain().Tip()->GetBlockHash()); BOOST_CHECK_EQUAL(sub->m_expected_tip, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
@@ -102,7 +102,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager, TestChain100Setup)
BOOST_CHECK_EQUAL(active_tip2, c2.m_chain.Tip()); BOOST_CHECK_EQUAL(active_tip2, c2.m_chain.Tip());
// Let scheduler events finish running to avoid accessing memory that is going to be unloaded // Let scheduler events finish running to avoid accessing memory that is going to be unloaded
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }
//! Test rebalancing the caches associated with each chainstate. //! Test rebalancing the caches associated with each chainstate.
@@ -374,7 +374,7 @@ struct SnapshotTestSetup : TestChain100Setup {
cs->ForceFlushStateToDisk(); cs->ForceFlushStateToDisk();
} }
// Process all callbacks referring to the old manager before wiping it. // Process all callbacks referring to the old manager before wiping it.
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
LOCK(::cs_main); LOCK(::cs_main);
chainman.ResetChainstates(); chainman.ResetChainstates();
BOOST_CHECK_EQUAL(chainman.GetAll().size(), 0); BOOST_CHECK_EQUAL(chainman.GetAll().size(), 0);
@@ -383,7 +383,7 @@ struct SnapshotTestSetup : TestChain100Setup {
.chainparams = ::Params(), .chainparams = ::Params(),
.datadir = chainman.m_options.datadir, .datadir = chainman.m_options.datadir,
.notifications = *m_node.notifications, .notifications = *m_node.notifications,
.signals = &GetMainSignals(), .signals = m_node.validation_signals.get(),
}; };
const BlockManager::Options blockman_opts{ const BlockManager::Options blockman_opts{
.chainparams = chainman_opts.chainparams, .chainparams = chainman_opts.chainparams,
+19 -12
View File
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
const CBlock block_dummy; const CBlock block_dummy;
BlockValidationState state_dummy; BlockValidationState state_dummy;
while (generate) { while (generate) {
GetMainSignals().BlockChecked(block_dummy, state_dummy); m_node.validation_signals->BlockChecked(block_dummy, state_dummy);
} }
}}; }};
@@ -37,8 +37,8 @@ BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
// keep going for about 1 sec, which is 250k iterations // keep going for about 1 sec, which is 250k iterations
for (int i = 0; i < 250000; i++) { for (int i = 0; i < 250000; i++) {
auto sub = std::make_shared<TestSubscriberNoop>(); auto sub = std::make_shared<TestSubscriberNoop>();
RegisterSharedValidationInterface(sub); m_node.validation_signals->RegisterSharedValidationInterface(sub);
UnregisterSharedValidationInterface(sub); m_node.validation_signals->UnregisterSharedValidationInterface(sub);
} }
// tell the other thread we are done // tell the other thread we are done
generate = false; generate = false;
@@ -52,8 +52,8 @@ BOOST_AUTO_TEST_CASE(unregister_validation_interface_race)
class TestInterface : public CValidationInterface class TestInterface : public CValidationInterface
{ {
public: public:
TestInterface(std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr) TestInterface(CMainSignals& signals, std::function<void()> on_call = nullptr, std::function<void()> on_destroy = nullptr)
: m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy)) : m_on_call(std::move(on_call)), m_on_destroy(std::move(on_destroy)), m_signals{signals}
{ {
} }
virtual ~TestInterface() virtual ~TestInterface()
@@ -64,14 +64,15 @@ public:
{ {
if (m_on_call) m_on_call(); if (m_on_call) m_on_call();
} }
static void Call() void Call()
{ {
CBlock block; CBlock block;
BlockValidationState state; BlockValidationState state;
GetMainSignals().BlockChecked(block, state); m_signals.BlockChecked(block, state);
} }
std::function<void()> m_on_call; std::function<void()> m_on_call;
std::function<void()> m_on_destroy; std::function<void()> m_on_destroy;
CMainSignals& m_signals;
}; };
// Regression test to ensure UnregisterAllValidationInterfaces calls don't // Regression test to ensure UnregisterAllValidationInterfaces calls don't
@@ -80,17 +81,23 @@ public:
BOOST_AUTO_TEST_CASE(unregister_all_during_call) BOOST_AUTO_TEST_CASE(unregister_all_during_call)
{ {
bool destroyed = false; bool destroyed = false;
RegisterSharedValidationInterface(std::make_shared<TestInterface>( auto shared{std::make_shared<TestInterface>(
*m_node.validation_signals,
[&] { [&] {
// First call should decrements reference count 2 -> 1 // First call should decrements reference count 2 -> 1
UnregisterAllValidationInterfaces(); m_node.validation_signals->UnregisterAllValidationInterfaces();
BOOST_CHECK(!destroyed); BOOST_CHECK(!destroyed);
// Second call should not decrement reference count 1 -> 0 // Second call should not decrement reference count 1 -> 0
UnregisterAllValidationInterfaces(); m_node.validation_signals->UnregisterAllValidationInterfaces();
BOOST_CHECK(!destroyed); BOOST_CHECK(!destroyed);
}, },
[&] { destroyed = true; })); [&] { destroyed = true; })};
TestInterface::Call(); m_node.validation_signals->RegisterSharedValidationInterface(shared);
BOOST_CHECK(shared.use_count() == 2);
shared->Call();
BOOST_CHECK(shared.use_count() == 1);
BOOST_CHECK(!destroyed);
shared.reset();
BOOST_CHECK(destroyed); BOOST_CHECK(destroyed);
} }
+1 -1
View File
@@ -3217,7 +3217,7 @@ static void LimitValidationInterfaceQueue(CMainSignals& signals) LOCKS_EXCLUDED(
AssertLockNotHeld(cs_main); AssertLockNotHeld(cs_main);
if (signals.CallbacksPending() > 10) { if (signals.CallbacksPending() > 10) {
SyncWithValidationInterfaceQueue(); signals.SyncWithValidationInterfaceQueue();
} }
} }
-37
View File
@@ -94,8 +94,6 @@ public:
} }
}; };
static CMainSignals g_signals;
CMainSignals::CMainSignals() {} CMainSignals::CMainSignals() {}
CMainSignals::~CMainSignals() {} CMainSignals::~CMainSignals() {}
@@ -124,11 +122,6 @@ size_t CMainSignals::CallbacksPending()
return m_internals->m_schedulerClient.CallbacksPending(); return m_internals->m_schedulerClient.CallbacksPending();
} }
CMainSignals& GetMainSignals()
{
return g_signals;
}
void CMainSignals::RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks) void CMainSignals::RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
{ {
// Each connection captures the shared_ptr to ensure that each callback is // Each connection captures the shared_ptr to ensure that each callback is
@@ -277,33 +270,3 @@ void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared
LOG_EVENT("%s: block hash=%s", __func__, block->GetHash().ToString()); LOG_EVENT("%s: block hash=%s", __func__, block->GetHash().ToString());
m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NewPoWValidBlock(pindex, block); }); m_internals->Iterate([&](CValidationInterface& callbacks) { callbacks.NewPoWValidBlock(pindex, block); });
} }
// These functions are temporary and will be removed in the following commit
void RegisterValidationInterface(CValidationInterface* callbacks)
{
GetMainSignals().RegisterValidationInterface(callbacks);
}
void UnregisterValidationInterface(CValidationInterface* callbacks)
{
GetMainSignals().UnregisterValidationInterface(callbacks);
}
void UnregisterAllValidationInterfaces()
{
GetMainSignals().UnregisterAllValidationInterfaces();
}
void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
{
GetMainSignals().RegisterSharedValidationInterface(callbacks);
}
void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks)
{
GetMainSignals().UnregisterSharedValidationInterface(callbacks);
}
void CallFunctionInValidationInterfaceQueue(std::function<void ()> func)
{
GetMainSignals().CallFunctionInValidationInterfaceQueue(func);
}
void SyncWithValidationInterfaceQueue()
{
GetMainSignals().SyncWithValidationInterfaceQueue();
}
-13
View File
@@ -21,22 +21,11 @@ class BlockValidationState;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
struct CBlockLocator; struct CBlockLocator;
class CValidationInterface;
class CScheduler; class CScheduler;
enum class MemPoolRemovalReason; enum class MemPoolRemovalReason;
struct RemovedMempoolTransactionInfo; struct RemovedMempoolTransactionInfo;
struct NewMempoolTransactionInfo; struct NewMempoolTransactionInfo;
void RegisterValidationInterface(CValidationInterface* callbacks);
void UnregisterValidationInterface(CValidationInterface* callbacks);
void UnregisterAllValidationInterfaces();
void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> callbacks);
void CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main);
/** /**
* Implement this to subscribe to events generated in validation and mempool * Implement this to subscribe to events generated in validation and mempool
* *
@@ -232,6 +221,4 @@ public:
void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&); void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&);
}; };
CMainSignals& GetMainSignals();
#endif // BITCOIN_VALIDATIONINTERFACE_H #endif // BITCOIN_VALIDATIONINTERFACE_H
+2 -1
View File
@@ -71,7 +71,8 @@ std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet) void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
{ {
SyncWithValidationInterfaceQueue(); // Calls SyncWithValidationInterfaceQueue
wallet->chain().waitForNotificationsIfTipChanged({});
wallet->m_chain_notifications_handler.reset(); wallet->m_chain_notifications_handler.reset();
UnloadWallet(std::move(wallet)); UnloadWallet(std::move(wallet));
} }
+4 -4
View File
@@ -812,7 +812,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
// transactionAddedToMempool notifications, and create block and mempool // transactionAddedToMempool notifications, and create block and mempool
// transactions paying to the wallet // transactions paying to the wallet
std::promise<void> promise; std::promise<void> promise;
CallFunctionInValidationInterfaceQueue([&promise] { m_node.validation_signals->CallFunctionInValidationInterfaceQueue([&promise] {
promise.get_future().wait(); promise.get_future().wait();
}); });
std::string error; std::string error;
@@ -840,7 +840,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
// Unblock notification queue and make sure stale blockConnected and // Unblock notification queue and make sure stale blockConnected and
// transactionAddedToMempool events are processed // transactionAddedToMempool events are processed
promise.set_value(); promise.set_value();
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
// AddToWallet events for block_tx and mempool_tx events are counted a // AddToWallet events for block_tx and mempool_tx events are counted a
// second time as the notification queue is processed // second time as the notification queue is processed
BOOST_CHECK_EQUAL(addtx_count, 5); BOOST_CHECK_EQUAL(addtx_count, 5);
@@ -863,7 +863,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey())); mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error)); BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
}); });
wallet = TestLoadWallet(context); wallet = TestLoadWallet(context);
// Since mempool transactions are requested at the end of loading, there will // Since mempool transactions are requested at the end of loading, there will
@@ -903,7 +903,7 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey())); auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
SyncWithValidationInterfaceQueue(); m_node.validation_signals->SyncWithValidationInterfaceQueue();
{ {
auto block_hash = block_tx.GetHash(); auto block_hash = block_tx.GetHash();