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