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
|