LCOV - code coverage report
Current view: top level - src/node - interfaces.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 285 504 56.5 %
Date: 2021-06-29 14:35:33 Functions: 65 122 53.3 %
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: 76 162 46.9 %

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

Generated by: LCOV version 1.14