LCOV - code coverage report
Current view: top level - src/node - interfaces.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 9 529 1.7 %
Date: 2023-09-26 12:08:55 Functions: 11 169 6.5 %

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

Generated by: LCOV version 1.14