LCOV - code coverage report
Current view: top level - src - validationinterface.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 101 107 94.4 %
Date: 2025-02-23 09:33:43 Functions: 28 30 93.3 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       3             : // Copyright (c) 2017-2021 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #include "validationinterface.h"
       8             : 
       9             : #include "chain.h"
      10             : #include "consensus/validation.h"
      11             : #include "evo/deterministicmns.h"
      12             : #include "logging.h"
      13             : #include "scheduler.h"
      14             : #include "util/validation.h"
      15             : #include "validation.h" // cs_main
      16             : 
      17             : #include <future>
      18             : #include <list>
      19             : #include <unordered_map>
      20             : #include <boost/signals2/signal.hpp>
      21             : 
      22        5461 : struct ValidationInterfaceConnections {
      23             :     boost::signals2::scoped_connection AcceptedBlockHeader;
      24             :     boost::signals2::scoped_connection UpdatedBlockTip;
      25             :     boost::signals2::scoped_connection TransactionAddedToMempool;
      26             :     boost::signals2::scoped_connection BlockConnected;
      27             :     boost::signals2::scoped_connection BlockDisconnected;
      28             :     boost::signals2::scoped_connection TransactionRemovedFromMempool;
      29             :     boost::signals2::scoped_connection SetBestChain;
      30             :     boost::signals2::scoped_connection Broadcast;
      31             :     boost::signals2::scoped_connection BlockChecked;
      32             :     boost::signals2::scoped_connection NotifyMasternodeListChanged;
      33             : };
      34             : 
      35             : struct MainSignalsInstance {
      36             :     /** Notifies listeners of accepted block header */
      37             :     boost::signals2::signal<void(const CBlockIndex*)> AcceptedBlockHeader;
      38             :     /** Notifies listeners of updated block chain tip */
      39             :     boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
      40             :     /** Notifies listeners of a transaction having been added to mempool. */
      41             :     boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
      42             :     /**
      43             :      * Notifies listeners of a block being connected.
      44             :      * Provides a vector of transactions evicted from the mempool as a result.
      45             :      */
      46             :     boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex)> BlockConnected;
      47             :     /** Notifies listeners of a block being disconnected */
      48             :     boost::signals2::signal<void (const std::shared_ptr<const CBlock> &, const uint256& blockHash, int nBlockHeight, int64_t blockTime)> BlockDisconnected;
      49             :     /** Notifies listeners of a transaction removal from the mempool */
      50             :     boost::signals2::signal<void (const CTransactionRef &, MemPoolRemovalReason reason)> TransactionRemovedFromMempool;
      51             :     /** Notifies listeners of a new active block chain. */
      52             :     boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
      53             :     /** Tells listeners to broadcast their data. */
      54             :     boost::signals2::signal<void (CConnman* connman)> Broadcast;
      55             :     /** Notifies listeners of a block validation result */
      56             :     boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
      57             :     /** Notifies listeners of updated deterministic masternode list */
      58             :     boost::signals2::signal<void (bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff)> NotifyMasternodeListChanged;
      59             : 
      60             :     std::unordered_map<CValidationInterface*, ValidationInterfaceConnections> m_connMainSignals;
      61             : 
      62             :     // We are not allowed to assume the scheduler only runs in one thread,
      63             :     // but must ensure all callbacks happen in-order, so we end up creating
      64             :     // our own queue here :(
      65             :     SingleThreadedSchedulerClient m_schedulerClient;
      66             : 
      67         494 :     explicit MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {}
      68             : };
      69             : 
      70             : static CMainSignals g_signals;
      71             : 
      72         494 : void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) {
      73         494 :     assert(!m_internals);
      74         494 :     m_internals.reset(new MainSignalsInstance(&scheduler));
      75         494 : }
      76             : 
      77         496 : void CMainSignals::UnregisterBackgroundSignalScheduler() {
      78         496 :     m_internals.reset(nullptr);
      79         496 : }
      80             : 
      81         496 : void CMainSignals::FlushBackgroundCallbacks() {
      82         496 :     if (m_internals) {
      83         494 :         m_internals->m_schedulerClient.EmptyQueue();
      84             :     }
      85         496 : }
      86             : 
      87       45528 : size_t CMainSignals::CallbacksPending() {
      88       45528 :     if (!m_internals) return 0;
      89       45528 :     return m_internals->m_schedulerClient.CallbacksPending();
      90             : }
      91             : 
      92     2189752 : CMainSignals& GetMainSignals()
      93             : {
      94     2189752 :     return g_signals;
      95             : }
      96        5461 : void RegisterSharedValidationInterface(std::shared_ptr<CValidationInterface> pwalletIn)
      97             : {
      98             :     // Each connection captures pwalletIn to ensure that each callback is
      99             :     // executed before pwalletIn is destroyed. For more details see bitcoin #18338
     100        5461 :     ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn.get()];
     101       10922 :     conns.AcceptedBlockHeader = g_signals.m_internals->AcceptedBlockHeader.connect(std::bind(&CValidationInterface::AcceptedBlockHeader, pwalletIn, std::placeholders::_1));
     102       10922 :     conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
     103       10922 :     conns.TransactionAddedToMempool = g_signals.m_internals->TransactionAddedToMempool.connect(std::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, std::placeholders::_1));
     104       10922 :     conns.BlockConnected = g_signals.m_internals->BlockConnected.connect(std::bind(&CValidationInterface::BlockConnected, pwalletIn, std::placeholders::_1, std::placeholders::_2));
     105       10922 :     conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect(std::bind(&CValidationInterface::BlockDisconnected, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
     106       10922 :     conns.TransactionRemovedFromMempool = g_signals.m_internals->TransactionRemovedFromMempool.connect(std::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, std::placeholders::_1, std::placeholders::_2));
     107       10922 :     conns.SetBestChain = g_signals.m_internals->SetBestChain.connect(std::bind(&CValidationInterface::SetBestChain, pwalletIn, std::placeholders::_1));
     108       10922 :     conns.Broadcast = g_signals.m_internals->Broadcast.connect(std::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, std::placeholders::_1));
     109       10922 :     conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
     110       10922 :     conns.NotifyMasternodeListChanged = g_signals.m_internals->NotifyMasternodeListChanged.connect(std::bind(&CValidationInterface::NotifyMasternodeListChanged, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
     111        5461 : }
     112        1994 : void RegisterValidationInterface(CValidationInterface* pwalletIn)
     113             : {
     114             :     // Create a shared_ptr with a no-op deleter - CValidationInterface lifecycle
     115             :     // is managed by the caller.
     116        1994 :     RegisterSharedValidationInterface({pwalletIn, [](CValidationInterface*) {}});
     117        1994 : }
     118             : 
     119        4271 : void UnregisterValidationInterface(CValidationInterface* pwalletIn)
     120             : {
     121        4271 :     if (g_signals.m_internals) {
     122        4271 :         g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
     123             :     }
     124        4271 : }
     125             : 
     126        3467 : void UnregisterSharedValidationInterface(std::shared_ptr<CValidationInterface> pwalletIn)
     127             : {
     128        3467 :     UnregisterValidationInterface(pwalletIn.get());
     129        3467 : }
     130             : 
     131         496 : void UnregisterAllValidationInterfaces()
     132             : {
     133         496 :     if (!g_signals.m_internals) {
     134             :         return;
     135             :     }
     136         494 :     g_signals.m_internals->m_connMainSignals.clear();
     137             : }
     138             : 
     139      109876 : void CallFunctionInValidationInterfaceQueue(std::function<void ()> func) {
     140      109876 :     g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func));
     141      109876 : }
     142             : 
     143        3533 : void SyncWithValidationInterfaceQueue() {
     144        3533 :     AssertLockNotHeld(cs_main);
     145             :     // if queue is empty, do not wait for nothing.s
     146        3533 :     if (g_signals.CallbacksPending() == 0) return;
     147             : 
     148             :     // Block until the validation queue drains
     149        1268 :     std::promise<void> promise;
     150        1268 :     CallFunctionInValidationInterfaceQueue([&promise] {
     151        1268 :         promise.set_value();
     152             :     });
     153        3804 :     promise.get_future().wait();
     154             : }
     155             : 
     156             : // Use a macro instead of a function for conditional logging to prevent
     157             : // evaluating arguments when logging is not enabled.
     158             : //
     159             : // NOTE: The lambda captures all local variables by value.
     160             : #define ENQUEUE_AND_LOG_EVENT(event, fmt, name, ...)           \
     161             :     do {                                                       \
     162             :         auto local_name = (name);                              \
     163             :         LOG_EVENT("Enqueuing " fmt, local_name, __VA_ARGS__);  \
     164             :         m_internals->m_schedulerClient.AddToProcessQueue([=] { \
     165             :             LOG_EVENT(fmt, local_name, __VA_ARGS__);           \
     166             :             event();                                           \
     167             :         });                                                    \
     168             :     } while (0)
     169             : 
     170             : #define LOG_EVENT(fmt, ...) \
     171             :     LogPrint(BCLog::VALIDATION, fmt "\n", __VA_ARGS__)
     172             : 
     173       41186 : void CMainSignals::AcceptedBlockHeader(const CBlockIndex* pindexNew)
     174             : {
     175       82372 :     auto event = [pindexNew, this] {
     176       41186 :         m_internals->AcceptedBlockHeader(pindexNew);
     177       41186 :     };
     178      157932 :     ENQUEUE_AND_LOG_EVENT(event, "%s: new block header=%s", __func__, pindexNew->GetBlockHash().ToString());
     179       41186 : }
     180             : 
     181       41471 : void CMainSignals::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) {
     182             :     // Dependencies exist that require UpdatedBlockTip events to be delivered in the order in which
     183             :     // the chain actually updates. One way to ensure this is for the caller to invoke this signal
     184             :     // in the same critical section where the chain is updated
     185             : 
     186       82942 :     auto event = [pindexNew, pindexFork, fInitialDownload, this] {
     187       41471 :         m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
     188       41471 :     };
     189      234510 :     ENQUEUE_AND_LOG_EVENT(event, "%s: new block hash=%s, fork block hash=%s (in IBD=%s)", __func__,
     190             :                           pindexNew->GetBlockHash().ToString(),
     191             :                           pindexFork ? pindexFork->GetBlockHash().ToString() : "null",
     192             :                           fInitialDownload);
     193       41471 : }
     194             : 
     195      171129 : void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) {
     196      171129 :     auto event = [ptx, this] {
     197      171129 :         m_internals->TransactionAddedToMempool(ptx);
     198      342258 :     };
     199      855605 :     ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s", __func__, ptx->GetHash().ToString());
     200      171129 : }
     201             : 
     202        1432 : void CMainSignals::TransactionRemovedFromMempool(const CTransactionRef& ptx, MemPoolRemovalReason reason) {
     203        1432 :     auto event = [ptx, reason, this] {
     204        1432 :         m_internals->TransactionRemovedFromMempool(ptx, reason);
     205        2864 :     };
     206        7106 :     ENQUEUE_AND_LOG_EVENT(event, "%s: txid=%s", __func__, ptx->GetHash().ToString());
     207        1432 : }
     208             : 
     209       41568 : void CMainSignals::BlockConnected(const std::shared_ptr<const CBlock> &pblock, const CBlockIndex *pindex) {
     210       41568 :     auto event = [pblock, pindex, this] {
     211       41568 :         m_internals->BlockConnected(pblock, pindex);
     212       83136 :     };
     213      200864 :     ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s, block height=%d", __func__,
     214             :                           pblock->GetHash().ToString(), pindex->nHeight);
     215       41568 : }
     216             : 
     217         329 : void CMainSignals::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock, const uint256& blockHash, int nBlockHeight, int64_t blockTime) {
     218         658 :     auto event = [pblock, blockHash, nBlockHeight, blockTime, this] {
     219         329 :         m_internals->BlockDisconnected(pblock, blockHash, nBlockHeight, blockTime);
     220         658 :     };
     221        2618 :     ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s, block height=%d, block time=%d", __func__,
     222             :                           blockHash.ToString(), nBlockHeight, blockTime);
     223         329 : }
     224             : 
     225           0 : void CMainSignals::SetBestChain(const CBlockLocator& locator) {
     226           0 :     auto event = [locator, this] {
     227           0 :         m_internals->SetBestChain(locator);
     228           0 :     };
     229           0 :     ENQUEUE_AND_LOG_EVENT(event, "%s: block hash=%s", __func__,
     230             :                           locator.IsNull() ? "null" : locator.vHave.front().ToString());
     231           0 : }
     232             : 
     233     1789460 : void CMainSignals::Broadcast(CConnman* connman) {
     234     1789460 :     m_internals->Broadcast(connman);
     235     1789460 : }
     236             : 
     237       52445 : void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
     238       52445 :     m_internals->BlockChecked(block, state);
     239       90633 :     LOG_EVENT("%s: block hash=%s (state=%s)", __func__,
     240             :               block.GetHash().ToString(), FormatStateMessage(state));
     241       52445 : }
     242             : 
     243        7251 : void CMainSignals::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) {
     244        7251 :     m_internals->NotifyMasternodeListChanged(undo, oldMNList, diff);
     245       14332 :     LOG_EVENT("%s: (undo=%d) old list for=%s, added=%d, updated=%d, removed=%d", __func__,
     246             :               undo,
     247             :               oldMNList.GetBlockHash().ToString(),
     248             :               diff.addedMNs.size(),
     249             :               diff.updatedMNs.size(),
     250             :               diff.removedMns.size());
     251        7251 : }

Generated by: LCOV version 1.14