LCOV - code coverage report
Current view: top level - src/node - interfaces.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 386 526 73.4 %
Date: 2022-04-21 14:51:19 Functions: 104 134 77.6 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 100 176 56.8 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2018-2021 The Bitcoin Core developers
#       2                 :            : // Distributed under the MIT software license, see the accompanying
#       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       4                 :            : 
#       5                 :            : #include <addrdb.h>
#       6                 :            : #include <banman.h>
#       7                 :            : #include <chain.h>
#       8                 :            : #include <chainparams.h>
#       9                 :            : #include <deploymentstatus.h>
#      10                 :            : #include <external_signer.h>
#      11                 :            : #include <init.h>
#      12                 :            : #include <interfaces/chain.h>
#      13                 :            : #include <interfaces/handler.h>
#      14                 :            : #include <interfaces/node.h>
#      15                 :            : #include <interfaces/wallet.h>
#      16                 :            : #include <mapport.h>
#      17                 :            : #include <net.h>
#      18                 :            : #include <net_processing.h>
#      19                 :            : #include <netaddress.h>
#      20                 :            : #include <netbase.h>
#      21                 :            : #include <node/blockstorage.h>
#      22                 :            : #include <node/coin.h>
#      23                 :            : #include <node/context.h>
#      24                 :            : #include <node/transaction.h>
#      25                 :            : #include <node/ui_interface.h>
#      26                 :            : #include <policy/feerate.h>
#      27                 :            : #include <policy/fees.h>
#      28                 :            : #include <policy/policy.h>
#      29                 :            : #include <policy/rbf.h>
#      30                 :            : #include <policy/settings.h>
#      31                 :            : #include <primitives/block.h>
#      32                 :            : #include <primitives/transaction.h>
#      33                 :            : #include <rpc/protocol.h>
#      34                 :            : #include <rpc/server.h>
#      35                 :            : #include <shutdown.h>
#      36                 :            : #include <support/allocators/secure.h>
#      37                 :            : #include <sync.h>
#      38                 :            : #include <timedata.h>
#      39                 :            : #include <txmempool.h>
#      40                 :            : #include <uint256.h>
#      41                 :            : #include <univalue.h>
#      42                 :            : #include <util/check.h>
#      43                 :            : #include <util/system.h>
#      44                 :            : #include <util/translation.h>
#      45                 :            : #include <validation.h>
#      46                 :            : #include <validationinterface.h>
#      47                 :            : #include <warnings.h>
#      48                 :            : 
#      49                 :            : #if defined(HAVE_CONFIG_H)
#      50                 :            : #include <config/bitcoin-config.h>
#      51                 :            : #endif
#      52                 :            : 
#      53                 :            : #include <any>
#      54                 :            : #include <memory>
#      55                 :            : #include <optional>
#      56                 :            : #include <utility>
#      57                 :            : 
#      58                 :            : #include <boost/signals2/signal.hpp>
#      59                 :            : 
#      60                 :            : using interfaces::BlockTip;
#      61                 :            : using interfaces::Chain;
#      62                 :            : using interfaces::FoundBlock;
#      63                 :            : using interfaces::Handler;
#      64                 :            : using interfaces::MakeHandler;
#      65                 :            : using interfaces::Node;
#      66                 :            : using interfaces::WalletLoader;
#      67                 :            : 
#      68                 :            : namespace node {
#      69                 :            : namespace {
#      70                 :            : #ifdef ENABLE_EXTERNAL_SIGNER
#      71                 :            : class ExternalSignerImpl : public interfaces::ExternalSigner
#      72                 :            : {
#      73                 :            : public:
#      74                 :          0 :     ExternalSignerImpl(::ExternalSigner signer) : m_signer(std::move(signer)) {}
#      75                 :          0 :     std::string getName() override { return m_signer.m_name; }
#      76                 :            : private:
#      77                 :            :     ::ExternalSigner m_signer;
#      78                 :            : };
#      79                 :            : #endif
#      80                 :            : 
#      81                 :            : class NodeImpl : public Node
#      82                 :            : {
#      83                 :            : private:
#      84                 :          1 :     ChainstateManager& chainman() { return *Assert(m_context->chainman); }
#      85                 :            : public:
#      86                 :          1 :     explicit NodeImpl(NodeContext& context) { setContext(&context); }
#      87                 :          0 :     void initLogging() override { InitLogging(*Assert(m_context->args)); }
#      88                 :          6 :     void initParameterInteraction() override { InitParameterInteraction(*Assert(m_context->args)); }
#      89                 :          0 :     bilingual_str getWarnings() override { return GetWarnings(true); }
#      90                 :          0 :     uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); }
#      91                 :            :     bool baseInitialize() override
#      92                 :          1 :     {
#      93 [ +  - ][ +  - ]:          1 :         return AppInitBasicSetup(gArgs) && AppInitParameterInteraction(gArgs, /*use_syscall_sandbox=*/false) && AppInitSanityChecks() &&
#                 [ +  - ]
#      94 [ +  - ][ +  - ]:          1 :                AppInitLockDataDirectory() && AppInitInterfaces(*m_context);
#      95                 :          1 :     }
#      96                 :            :     bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override
#      97                 :          1 :     {
#      98                 :          1 :         return AppInitMain(*m_context, tip_info);
#      99                 :          1 :     }
#     100                 :            :     void appShutdown() override
#     101                 :          1 :     {
#     102                 :          1 :         Interrupt(*m_context);
#     103                 :          1 :         Shutdown(*m_context);
#     104                 :          1 :     }
#     105                 :            :     void startShutdown() override
#     106                 :          1 :     {
#     107                 :          1 :         StartShutdown();
#     108                 :            :         // Stop RPC for clean shutdown if any of waitfor* commands is executed.
#     109         [ -  + ]:          1 :         if (gArgs.GetBoolArg("-server", false)) {
#     110                 :          0 :             InterruptRPC();
#     111                 :          0 :             StopRPC();
#     112                 :          0 :         }
#     113                 :          1 :     }
#     114                 :          0 :     bool shutdownRequested() override { return ShutdownRequested(); }
#     115                 :            :     bool isSettingIgnored(const std::string& name) override
#     116                 :         72 :     {
#     117                 :         72 :         bool ignored = false;
#     118                 :         72 :         gArgs.LockSettings([&](util::Settings& settings) {
#     119         [ -  + ]:         72 :             if (auto* options = util::FindKey(settings.command_line_options, name)) {
#     120                 :          0 :                 ignored = !options->empty();
#     121                 :          0 :             }
#     122                 :         72 :         });
#     123                 :         72 :         return ignored;
#     124                 :         72 :     }
#     125                 :        120 :     util::SettingsValue getPersistentSetting(const std::string& name) override { return gArgs.GetPersistentSetting(name); }
#     126                 :            :     void updateSetting(const std::string& name, const util::SettingsValue& value) override
#     127                 :          7 :     {
#     128                 :          7 :         gArgs.LockSettings([&](util::Settings& settings) {
#     129         [ -  + ]:          7 :             if (value.isNull()) {
#     130                 :          0 :                 settings.rw_settings.erase(name);
#     131                 :          7 :             } else {
#     132                 :          7 :                 settings.rw_settings[name] = value;
#     133                 :          7 :             }
#     134                 :          7 :         });
#     135                 :          7 :         gArgs.WriteSettingsFile();
#     136                 :          7 :     }
#     137                 :            :     void forceSetting(const std::string& name, const util::SettingsValue& value) override
#     138                 :          0 :     {
#     139                 :          0 :         gArgs.LockSettings([&](util::Settings& settings) {
#     140         [ #  # ]:          0 :             if (value.isNull()) {
#     141                 :          0 :                 settings.forced_settings.erase(name);
#     142                 :          0 :             } else {
#     143                 :          0 :                 settings.forced_settings[name] = value;
#     144                 :          0 :             }
#     145                 :          0 :         });
#     146                 :          0 :     }
#     147                 :          0 :     void mapPort(bool use_upnp, bool use_natpmp) override { StartMapPort(use_upnp, use_natpmp); }
#     148                 :          1 :     bool getProxy(Network net, Proxy& proxy_info) override { return GetProxy(net, proxy_info); }
#     149                 :            :     size_t getNodeCount(ConnectionDirection flags) override
#     150                 :          9 :     {
#     151         [ +  - ]:          9 :         return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0;
#     152                 :          9 :     }
#     153                 :            :     bool getNodesStats(NodesStats& stats) override
#     154                 :          3 :     {
#     155                 :          3 :         stats.clear();
#     156                 :            : 
#     157         [ +  - ]:          3 :         if (m_context->connman) {
#     158                 :          3 :             std::vector<CNodeStats> stats_temp;
#     159                 :          3 :             m_context->connman->GetNodeStats(stats_temp);
#     160                 :            : 
#     161                 :          3 :             stats.reserve(stats_temp.size());
#     162         [ -  + ]:          3 :             for (auto& node_stats_temp : stats_temp) {
#     163                 :          0 :                 stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats());
#     164                 :          0 :             }
#     165                 :            : 
#     166                 :            :             // Try to retrieve the CNodeStateStats for each node.
#     167         [ +  - ]:          3 :             if (m_context->peerman) {
#     168                 :          3 :                 TRY_LOCK(::cs_main, lockMain);
#     169         [ +  - ]:          3 :                 if (lockMain) {
#     170         [ -  + ]:          3 :                     for (auto& node_stats : stats) {
#     171                 :          0 :                         std::get<1>(node_stats) =
#     172                 :          0 :                             m_context->peerman->GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
#     173                 :          0 :                     }
#     174                 :          3 :                 }
#     175                 :          3 :             }
#     176                 :          3 :             return true;
#     177                 :          3 :         }
#     178                 :          0 :         return false;
#     179                 :          3 :     }
#     180                 :            :     bool getBanned(banmap_t& banmap) override
#     181                 :          3 :     {
#     182         [ +  - ]:          3 :         if (m_context->banman) {
#     183                 :          3 :             m_context->banman->GetBanned(banmap);
#     184                 :          3 :             return true;
#     185                 :          3 :         }
#     186                 :          0 :         return false;
#     187                 :          3 :     }
#     188                 :            :     bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override
#     189                 :          0 :     {
#     190         [ #  # ]:          0 :         if (m_context->banman) {
#     191                 :          0 :             m_context->banman->Ban(net_addr, ban_time_offset);
#     192                 :          0 :             return true;
#     193                 :          0 :         }
#     194                 :          0 :         return false;
#     195                 :          0 :     }
#     196                 :            :     bool unban(const CSubNet& ip) override
#     197                 :          0 :     {
#     198         [ #  # ]:          0 :         if (m_context->banman) {
#     199                 :          0 :             m_context->banman->Unban(ip);
#     200                 :          0 :             return true;
#     201                 :          0 :         }
#     202                 :          0 :         return false;
#     203                 :          0 :     }
#     204                 :            :     bool disconnectByAddress(const CNetAddr& net_addr) override
#     205                 :          0 :     {
#     206         [ #  # ]:          0 :         if (m_context->connman) {
#     207                 :          0 :             return m_context->connman->DisconnectNode(net_addr);
#     208                 :          0 :         }
#     209                 :          0 :         return false;
#     210                 :          0 :     }
#     211                 :            :     bool disconnectById(NodeId id) override
#     212                 :          0 :     {
#     213         [ #  # ]:          0 :         if (m_context->connman) {
#     214                 :          0 :             return m_context->connman->DisconnectNode(id);
#     215                 :          0 :         }
#     216                 :          0 :         return false;
#     217                 :          0 :     }
#     218                 :            :     std::vector<std::unique_ptr<interfaces::ExternalSigner>> listExternalSigners() override
#     219                 :          0 :     {
#     220                 :          0 : #ifdef ENABLE_EXTERNAL_SIGNER
#     221                 :          0 :         std::vector<ExternalSigner> signers = {};
#     222                 :          0 :         const std::string command = gArgs.GetArg("-signer", "");
#     223         [ #  # ]:          0 :         if (command == "") return {};
#     224                 :          0 :         ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
#     225                 :          0 :         std::vector<std::unique_ptr<interfaces::ExternalSigner>> result;
#     226         [ #  # ]:          0 :         for (auto& signer : signers) {
#     227                 :          0 :             result.emplace_back(std::make_unique<ExternalSignerImpl>(std::move(signer)));
#     228                 :          0 :         }
#     229                 :          0 :         return result;
#     230                 :            : #else
#     231                 :            :         // This result is indistinguishable from a successful call that returns
#     232                 :            :         // no signers. For the current GUI this doesn't matter, because the wallet
#     233                 :            :         // creation dialog disables the external signer checkbox in both
#     234                 :            :         // cases. The return type could be changed to std::optional<std::vector>
#     235                 :            :         // (or something that also includes error messages) if this distinction
#     236                 :            :         // becomes important.
#     237                 :            :         return {};
#     238                 :            : #endif // ENABLE_EXTERNAL_SIGNER
#     239                 :          0 :     }
#     240         [ +  - ]:          2 :     int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; }
#     241         [ +  - ]:          2 :     int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; }
#     242         [ #  # ]:          0 :     size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; }
#     243         [ #  # ]:          0 :     size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; }
#     244                 :            :     bool getHeaderTip(int& height, int64_t& block_time) override
#     245                 :          0 :     {
#     246                 :          0 :         LOCK(::cs_main);
#     247         [ #  # ]:          0 :         if (::pindexBestHeader) {
#     248                 :          0 :             height = ::pindexBestHeader->nHeight;
#     249                 :          0 :             block_time = ::pindexBestHeader->GetBlockTime();
#     250                 :          0 :             return true;
#     251                 :          0 :         }
#     252                 :          0 :         return false;
#     253                 :          0 :     }
#     254                 :            :     int getNumBlocks() override
#     255                 :          0 :     {
#     256                 :          0 :         LOCK(::cs_main);
#     257                 :          0 :         return chainman().ActiveChain().Height();
#     258                 :          0 :     }
#     259                 :            :     uint256 getBestBlockHash() override
#     260                 :          1 :     {
#     261                 :          1 :         const CBlockIndex* tip = WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip());
#     262         [ +  - ]:          1 :         return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
#     263                 :          1 :     }
#     264                 :            :     int64_t getLastBlockTime() override
#     265                 :          0 :     {
#     266                 :          0 :         LOCK(::cs_main);
#     267         [ #  # ]:          0 :         if (chainman().ActiveChain().Tip()) {
#     268                 :          0 :             return chainman().ActiveChain().Tip()->GetBlockTime();
#     269                 :          0 :         }
#     270                 :          0 :         return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
#     271                 :          0 :     }
#     272                 :            :     double getVerificationProgress() override
#     273                 :          0 :     {
#     274                 :          0 :         const CBlockIndex* tip;
#     275                 :          0 :         {
#     276                 :          0 :             LOCK(::cs_main);
#     277                 :          0 :             tip = chainman().ActiveChain().Tip();
#     278                 :          0 :         }
#     279                 :          0 :         return GuessVerificationProgress(Params().TxData(), tip);
#     280                 :          0 :     }
#     281                 :          0 :     bool isInitialBlockDownload() override {
#     282                 :          0 :         return chainman().ActiveChainstate().IsInitialBlockDownload();
#     283                 :          0 :     }
#     284                 :          1 :     bool getReindex() override { return node::fReindex; }
#     285                 :          1 :     bool getImporting() override { return node::fImporting; }
#     286                 :            :     void setNetworkActive(bool active) override
#     287                 :          0 :     {
#     288         [ #  # ]:          0 :         if (m_context->connman) {
#     289                 :          0 :             m_context->connman->SetNetworkActive(active);
#     290                 :          0 :         }
#     291                 :          0 :     }
#     292 [ +  - ][ +  - ]:          4 :     bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
#     293                 :          2 :     CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
#     294                 :            :     UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
#     295                 :         36 :     {
#     296                 :         36 :         JSONRPCRequest req;
#     297                 :         36 :         req.context = m_context;
#     298                 :         36 :         req.params = params;
#     299                 :         36 :         req.strMethod = command;
#     300                 :         36 :         req.URI = uri;
#     301                 :         36 :         return ::tableRPC.execute(req);
#     302                 :         36 :     }
#     303                 :          1 :     std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); }
#     304                 :          1 :     void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); }
#     305                 :          1 :     void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); }
#     306                 :            :     bool getUnspentOutput(const COutPoint& output, Coin& coin) override
#     307                 :          0 :     {
#     308                 :          0 :         LOCK(::cs_main);
#     309                 :          0 :         return chainman().ActiveChainstate().CoinsTip().GetCoin(output, coin);
#     310                 :          0 :     }
#     311                 :            :     TransactionError broadcastTransaction(CTransactionRef tx, CAmount max_tx_fee, std::string& err_string) override
#     312                 :          0 :     {
#     313                 :          0 :         return BroadcastTransaction(*m_context, std::move(tx), err_string, max_tx_fee, /*relay=*/ true, /*wait_callback=*/ false);
#     314                 :          0 :     }
#     315                 :            :     WalletLoader& walletLoader() override
#     316                 :          6 :     {
#     317                 :          6 :         return *Assert(m_context->wallet_loader);
#     318                 :          6 :     }
#     319                 :            :     std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
#     320                 :          0 :     {
#     321                 :          0 :         return MakeHandler(::uiInterface.InitMessage_connect(fn));
#     322                 :          0 :     }
#     323                 :            :     std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override
#     324                 :          1 :     {
#     325                 :          1 :         return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn));
#     326                 :          1 :     }
#     327                 :            :     std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override
#     328                 :          1 :     {
#     329                 :          1 :         return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn));
#     330                 :          1 :     }
#     331                 :            :     std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
#     332                 :          3 :     {
#     333                 :          3 :         return MakeHandler(::uiInterface.ShowProgress_connect(fn));
#     334                 :          3 :     }
#     335                 :            :     std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) override
#     336                 :          0 :     {
#     337                 :          0 :         return MakeHandler(::uiInterface.InitWallet_connect(fn));
#     338                 :          0 :     }
#     339                 :            :     std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
#     340                 :          3 :     {
#     341                 :          3 :         return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));
#     342                 :          3 :     }
#     343                 :            :     std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override
#     344                 :          3 :     {
#     345                 :          3 :         return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn));
#     346                 :          3 :     }
#     347                 :            :     std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override
#     348                 :          3 :     {
#     349                 :          3 :         return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn));
#     350                 :          3 :     }
#     351                 :            :     std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override
#     352                 :          3 :     {
#     353                 :          3 :         return MakeHandler(::uiInterface.BannedListChanged_connect(fn));
#     354                 :          3 :     }
#     355                 :            :     std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
#     356                 :          3 :     {
#     357                 :          3 :         return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
#     358                 :          0 :             fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
#     359                 :          0 :                 GuessVerificationProgress(Params().TxData(), block));
#     360                 :          0 :         }));
#     361                 :          3 :     }
#     362                 :            :     std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
#     363                 :          3 :     {
#     364                 :          3 :         return MakeHandler(
#     365                 :          3 :             ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
#     366                 :          0 :                 fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
#     367                 :          0 :                     /* verification progress is unused when a header was received */ 0);
#     368                 :          0 :             }));
#     369                 :          3 :     }
#     370                 :          4 :     NodeContext* context() override { return m_context; }
#     371                 :            :     void setContext(NodeContext* context) override
#     372                 :          4 :     {
#     373                 :          4 :         m_context = context;
#     374                 :          4 :     }
#     375                 :            :     NodeContext* m_context{nullptr};
#     376                 :            : };
#     377                 :            : 
#     378                 :            : bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active)
#     379                 :     336536 : {
#     380         [ +  + ]:     336536 :     if (!index) return false;
#     381         [ +  + ]:     335158 :     if (block.m_hash) *block.m_hash = index->GetBlockHash();
#     382         [ +  + ]:     335158 :     if (block.m_height) *block.m_height = index->nHeight;
#     383         [ +  + ]:     335158 :     if (block.m_time) *block.m_time = index->GetBlockTime();
#     384         [ +  + ]:     335158 :     if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
#     385         [ +  + ]:     335158 :     if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
#     386         [ +  + ]:     335158 :     if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
#     387 [ +  + ][ +  - ]:     335158 :     if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active);
#     388         [ +  + ]:     335158 :     if (block.m_data) {
#     389                 :      98739 :         REVERSE_LOCK(lock);
#     390         [ +  + ]:      98739 :         if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
#     391                 :      98739 :     }
#     392                 :     335158 :     block.found = true;
#     393                 :     335158 :     return true;
#     394                 :     336536 : }
#     395                 :            : 
#     396                 :            : class NotificationsProxy : public CValidationInterface
#     397                 :            : {
#     398                 :            : public:
#     399                 :            :     explicit NotificationsProxy(std::shared_ptr<Chain::Notifications> notifications)
#     400                 :        795 :         : m_notifications(std::move(notifications)) {}
#     401                 :        795 :     virtual ~NotificationsProxy() = default;
#     402                 :            :     void TransactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override
#     403                 :       6729 :     {
#     404                 :       6729 :         m_notifications->transactionAddedToMempool(tx, mempool_sequence);
#     405                 :       6729 :     }
#     406                 :            :     void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
#     407                 :        198 :     {
#     408                 :        198 :         m_notifications->transactionRemovedFromMempool(tx, reason, mempool_sequence);
#     409                 :        198 :     }
#     410                 :            :     void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
#     411                 :      40994 :     {
#     412                 :      40994 :         m_notifications->blockConnected(*block, index->nHeight);
#     413                 :      40994 :     }
#     414                 :            :     void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
#     415                 :        817 :     {
#     416                 :        817 :         m_notifications->blockDisconnected(*block, index->nHeight);
#     417                 :        817 :     }
#     418                 :            :     void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
#     419                 :      40774 :     {
#     420                 :      40774 :         m_notifications->updatedBlockTip();
#     421                 :      40774 :     }
#     422                 :        652 :     void ChainStateFlushed(const CBlockLocator& locator) override { m_notifications->chainStateFlushed(locator); }
#     423                 :            :     std::shared_ptr<Chain::Notifications> m_notifications;
#     424                 :            : };
#     425                 :            : 
#     426                 :            : class NotificationsHandlerImpl : public Handler
#     427                 :            : {
#     428                 :            : public:
#     429                 :            :     explicit NotificationsHandlerImpl(std::shared_ptr<Chain::Notifications> notifications)
#     430                 :            :         : m_proxy(std::make_shared<NotificationsProxy>(std::move(notifications)))
#     431                 :        795 :     {
#     432                 :        795 :         RegisterSharedValidationInterface(m_proxy);
#     433                 :        795 :     }
#     434                 :        795 :     ~NotificationsHandlerImpl() override { disconnect(); }
#     435                 :            :     void disconnect() override
#     436                 :        795 :     {
#     437         [ +  - ]:        795 :         if (m_proxy) {
#     438                 :        795 :             UnregisterSharedValidationInterface(m_proxy);
#     439                 :        795 :             m_proxy.reset();
#     440                 :        795 :         }
#     441                 :        795 :     }
#     442                 :            :     std::shared_ptr<NotificationsProxy> m_proxy;
#     443                 :            : };
#     444                 :            : 
#     445                 :            : class RpcHandlerImpl : public Handler
#     446                 :            : {
#     447                 :            : public:
#     448                 :            :     explicit RpcHandlerImpl(const CRPCCommand& command) : m_command(command), m_wrapped_command(&command)
#     449                 :      51935 :     {
#     450                 :      51935 :         m_command.actor = [this](const JSONRPCRequest& request, UniValue& result, bool last_handler) {
#     451         [ -  + ]:      27407 :             if (!m_wrapped_command) return false;
#     452                 :      27407 :             try {
#     453                 :      27407 :                 return m_wrapped_command->actor(request, result, last_handler);
#     454                 :      27407 :             } catch (const UniValue& e) {
#     455                 :            :                 // If this is not the last handler and a wallet not found
#     456                 :            :                 // exception was thrown, return false so the next handler can
#     457                 :            :                 // try to handle the request. Otherwise, reraise the exception.
#     458         [ -  + ]:       1098 :                 if (!last_handler) {
#     459                 :          0 :                     const UniValue& code = e["code"];
#     460 [ #  # ][ #  # ]:          0 :                     if (code.isNum() && code.get_int() == RPC_WALLET_NOT_FOUND) {
#     461                 :          0 :                         return false;
#     462                 :          0 :                     }
#     463                 :          0 :                 }
#     464                 :       1098 :                 throw;
#     465                 :       1098 :             }
#     466                 :      27407 :         };
#     467                 :      51935 :         ::tableRPC.appendCommand(m_command.name, &m_command);
#     468                 :      51935 :     }
#     469                 :            : 
#     470                 :            :     void disconnect() final
#     471                 :      51935 :     {
#     472         [ +  - ]:      51935 :         if (m_wrapped_command) {
#     473                 :      51935 :             m_wrapped_command = nullptr;
#     474                 :      51935 :             ::tableRPC.removeCommand(m_command.name, &m_command);
#     475                 :      51935 :         }
#     476                 :      51935 :     }
#     477                 :            : 
#     478                 :      51935 :     ~RpcHandlerImpl() override { disconnect(); }
#     479                 :            : 
#     480                 :            :     CRPCCommand m_command;
#     481                 :            :     const CRPCCommand* m_wrapped_command;
#     482                 :            : };
#     483                 :            : 
#     484                 :            : class ChainImpl : public Chain
#     485                 :            : {
#     486                 :            : private:
#     487                 :     114350 :     ChainstateManager& chainman() { return *Assert(m_node.chainman); }
#     488                 :            : public:
#     489                 :       1631 :     explicit ChainImpl(NodeContext& node) : m_node(node) {}
#     490                 :            :     std::optional<int> getHeight() override
#     491                 :        784 :     {
#     492                 :        784 :         LOCK(::cs_main);
#     493                 :        784 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     494                 :        784 :         int height = active.Height();
#     495         [ +  + ]:        784 :         if (height >= 0) {
#     496                 :        774 :             return height;
#     497                 :        774 :         }
#     498                 :         10 :         return std::nullopt;
#     499                 :        784 :     }
#     500                 :            :     uint256 getBlockHash(int height) override
#     501                 :        861 :     {
#     502                 :        861 :         LOCK(::cs_main);
#     503                 :        861 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     504                 :        861 :         CBlockIndex* block = active[height];
#     505                 :        861 :         assert(block);
#     506                 :          0 :         return block->GetBlockHash();
#     507                 :        861 :     }
#     508                 :            :     bool haveBlockOnDisk(int height) override
#     509                 :          0 :     {
#     510                 :          0 :         LOCK(cs_main);
#     511                 :          0 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     512                 :          0 :         CBlockIndex* block = active[height];
#     513 [ #  # ][ #  # ]:          0 :         return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
#                 [ #  # ]
#     514                 :          0 :     }
#     515                 :            :     CBlockLocator getTipLocator() override
#     516                 :        544 :     {
#     517                 :        544 :         LOCK(cs_main);
#     518                 :        544 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     519                 :        544 :         return active.GetLocator();
#     520                 :        544 :     }
#     521                 :            :     std::optional<int> findLocatorFork(const CBlockLocator& locator) override
#     522                 :        782 :     {
#     523                 :        782 :         LOCK(cs_main);
#     524                 :        782 :         const CChainState& active = Assert(m_node.chainman)->ActiveChainstate();
#     525         [ +  + ]:        782 :         if (const CBlockIndex* fork = active.FindForkInGlobalIndex(locator)) {
#     526                 :        772 :             return fork->nHeight;
#     527                 :        772 :         }
#     528                 :         10 :         return std::nullopt;
#     529                 :        782 :     }
#     530                 :            :     bool findBlock(const uint256& hash, const FoundBlock& block) override
#     531                 :     236822 :     {
#     532                 :     236822 :         WAIT_LOCK(cs_main, lock);
#     533                 :     236822 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     534                 :     236822 :         return FillBlock(m_node.chainman->m_blockman.LookupBlockIndex(hash), block, lock, active);
#     535                 :     236822 :     }
#     536                 :            :     bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
#     537                 :        818 :     {
#     538                 :        818 :         WAIT_LOCK(cs_main, lock);
#     539                 :        818 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     540                 :        818 :         return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active);
#     541                 :        818 :     }
#     542                 :            :     bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
#     543                 :         69 :     {
#     544                 :         69 :         WAIT_LOCK(cs_main, lock);
#     545                 :         69 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     546         [ +  - ]:         69 :         if (const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash)) {
#     547         [ +  + ]:         69 :             if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
#     548                 :         67 :                 return FillBlock(ancestor, ancestor_out, lock, active);
#     549                 :         67 :             }
#     550                 :         69 :         }
#     551                 :          2 :         return FillBlock(nullptr, ancestor_out, lock, active);
#     552                 :         69 :     }
#     553                 :            :     bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
#     554                 :         14 :     {
#     555                 :         14 :         WAIT_LOCK(cs_main, lock);
#     556                 :         14 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     557                 :         14 :         const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash);
#     558                 :         14 :         const CBlockIndex* ancestor = m_node.chainman->m_blockman.LookupBlockIndex(ancestor_hash);
#     559 [ +  - ][ +  + ]:         14 :         if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
#                 [ +  + ]
#     560                 :         14 :         return FillBlock(ancestor, ancestor_out, lock, active);
#     561                 :         14 :     }
#     562                 :            :     bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
#     563                 :         32 :     {
#     564                 :         32 :         WAIT_LOCK(cs_main, lock);
#     565                 :         32 :         const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     566                 :         32 :         const CBlockIndex* block1 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash1);
#     567                 :         32 :         const CBlockIndex* block2 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash2);
#     568 [ +  + ][ +  + ]:         32 :         const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
#     569                 :            :         // Using & instead of && below to avoid short circuiting and leaving
#     570                 :            :         // output uninitialized. Cast bool to int to avoid -Wbitwise-instead-of-logical
#     571                 :            :         // compiler warnings.
#     572                 :         32 :         return int{FillBlock(ancestor, ancestor_out, lock, active)} &
#     573                 :         32 :                int{FillBlock(block1, block1_out, lock, active)} &
#     574                 :         32 :                int{FillBlock(block2, block2_out, lock, active)};
#     575                 :         32 :     }
#     576                 :       1590 :     void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
#     577                 :            :     double guessVerificationProgress(const uint256& block_hash) override
#     578                 :      99549 :     {
#     579                 :      99549 :         LOCK(cs_main);
#     580                 :      99549 :         return GuessVerificationProgress(Params().TxData(), chainman().m_blockman.LookupBlockIndex(block_hash));
#     581                 :      99549 :     }
#     582                 :            :     bool hasBlocks(const uint256& block_hash, int min_height, std::optional<int> max_height) override
#     583                 :         60 :     {
#     584                 :            :         // hasBlocks returns true if all ancestors of block_hash in specified
#     585                 :            :         // range have block data (are not pruned), false if any ancestors in
#     586                 :            :         // specified range are missing data.
#     587                 :            :         //
#     588                 :            :         // For simplicity and robustness, min_height and max_height are only
#     589                 :            :         // used to limit the range, and passing min_height that's too low or
#     590                 :            :         // max_height that's too high will not crash or change the result.
#     591                 :         60 :         LOCK(::cs_main);
#     592         [ +  - ]:         60 :         if (const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) {
#     593 [ +  + ][ +  + ]:         60 :             if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
#     594         [ +  + ]:       4834 :             for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
#     595                 :            :                 // Check pprev to not segfault if min_height is too low
#     596 [ +  + ][ +  + ]:       4806 :                 if (block->nHeight <= min_height || !block->pprev) return true;
#     597                 :       4806 :             }
#     598                 :         60 :         }
#     599                 :         28 :         return false;
#     600                 :         60 :     }
#     601                 :            :     RBFTransactionState isRBFOptIn(const CTransaction& tx) override
#     602                 :       1031 :     {
#     603         [ -  + ]:       1031 :         if (!m_node.mempool) return IsRBFOptInEmptyMempool(tx);
#     604                 :       1031 :         LOCK(m_node.mempool->cs);
#     605                 :       1031 :         return IsRBFOptIn(tx, *m_node.mempool);
#     606                 :       1031 :     }
#     607                 :            :     bool isInMempool(const uint256& txid) override
#     608                 :      26170 :     {
#     609         [ -  + ]:      26170 :         if (!m_node.mempool) return false;
#     610                 :      26170 :         LOCK(m_node.mempool->cs);
#     611                 :      26170 :         return m_node.mempool->exists(GenTxid::Txid(txid));
#     612                 :      26170 :     }
#     613                 :            :     bool hasDescendantsInMempool(const uint256& txid) override
#     614                 :        325 :     {
#     615         [ -  + ]:        325 :         if (!m_node.mempool) return false;
#     616                 :        325 :         LOCK(m_node.mempool->cs);
#     617                 :        325 :         auto it = m_node.mempool->GetIter(txid);
#     618 [ +  + ][ +  + ]:        325 :         return it && (*it)->GetCountWithDescendants() > 1;
#     619                 :        325 :     }
#     620                 :            :     bool broadcastTransaction(const CTransactionRef& tx,
#     621                 :            :         const CAmount& max_tx_fee,
#     622                 :            :         bool relay,
#     623                 :            :         std::string& err_string) override
#     624                 :       2475 :     {
#     625                 :       2475 :         const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback=*/false);
#     626                 :            :         // Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
#     627                 :            :         // Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures
#     628                 :            :         // that Chain clients do not need to know about.
#     629                 :       2475 :         return TransactionError::OK == err;
#     630                 :       2475 :     }
#     631                 :            :     void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants, size_t* ancestorsize, CAmount* ancestorfees) override
#     632                 :    1394197 :     {
#     633                 :    1394197 :         ancestors = descendants = 0;
#     634         [ -  + ]:    1394197 :         if (!m_node.mempool) return;
#     635                 :    1394197 :         m_node.mempool->GetTransactionAncestry(txid, ancestors, descendants, ancestorsize, ancestorfees);
#     636                 :    1394197 :     }
#     637                 :            :     void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override
#     638                 :       5485 :     {
#     639                 :       5485 :         limit_ancestor_count = gArgs.GetIntArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
#     640                 :       5485 :         limit_descendant_count = gArgs.GetIntArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
#     641                 :       5485 :     }
#     642                 :            :     bool checkChainLimits(const CTransactionRef& tx) override
#     643                 :       5177 :     {
#     644         [ -  + ]:       5177 :         if (!m_node.mempool) return true;
#     645                 :       5177 :         LockPoints lp;
#     646                 :       5177 :         CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp);
#     647                 :       5177 :         CTxMemPool::setEntries ancestors;
#     648                 :       5177 :         auto limit_ancestor_count = gArgs.GetIntArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
#     649                 :       5177 :         auto limit_ancestor_size = gArgs.GetIntArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000;
#     650                 :       5177 :         auto limit_descendant_count = gArgs.GetIntArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
#     651                 :       5177 :         auto limit_descendant_size = gArgs.GetIntArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000;
#     652                 :       5177 :         std::string unused_error_string;
#     653                 :       5177 :         LOCK(m_node.mempool->cs);
#     654                 :       5177 :         return m_node.mempool->CalculateMemPoolAncestors(
#     655                 :       5177 :             entry, ancestors, limit_ancestor_count, limit_ancestor_size,
#     656                 :       5177 :             limit_descendant_count, limit_descendant_size, unused_error_string);
#     657                 :       5177 :     }
#     658                 :            :     CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
#     659                 :       9846 :     {
#     660         [ -  + ]:       9846 :         if (!m_node.fee_estimator) return {};
#     661                 :       9846 :         return m_node.fee_estimator->estimateSmartFee(num_blocks, calc, conservative);
#     662                 :       9846 :     }
#     663                 :            :     unsigned int estimateMaxBlocks() override
#     664                 :       5517 :     {
#     665         [ -  + ]:       5517 :         if (!m_node.fee_estimator) return 0;
#     666                 :       5517 :         return m_node.fee_estimator->HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
#     667                 :       5517 :     }
#     668                 :            :     CFeeRate mempoolMinFee() override
#     669                 :       4414 :     {
#     670         [ -  + ]:       4414 :         if (!m_node.mempool) return {};
#     671                 :       4414 :         return m_node.mempool->GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
#     672                 :       4414 :     }
#     673                 :       6164 :     CFeeRate relayMinFee() override { return ::minRelayTxFee; }
#     674                 :        168 :     CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
#     675                 :      64457 :     CFeeRate relayDustFee() override { return ::dustRelayFee; }
#     676                 :            :     bool havePruned() override
#     677                 :        324 :     {
#     678                 :        324 :         LOCK(cs_main);
#     679                 :        324 :         return node::fHavePruned;
#     680                 :        324 :     }
#     681 [ +  - ][ +  - ]:       9389 :     bool isReadyToBroadcast() override { return !node::fImporting && !node::fReindex && !isInitialBlockDownload(); }
#                 [ +  + ]
#     682                 :      14741 :     bool isInitialBlockDownload() override {
#     683                 :      14741 :         return chainman().ActiveChainstate().IsInitialBlockDownload();
#     684                 :      14741 :     }
#     685                 :      99335 :     bool shutdownRequested() override { return ShutdownRequested(); }
#     686                 :       1648 :     void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
#     687                 :          3 :     void initWarning(const bilingual_str& message) override { InitWarning(message); }
#     688                 :         28 :     void initError(const bilingual_str& message) override { InitError(message); }
#     689                 :            :     void showProgress(const std::string& title, int progress, bool resume_possible) override
#     690                 :       3502 :     {
#     691                 :       3502 :         ::uiInterface.ShowProgress(title, progress, resume_possible);
#     692                 :       3502 :     }
#     693                 :            :     std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) override
#     694                 :        795 :     {
#     695                 :        795 :         return std::make_unique<NotificationsHandlerImpl>(std::move(notifications));
#     696                 :        795 :     }
#     697                 :            :     void waitForNotificationsIfTipChanged(const uint256& old_tip) override
#     698                 :       9368 :     {
#     699         [ +  - ]:       9368 :         if (!old_tip.IsNull()) {
#     700                 :       9368 :             LOCK(::cs_main);
#     701                 :       9368 :             const CChain& active = Assert(m_node.chainman)->ActiveChain();
#     702         [ +  + ]:       9368 :             if (old_tip == active.Tip()->GetBlockHash()) return;
#     703                 :       9368 :         }
#     704                 :        264 :         SyncWithValidationInterfaceQueue();
#     705                 :        264 :     }
#     706                 :            :     std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
#     707                 :      51935 :     {
#     708                 :      51935 :         return std::make_unique<RpcHandlerImpl>(command);
#     709                 :      51935 :     }
#     710                 :        465 :     bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); }
#     711                 :            :     void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) override
#     712                 :         62 :     {
#     713                 :         62 :         RPCRunLater(name, std::move(fn), seconds);
#     714                 :         62 :     }
#     715                 :        474 :     int rpcSerializationFlags() override { return RPCSerializationFlags(); }
#     716                 :            :     util::SettingsValue getSetting(const std::string& name) override
#     717                 :          0 :     {
#     718                 :          0 :         return gArgs.GetSetting(name);
#     719                 :          0 :     }
#     720                 :            :     std::vector<util::SettingsValue> getSettingsList(const std::string& name) override
#     721                 :       1497 :     {
#     722                 :       1497 :         return gArgs.GetSettingsList(name);
#     723                 :       1497 :     }
#     724                 :            :     util::SettingsValue getRwSetting(const std::string& name) override
#     725                 :        247 :     {
#     726                 :        247 :         util::SettingsValue result;
#     727                 :        247 :         gArgs.LockSettings([&](const util::Settings& settings) {
#     728         [ +  + ]:        247 :             if (const util::SettingsValue* value = util::FindKey(settings.rw_settings, name)) {
#     729                 :         18 :                 result = *value;
#     730                 :         18 :             }
#     731                 :        247 :         });
#     732                 :        247 :         return result;
#     733                 :        247 :     }
#     734                 :            :     bool updateRwSetting(const std::string& name, const util::SettingsValue& value, bool write) override
#     735                 :        239 :     {
#     736                 :        239 :         gArgs.LockSettings([&](util::Settings& settings) {
#     737         [ -  + ]:        239 :             if (value.isNull()) {
#     738                 :          0 :                 settings.rw_settings.erase(name);
#     739                 :        239 :             } else {
#     740                 :        239 :                 settings.rw_settings[name] = value;
#     741                 :        239 :             }
#     742                 :        239 :         });
#     743 [ +  + ][ +  - ]:        239 :         return !write || gArgs.WriteSettingsFile();
#     744                 :        239 :     }
#     745                 :            :     void requestMempoolTransactions(Notifications& notifications) override
#     746                 :        782 :     {
#     747         [ -  + ]:        782 :         if (!m_node.mempool) return;
#     748                 :        782 :         LOCK2(::cs_main, m_node.mempool->cs);
#     749         [ +  + ]:        782 :         for (const CTxMemPoolEntry& entry : m_node.mempool->mapTx) {
#     750                 :        145 :             notifications.transactionAddedToMempool(entry.GetSharedTx(), 0 /* mempool_sequence */);
#     751                 :        145 :         }
#     752                 :        782 :     }
#     753                 :            :     NodeContext& m_node;
#     754                 :            : };
#     755                 :            : } // namespace
#     756                 :            : } // namespace node
#     757                 :            : 
#     758                 :            : namespace interfaces {
#     759                 :          1 : std::unique_ptr<Node> MakeNode(node::NodeContext& context) { return std::make_unique<node::NodeImpl>(context); }
#     760                 :       1631 : std::unique_ptr<Chain> MakeChain(node::NodeContext& context) { return std::make_unique<node::ChainImpl>(context); }
#     761                 :            : } // namespace interfaces

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a