interfaces.cpp raw
1 // Copyright (c) 2018-2022 The Limenka 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 <chainparamsbase.h>
11 #include <common/args.h>
12 #include <common/pcp.h>
13 #include <consensus/merkle.h>
14 #include <consensus/validation.h>
15 #include <deploymentstatus.h>
16 #include <external_signer.h>
17 #include <index/blockfilterindex.h>
18 #include <init.h>
19 #include <interfaces/chain.h>
20 #include <interfaces/handler.h>
21 #include <interfaces/mining.h>
22 #include <interfaces/node.h>
23 #include <interfaces/types.h>
24 #include <interfaces/wallet.h>
25 #include <kernel/chain.h>
26 #include <kernel/context.h>
27 #include <kernel/mempool_entry.h>
28 #include <logging.h>
29 #include <mapport.h>
30 #include <net.h>
31 #include <net_processing.h>
32 #include <netaddress.h>
33 #include <netbase.h>
34 #include <node/blockstorage.h>
35 #include <node/coin.h>
36 #include <node/context.h>
37 #include <node/interface_ui.h>
38 #include <node/mini_miner.h>
39 #include <node/miner.h>
40 #include <node/kernel_notifications.h>
41 #include <node/transaction.h>
42 #include <node/types.h>
43 #include <node/warnings.h>
44 #include <policy/feerate.h>
45 #include <policy/fees.h>
46 #include <policy/policy.h>
47 #include <policy/rbf.h>
48 #include <policy/settings.h>
49 #include <primitives/block.h>
50 #include <primitives/transaction.h>
51 #include <rpc/blockchain.h>
52 #include <rpc/protocol.h>
53 #include <rpc/server.h>
54 #include <support/allocators/secure.h>
55 #include <sync.h>
56 #include <txmempool.h>
57 #include <uint256.h>
58 #include <univalue.h>
59 #include <util/check.h>
60 #include <util/result.h>
61 #include <util/signalinterrupt.h>
62 #include <util/string.h>
63 #include <util/translation.h>
64 #include <validation.h>
65 #include <validationinterface.h>
66
67 #include <limenka-build-config.h> // IWYU pragma: keep
68
69 #include <any>
70 #include <memory>
71 #include <optional>
72 #include <utility>
73
74 #include <boost/signals2/signal.hpp>
75
76 using interfaces::BlockRef;
77 using interfaces::BlockTemplate;
78 using interfaces::BlockTip;
79 using interfaces::Chain;
80 using interfaces::FoundBlock;
81 using interfaces::Handler;
82 using interfaces::MakeSignalHandler;
83 using interfaces::Mining;
84 using interfaces::Node;
85 using interfaces::WalletLoader;
86 using node::BlockAssembler;
87 using util::Join;
88
89 namespace node {
90 // All members of the classes in this namespace are intentionally public, as the
91 // classes themselves are private.
92 namespace {
93 #ifdef ENABLE_EXTERNAL_SIGNER
94 class ExternalSignerImpl : public interfaces::ExternalSigner
95 {
96 public:
97 ExternalSignerImpl(::ExternalSigner signer) : m_signer(std::move(signer)) {}
98 std::string getName() override { return m_signer.m_name; }
99 ::ExternalSigner m_signer;
100 };
101 #endif
102
103 class NodeImpl : public Node
104 {
105 public:
106 explicit NodeImpl(NodeContext& context) { setContext(&context); }
107 void initLogging() override { InitLogging(args()); }
108 void initParameterInteraction() override { InitParameterInteraction(args()); }
109 bilingual_str getWarnings() override { return Join(Assert(m_context->warnings)->GetMessages(), Untranslated("<hr />")); }
110 int getExitStatus() override { return Assert(m_context)->exit_status.load(); }
111 BCLog::CategoryMask getLogCategories() override { return LogInstance().GetCategoryMask(); }
112 bool baseInitialize() override
113 {
114 if (!AppInitBasicSetup(args(), Assert(context())->exit_status)) return false;
115 if (!AppInitParameterInteraction(args())) return false;
116
117 m_context->warnings = std::make_unique<node::Warnings>();
118 m_context->kernel = std::make_unique<kernel::Context>();
119 m_context->ecc_context = std::make_unique<ECC_Context>();
120 if (!AppInitSanityChecks(*m_context->kernel)) return false;
121
122 if (!AppInitLockDirectories()) return false;
123 if (!AppInitInterfaces(*m_context)) return false;
124
125 return true;
126 }
127 bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override
128 {
129 if (AppInitMain(*m_context, tip_info)) return true;
130 // Error during initialization, set exit status before continue
131 m_context->exit_status.store(EXIT_FAILURE);
132 return false;
133 }
134 void appShutdown() override
135 {
136 Interrupt(*m_context);
137 Shutdown(*m_context);
138 }
139 void startShutdown() override
140 {
141 NodeContext& ctx{*Assert(m_context)};
142 if (!(Assert(ctx.shutdown_request))()) {
143 LogError("Failed to send shutdown signal\n");
144 }
145
146 // Stop RPC for clean shutdown if any of waitfor* commands is executed.
147 if (args().GetBoolArg("-server", false)) {
148 InterruptRPC();
149 StopRPC();
150 }
151 }
152 bool shutdownRequested() override { return ShutdownRequested(*Assert(m_context)); };
153 bool isSettingIgnored(const std::string& name) override
154 {
155 bool ignored = false;
156 args().LockSettings([&](common::Settings& settings) {
157 if (auto* options = common::FindKey(settings.command_line_options, name)) {
158 ignored = !options->empty();
159 }
160 });
161 return ignored;
162 }
163 common::SettingsValue getPersistentSetting(const std::string& name) override { return args().GetPersistentSetting(name); }
164 void updateRwSetting(const std::string& name, const common::SettingsValue& value) override
165 {
166 args().LockSettings([&](common::Settings& settings) {
167 if (value.isNull()) {
168 settings.rw_settings.erase(name);
169 } else {
170 settings.rw_settings[name] = value;
171 }
172 });
173 args().WriteSettingsFile();
174 }
175 void forceSetting(const std::string& name, const common::SettingsValue& value) override
176 {
177 args().LockSettings([&](common::Settings& settings) {
178 if (value.isNull()) {
179 settings.forced_settings.erase(name);
180 } else {
181 settings.forced_settings[name] = value;
182 }
183 });
184 }
185 void resetSettings() override
186 {
187 args().WriteSettingsFile(/*errors=*/nullptr, /*backup=*/true);
188 args().LockSettings([&](common::Settings& settings) {
189 std::map<std::string, common::SettingsValue> new_rw_settings;
190 if (auto it = settings.rw_settings.find(CONSENSUSRULES_CONFIG_NAME); it != settings.rw_settings.end()) {
191 new_rw_settings.emplace(it->first, std::move(it->second));
192 }
193 settings.rw_settings.swap(new_rw_settings);
194 });
195 args().WriteSettingsFile();
196 }
197 void mapPort(bool use_upnp, bool use_pcp) override {
198 if (use_pcp && !MapPortIsProtoEnabled(MapPortProtoFlag::PCP)) {
199 // Explicitly enabling PCP
200 g_pcp_warn_for_unauthorized = true;
201 }
202 StartMapPort(use_upnp, use_pcp);
203 }
204 bool getProxy(Network net, Proxy& proxy_info) override { return GetProxy(net, proxy_info); }
205 size_t getNodeCount(ConnectionDirection flags) override
206 {
207 return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0;
208 }
209 bool getNodesStats(NodesStats& stats) override
210 {
211 stats.clear();
212
213 if (m_context->connman) {
214 std::vector<CNodeStats> stats_temp;
215 m_context->connman->GetNodeStats(stats_temp);
216
217 stats.reserve(stats_temp.size());
218 for (auto& node_stats_temp : stats_temp) {
219 stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats());
220 }
221
222 // Try to retrieve the CNodeStateStats for each node.
223 if (m_context->peerman) {
224 TRY_LOCK(::cs_main, lockMain);
225 if (lockMain) {
226 for (auto& node_stats : stats) {
227 std::get<1>(node_stats) =
228 m_context->peerman->GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
229 }
230 }
231 }
232 return true;
233 }
234 return false;
235 }
236 bool getBanned(banmap_t& banmap) override
237 {
238 if (m_context->banman) {
239 m_context->banman->GetBanned(banmap);
240 return true;
241 }
242 return false;
243 }
244 bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override
245 {
246 if (m_context->banman) {
247 m_context->banman->Ban(net_addr, ban_time_offset);
248 return true;
249 }
250 return false;
251 }
252 bool unban(const CSubNet& ip) override
253 {
254 if (m_context->banman) {
255 m_context->banman->Unban(ip);
256 return true;
257 }
258 return false;
259 }
260 bool disconnectByAddress(const CNetAddr& net_addr) override
261 {
262 if (m_context->connman) {
263 return m_context->connman->DisconnectNode(net_addr);
264 }
265 return false;
266 }
267 bool disconnectById(NodeId id) override
268 {
269 if (m_context->connman) {
270 return m_context->connman->DisconnectNode(id);
271 }
272 return false;
273 }
274 std::vector<std::unique_ptr<interfaces::ExternalSigner>> listExternalSigners() override
275 {
276 #ifdef ENABLE_EXTERNAL_SIGNER
277 std::vector<ExternalSigner> signers = {};
278 const std::string command = args().GetArg("-signer", "");
279 if (command == "") return {};
280 ExternalSigner::Enumerate(command, signers, Params().GetChainTypeString());
281 std::vector<std::unique_ptr<interfaces::ExternalSigner>> result;
282 result.reserve(signers.size());
283 for (auto& signer : signers) {
284 result.emplace_back(std::make_unique<ExternalSignerImpl>(std::move(signer)));
285 }
286 return result;
287 #else
288 // This result is indistinguishable from a successful call that returns
289 // no signers. For the current GUI this doesn't matter, because the wallet
290 // creation dialog disables the external signer checkbox in both
291 // cases. The return type could be changed to std::optional<std::vector>
292 // (or something that also includes error messages) if this distinction
293 // becomes important.
294 return {};
295 #endif // ENABLE_EXTERNAL_SIGNER
296 }
297 int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; }
298 int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; }
299 size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; }
300 size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; }
301 size_t getMempoolMaxUsage() override { return m_context->mempool ? m_context->mempool->m_opts.max_size_bytes : 0; }
302 bool getHeaderTip(int& height, int64_t& block_time) override
303 {
304 LOCK(::cs_main);
305 auto best_header = chainman().m_best_header;
306 if (best_header) {
307 height = best_header->nHeight;
308 block_time = best_header->GetBlockTime();
309 return true;
310 }
311 return false;
312 }
313 std::map<CNetAddr, LocalServiceInfo> getNetLocalAddresses() override
314 {
315 if (m_context->connman)
316 return m_context->connman->getNetLocalAddresses();
317 else
318 return {};
319 }
320 int getNumBlocks() override
321 {
322 LOCK(::cs_main);
323 return chainman().ActiveChain().Height();
324 }
325 uint256 getBestBlockHash() override
326 {
327 const CBlockIndex* tip = WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip());
328 return tip ? tip->GetBlockHash() : chainman().GetParams().GenesisBlock().GetHash();
329 }
330 int64_t getLastBlockTime() override
331 {
332 LOCK(::cs_main);
333 if (chainman().ActiveChain().Tip()) {
334 return chainman().ActiveChain().Tip()->GetBlockTime();
335 }
336 return chainman().GetParams().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
337 }
338 double getVerificationProgress() override
339 {
340 return chainman().GuessVerificationProgress(WITH_LOCK(chainman().GetMutex(), return chainman().ActiveChain().Tip()));
341 }
342 bool isInitialBlockDownload() override
343 {
344 return chainman().IsInitialBlockDownload();
345 }
346 bool isLoadingBlocks() override { return chainman().m_blockman.LoadingBlocks(); }
347 void setNetworkActive(bool active) override
348 {
349 if (m_context->connman) {
350 m_context->connman->SetNetworkActive(active);
351 }
352 }
353 bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
354 CFeeRate getDustRelayFee() override
355 {
356 if (!m_context->mempool) return CFeeRate{DUST_RELAY_TX_FEE};
357 return m_context->mempool->m_opts.dust_relay_feerate;
358 }
359 UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
360 {
361 JSONRPCRequest req;
362 req.context = m_context;
363 req.params = params;
364 req.strMethod = command;
365 req.URI = uri;
366 req.m_wallet_restriction.clear();
367 return ::tableRPC.execute(req);
368 }
369 std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); }
370 void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); }
371 void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); }
372 std::optional<Coin> getUnspentOutput(const COutPoint& output) override
373 {
374 LOCK(::cs_main);
375 return chainman().ActiveChainstate().CoinsTip().GetCoin(output);
376 }
377 TransactionError broadcastTransaction(CTransactionRef tx, const std::variant<CAmount, CFeeRate>& max_tx_fee, std::string& err_string) override
378 {
379 return BroadcastTransaction(*m_context, std::move(tx), err_string, max_tx_fee, /*relay=*/ true, /*wait_callback=*/ false);
380 }
381 WalletLoader& walletLoader() override
382 {
383 return *Assert(m_context->wallet_loader);
384 }
385 std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
386 {
387 return MakeSignalHandler(::uiInterface.InitMessage_connect(fn));
388 }
389 std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override
390 {
391 return MakeSignalHandler(::uiInterface.ThreadSafeMessageBox_connect(fn));
392 }
393 std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override
394 {
395 return MakeSignalHandler(::uiInterface.ThreadSafeQuestion_connect(fn));
396 }
397 std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
398 {
399 return MakeSignalHandler(::uiInterface.ShowProgress_connect(fn));
400 }
401 std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) override
402 {
403 return MakeSignalHandler(::uiInterface.InitWallet_connect(fn));
404 }
405 std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
406 {
407 return MakeSignalHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));
408 }
409 std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override
410 {
411 return MakeSignalHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn));
412 }
413 std::unique_ptr<Handler> handleNotifyNetworkLocalChanged(NotifyNetworkLocalChangedFn fn) override
414 {
415 return MakeSignalHandler(::uiInterface.NotifyNetworkLocalChanged_connect(fn));
416 }
417 std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override
418 {
419 return MakeSignalHandler(::uiInterface.NotifyAlertChanged_connect(fn));
420 }
421 std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override
422 {
423 if (m_context->banman) {
424 m_context->banman->EnsureSweepScheduled();
425 }
426 return MakeSignalHandler(::uiInterface.BannedListChanged_connect(fn));
427 }
428 std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
429 {
430 return MakeSignalHandler(::uiInterface.NotifyBlockTip_connect([fn, this](SynchronizationState sync_state, const CBlockIndex* block) {
431 fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
432 chainman().GuessVerificationProgress(block));
433 }));
434 }
435 std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
436 {
437 return MakeSignalHandler(
438 ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, int64_t height, int64_t timestamp, bool presync) {
439 fn(sync_state, BlockTip{(int)height, timestamp, uint256{}}, presync);
440 }));
441 }
442 NodeContext* context() override { return m_context; }
443 void setContext(NodeContext* context) override
444 {
445 m_context = context;
446 }
447 ArgsManager& args() { return *Assert(Assert(m_context)->args); }
448 ChainstateManager& chainman() { return *Assert(m_context->chainman); }
449 CTxMemPool& mempool() override { return *Assert(m_context->mempool); }
450 NodeContext* m_context{nullptr};
451 };
452
453 // NOLINTNEXTLINE(misc-no-recursion)
454 bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active, const BlockManager& blockman)
455 {
456 if (!index) return false;
457 if (block.m_hash) *block.m_hash = index->GetBlockHash();
458 if (block.m_height) *block.m_height = index->nHeight;
459 if (block.m_time) *block.m_time = index->GetBlockTime();
460 if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
461 if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
462 if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
463 if (block.m_locator) { *block.m_locator = GetLocator(index); }
464 if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active, blockman);
465 if (block.m_data) {
466 REVERSE_LOCK(lock);
467 if (!blockman.ReadBlock(*block.m_data, *index)) block.m_data->SetNull();
468 }
469 block.found = true;
470 return true;
471 }
472
473 class NotificationsProxy : public CValidationInterface
474 {
475 public:
476 explicit NotificationsProxy(std::shared_ptr<Chain::Notifications> notifications)
477 : m_notifications(std::move(notifications)) {}
478 virtual ~NotificationsProxy() = default;
479 void TransactionAddedToMempool(const NewMempoolTransactionInfo& tx, uint64_t mempool_sequence) override
480 {
481 m_notifications->transactionAddedToMempool(tx.info.m_tx);
482 }
483 void TransactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override
484 {
485 m_notifications->transactionRemovedFromMempool(tx, reason);
486 }
487 void BlockConnected(ChainstateRole role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
488 {
489 m_notifications->blockConnected(role, kernel::MakeBlockInfo(index, block.get()));
490 }
491 void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
492 {
493 m_notifications->blockDisconnected(kernel::MakeBlockInfo(index, block.get()));
494 }
495 void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
496 {
497 m_notifications->updatedBlockTip();
498 }
499 void ChainStateFlushed(ChainstateRole role, const CBlockLocator& locator) override {
500 m_notifications->chainStateFlushed(role, locator);
501 }
502 std::shared_ptr<Chain::Notifications> m_notifications;
503 };
504
505 class NotificationsHandlerImpl : public Handler
506 {
507 public:
508 explicit NotificationsHandlerImpl(ValidationSignals& signals, std::shared_ptr<Chain::Notifications> notifications)
509 : m_signals{signals}, m_proxy{std::make_shared<NotificationsProxy>(std::move(notifications))}
510 {
511 m_signals.RegisterSharedValidationInterface(m_proxy);
512 }
513 ~NotificationsHandlerImpl() override { disconnect(); }
514 void disconnect() override
515 {
516 if (m_proxy) {
517 m_signals.UnregisterSharedValidationInterface(m_proxy);
518 m_proxy.reset();
519 }
520 }
521 ValidationSignals& m_signals;
522 std::shared_ptr<NotificationsProxy> m_proxy;
523 };
524
525 class RpcHandlerImpl : public Handler
526 {
527 public:
528 explicit RpcHandlerImpl(const CRPCCommand& command) : m_command(command), m_wrapped_command(&command)
529 {
530 m_command.actor = [this](const JSONRPCRequest& request, UniValue& result, bool last_handler) {
531 if (!m_wrapped_command) return false;
532 try {
533 return m_wrapped_command->actor(request, result, last_handler);
534 } catch (const UniValue& e) {
535 // If this is not the last handler and a wallet not found
536 // exception was thrown, return false so the next handler can
537 // try to handle the request. Otherwise, reraise the exception.
538 if (!last_handler) {
539 const UniValue& code = e["code"];
540 if (code.isNum() && code.getInt<int>() == RPC_WALLET_NOT_FOUND) {
541 return false;
542 }
543 }
544 throw;
545 }
546 };
547 ::tableRPC.appendCommand(m_command.name, &m_command);
548 }
549
550 void disconnect() final
551 {
552 if (m_wrapped_command) {
553 m_wrapped_command = nullptr;
554 ::tableRPC.removeCommand(m_command.name, &m_command);
555 }
556 }
557
558 ~RpcHandlerImpl() override { disconnect(); }
559
560 CRPCCommand m_command;
561 const CRPCCommand* m_wrapped_command;
562 };
563
564 class ChainImpl : public Chain
565 {
566 public:
567 explicit ChainImpl(NodeContext& node) : m_node(node) {}
568 std::optional<int> getHeight() override
569 {
570 const int height{WITH_LOCK(::cs_main, return chainman().ActiveChain().Height())};
571 return height >= 0 ? std::optional{height} : std::nullopt;
572 }
573 uint256 getBlockHash(int height) override
574 {
575 LOCK(::cs_main);
576 return Assert(chainman().ActiveChain()[height])->GetBlockHash();
577 }
578 bool haveBlockOnDisk(int height) override
579 {
580 LOCK(::cs_main);
581 const CBlockIndex* block{chainman().ActiveChain()[height]};
582 return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
583 }
584 bool pruneLockExists(const std::string& name) const override
585 {
586 LOCK(cs_main);
587 auto& blockman = m_node.chainman->m_blockman;
588 return blockman.PruneLockExists(name);
589 }
590 bool updatePruneLock(const std::string& name, const node::PruneLockInfo& lock_info, bool sync) override
591 {
592 LOCK(cs_main);
593 auto& blockman = m_node.chainman->m_blockman;
594 return blockman.UpdatePruneLock(name, lock_info, sync);
595 }
596 bool deletePruneLock(const std::string& name) override
597 {
598 LOCK(cs_main);
599 auto& blockman = m_node.chainman->m_blockman;
600 return blockman.DeletePruneLock(name);
601 }
602 CBlockLocator getTipLocator() override
603 {
604 LOCK(::cs_main);
605 return chainman().ActiveChain().GetLocator();
606 }
607 int64_t getTipMtp() override
608 {
609 LOCK(::cs_main);
610 const CBlockIndex* tip{chainman().ActiveTip()};
611 if (!tip) return 0;
612 return tip->GetMedianTimePast(chainman().GetParams().GetConsensus().nForkMTPWindow);
613 }
614 CBlockLocator getActiveChainLocator(const uint256& block_hash) override
615 {
616 LOCK(::cs_main);
617 const CBlockIndex* index = chainman().m_blockman.LookupBlockIndex(block_hash);
618 return GetLocator(index);
619 }
620 std::optional<int> findLocatorFork(const CBlockLocator& locator) override
621 {
622 LOCK(::cs_main);
623 if (const CBlockIndex* fork = chainman().ActiveChainstate().FindForkInGlobalIndex(locator)) {
624 return fork->nHeight;
625 }
626 return std::nullopt;
627 }
628 bool hasBlockFilterIndex(BlockFilterType filter_type) override
629 {
630 return GetBlockFilterIndex(filter_type) != nullptr;
631 }
632 std::optional<bool> blockFilterMatchesAny(BlockFilterType filter_type, const uint256& block_hash, const GCSFilter::ElementSet& filter_set) override
633 {
634 const BlockFilterIndex* block_filter_index{GetBlockFilterIndex(filter_type)};
635 if (!block_filter_index) return std::nullopt;
636
637 BlockFilter filter;
638 const CBlockIndex* index{WITH_LOCK(::cs_main, return chainman().m_blockman.LookupBlockIndex(block_hash))};
639 if (index == nullptr || !block_filter_index->LookupFilter(index, filter)) return std::nullopt;
640 return filter.GetFilter().MatchAny(filter_set);
641 }
642 bool findBlock(const uint256& hash, const FoundBlock& block) override
643 {
644 WAIT_LOCK(cs_main, lock);
645 return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, chainman().ActiveChain(), chainman().m_blockman);
646 }
647 bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
648 {
649 WAIT_LOCK(cs_main, lock);
650 const CChain& active = chainman().ActiveChain();
651 return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active, chainman().m_blockman);
652 }
653 bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
654 {
655 WAIT_LOCK(cs_main, lock);
656 const CChain& active = chainman().ActiveChain();
657 if (const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) {
658 if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
659 return FillBlock(ancestor, ancestor_out, lock, active, chainman().m_blockman);
660 }
661 }
662 return FillBlock(nullptr, ancestor_out, lock, active, chainman().m_blockman);
663 }
664 bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
665 {
666 WAIT_LOCK(cs_main, lock);
667 const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash);
668 const CBlockIndex* ancestor = chainman().m_blockman.LookupBlockIndex(ancestor_hash);
669 if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
670 return FillBlock(ancestor, ancestor_out, lock, chainman().ActiveChain(), chainman().m_blockman);
671 }
672 bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
673 {
674 WAIT_LOCK(cs_main, lock);
675 const CChain& active = chainman().ActiveChain();
676 const CBlockIndex* block1 = chainman().m_blockman.LookupBlockIndex(block_hash1);
677 const CBlockIndex* block2 = chainman().m_blockman.LookupBlockIndex(block_hash2);
678 const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
679 // Using & instead of && below to avoid short circuiting and leaving
680 // output uninitialized. Cast bool to int to avoid -Wbitwise-instead-of-logical
681 // compiler warnings.
682 return int{FillBlock(ancestor, ancestor_out, lock, active, chainman().m_blockman)} &
683 int{FillBlock(block1, block1_out, lock, active, chainman().m_blockman)} &
684 int{FillBlock(block2, block2_out, lock, active, chainman().m_blockman)};
685 }
686 void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
687 double guessVerificationProgress(const uint256& block_hash) override
688 {
689 LOCK(chainman().GetMutex());
690 return chainman().GuessVerificationProgress(chainman().m_blockman.LookupBlockIndex(block_hash));
691 }
692 bool hasBlocks(const uint256& block_hash, int min_height, std::optional<int> max_height) override
693 {
694 // hasBlocks returns true if all ancestors of block_hash in specified
695 // range have block data (are not pruned), false if any ancestors in
696 // specified range are missing data.
697 //
698 // For simplicity and robustness, min_height and max_height are only
699 // used to limit the range, and passing min_height that's too low or
700 // max_height that's too high will not crash or change the result.
701 LOCK(::cs_main);
702 if (const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) {
703 if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
704 for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
705 // Check pprev to not segfault if min_height is too low
706 if (block->nHeight <= min_height || !block->pprev) return true;
707 }
708 }
709 return false;
710 }
711 RBFTransactionState isRBFOptIn(const CTransaction& tx) override
712 {
713 if (!m_node.mempool) return IsRBFOptInEmptyMempool(tx);
714 LOCK(m_node.mempool->cs);
715 return IsRBFOptIn(tx, *m_node.mempool);
716 }
717 bool isInMempool(const uint256& txid) override
718 {
719 if (!m_node.mempool) return false;
720 LOCK(m_node.mempool->cs);
721 return m_node.mempool->exists(GenTxid::Txid(txid));
722 }
723 bool hasDescendantsInMempool(const uint256& txid) override
724 {
725 if (!m_node.mempool) return false;
726 LOCK(m_node.mempool->cs);
727 const auto entry{m_node.mempool->GetEntry(Txid::FromUint256(txid))};
728 if (entry == nullptr) return false;
729 return entry->GetCountWithDescendants() > 1;
730 }
731 bool broadcastTransaction(const CTransactionRef& tx,
732 const CAmount& max_tx_fee,
733 bool relay,
734 std::string& err_string) override
735 {
736 const TransactionError err = BroadcastTransaction(m_node, tx, err_string, max_tx_fee, relay, /*wait_callback=*/false);
737 // Chain clients only care about failures to accept the tx to the mempool. Disregard non-mempool related failures.
738 // Note: this will need to be updated if BroadcastTransactions() is updated to return other non-mempool failures
739 // that Chain clients do not need to know about.
740 return TransactionError::OK == err;
741 }
742 void getTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants, size_t* ancestorsize, CAmount* ancestorfees) override
743 {
744 ancestors = descendants = 0;
745 if (!m_node.mempool) return;
746 m_node.mempool->GetTransactionAncestry(txid, ancestors, descendants, ancestorsize, ancestorfees);
747 }
748
749 std::map<COutPoint, CAmount> calculateIndividualBumpFees(const std::vector<COutPoint>& outpoints, const CFeeRate& target_feerate) override
750 {
751 if (!m_node.mempool) {
752 std::map<COutPoint, CAmount> bump_fees;
753 for (const auto& outpoint : outpoints) {
754 bump_fees.emplace(outpoint, 0);
755 }
756 return bump_fees;
757 }
758 return MiniMiner(*m_node.mempool, outpoints).CalculateBumpFees(target_feerate);
759 }
760
761 std::optional<CAmount> calculateCombinedBumpFee(const std::vector<COutPoint>& outpoints, const CFeeRate& target_feerate) override
762 {
763 if (!m_node.mempool) {
764 return 0;
765 }
766 return MiniMiner(*m_node.mempool, outpoints).CalculateTotalBumpFees(target_feerate);
767 }
768 void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override
769 {
770 const CTxMemPool::Limits default_limits{};
771
772 const CTxMemPool::Limits& limits{m_node.mempool ? m_node.mempool->m_opts.limits : default_limits};
773
774 limit_ancestor_count = limits.ancestor_count;
775 limit_descendant_count = limits.descendant_count;
776 }
777 util::Result<void> checkChainLimits(const CTransactionRef& tx) override
778 {
779 if (!m_node.mempool) return {};
780 LockPoints lp;
781 CTxMemPoolEntry entry(tx, 0, 0, 0, 0, COIN_AGE_CACHE_ZERO, false, /*extra_weight=*/0, 0, lp);
782 LOCK(m_node.mempool->cs);
783 return m_node.mempool->CheckPackageLimits({tx}, entry.GetTxSize());
784 }
785 CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
786 {
787 if (!m_node.fee_estimator) return {};
788 return m_node.fee_estimator->estimateSmartFee(num_blocks, calc, conservative);
789 }
790 unsigned int estimateMaxBlocks() override
791 {
792 if (!m_node.fee_estimator) return 0;
793 return m_node.fee_estimator->HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
794 }
795 CFeeRate mempoolMinFee() override
796 {
797 if (!m_node.mempool) return {};
798 return m_node.mempool->GetMinFee();
799 }
800 CFeeRate relayMinFee() override
801 {
802 if (!m_node.mempool) return CFeeRate{DEFAULT_MIN_RELAY_TX_FEE};
803 return m_node.mempool->m_opts.min_relay_feerate;
804 }
805 CFeeRate relayIncrementalFee() override
806 {
807 if (!m_node.mempool) return CFeeRate{DEFAULT_INCREMENTAL_RELAY_FEE};
808 return m_node.mempool->m_opts.incremental_relay_feerate;
809 }
810 CFeeRate relayDustFee() override
811 {
812 if (!m_node.mempool) return CFeeRate{DUST_RELAY_TX_FEE};
813 return m_node.mempool->m_opts.dust_relay_feerate;
814 }
815 bool havePruned() override
816 {
817 LOCK(::cs_main);
818 return chainman().m_blockman.m_have_pruned;
819 }
820 std::optional<int> getPruneHeight() override
821 {
822 LOCK(chainman().GetMutex());
823 return GetPruneHeight(chainman().m_blockman, chainman().ActiveChain());
824 }
825 bool isReadyToBroadcast() override { return !chainman().m_blockman.LoadingBlocks() && !isInitialBlockDownload(); }
826 bool isInitialBlockDownload() override
827 {
828 return chainman().IsInitialBlockDownload();
829 }
830 bool shutdownRequested() override { return ShutdownRequested(m_node); }
831 void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); }
832 void initWarning(const bilingual_str& message) override { InitWarning(message); }
833 void initError(const bilingual_str& message) override { InitError(message); }
834 bool initQuestion(const bilingual_str& message, const bilingual_str& non_interactive_message, const bilingual_str& caption, unsigned int style) override {
835 return uiInterface.ThreadSafeQuestion(message, non_interactive_message.translated, caption.translated, style);
836 }
837 void showProgress(const std::string& title, int progress, bool resume_possible) override
838 {
839 ::uiInterface.ShowProgress(title, progress, resume_possible);
840 }
841 std::unique_ptr<Handler> handleNotifications(std::shared_ptr<Notifications> notifications) override
842 {
843 return std::make_unique<NotificationsHandlerImpl>(validation_signals(), std::move(notifications));
844 }
845 void waitForNotificationsIfTipChanged(const uint256& old_tip) override
846 {
847 if (!old_tip.IsNull() && old_tip == WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()->GetBlockHash())) return;
848 validation_signals().SyncWithValidationInterfaceQueue();
849 }
850 void waitForNotifications() override
851 {
852 validation_signals().SyncWithValidationInterfaceQueue();
853 }
854 std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
855 {
856 return std::make_unique<RpcHandlerImpl>(command);
857 }
858 bool rpcEnableDeprecated(const std::string& method) override { return IsDeprecatedRPCEnabled(method); }
859 void rpcRunLater(const std::string& name, std::function<void()> fn, int64_t seconds) override
860 {
861 RPCRunLater(name, std::move(fn), seconds);
862 }
863 common::SettingsValue getSetting(const std::string& name) override
864 {
865 return args().GetSetting(name);
866 }
867 std::vector<common::SettingsValue> getSettingsList(const std::string& name) override
868 {
869 return args().GetSettingsList(name);
870 }
871 common::SettingsValue getRwSetting(const std::string& name) override
872 {
873 common::SettingsValue result;
874 args().LockSettings([&](const common::Settings& settings) {
875 if (const common::SettingsValue* value = common::FindKey(settings.rw_settings, name)) {
876 result = *value;
877 }
878 });
879 return result;
880 }
881 bool updateRwSetting(const std::string& name,
882 const interfaces::SettingsUpdate& update_settings_func) override
883 {
884 std::optional<interfaces::SettingsAction> action;
885 args().LockSettings([&](common::Settings& settings) {
886 if (auto* value = common::FindKey(settings.rw_settings, name)) {
887 action = update_settings_func(*value);
888 if (value->isNull()) settings.rw_settings.erase(name);
889 } else {
890 UniValue new_value;
891 action = update_settings_func(new_value);
892 if (!new_value.isNull()) settings.rw_settings[name] = std::move(new_value);
893 }
894 });
895 if (!action) return false;
896 // Now dump value to disk if requested
897 return *action != interfaces::SettingsAction::WRITE || args().WriteSettingsFile();
898 }
899 bool overwriteRwSetting(const std::string& name, common::SettingsValue value, interfaces::SettingsAction action) override
900 {
901 return updateRwSetting(name, [&](common::SettingsValue& settings) {
902 settings = std::move(value);
903 return action;
904 });
905 }
906 bool deleteRwSettings(const std::string& name, interfaces::SettingsAction action) override
907 {
908 return overwriteRwSetting(name, {}, action);
909 }
910 void requestMempoolTransactions(Notifications& notifications) override
911 {
912 if (!m_node.mempool) return;
913 LOCK2(::cs_main, m_node.mempool->cs);
914 for (const CTxMemPoolEntry& entry : m_node.mempool->entryAll()) {
915 notifications.transactionAddedToMempool(entry.GetSharedTx());
916 }
917 }
918 bool hasAssumedValidChain() override
919 {
920 return chainman().IsSnapshotActive();
921 }
922
923 NodeContext* context() override { return &m_node; }
924 ArgsManager& args() { return *Assert(m_node.args); }
925 ChainstateManager& chainman() { return *Assert(m_node.chainman); }
926 ValidationSignals& validation_signals() { return *Assert(m_node.validation_signals); }
927 NodeContext& m_node;
928 };
929
930 class BlockTemplateImpl : public BlockTemplate
931 {
932 public:
933 explicit BlockTemplateImpl(std::shared_ptr<CBlockTemplate> block_template, NodeContext& node) : m_block_template(std::move(block_template)), m_node(node)
934 {
935 assert(m_block_template);
936 }
937
938 const CBlockHeader& getBlockHeader() const override
939 {
940 return m_block_template->block;
941 }
942
943 const CBlock& getBlock() const override
944 {
945 return m_block_template->block;
946 }
947
948 const std::vector<CAmount>& getTxFees() const override
949 {
950 return m_block_template->vTxFees;
951 }
952
953 const std::vector<int64_t>& getTxSigops() const override
954 {
955 return m_block_template->vTxSigOpsCost;
956 }
957
958 const std::vector<double>& getTxCoinAgePriorities() const override
959 {
960 return m_block_template->vTxPriorities;
961 }
962
963 CTransactionRef getCoinbaseTx() const override
964 {
965 return m_block_template->block.vtx[0];
966 }
967
968 const std::vector<unsigned char>& getCoinbaseCommitment() const override
969 {
970 return m_block_template->vchCoinbaseCommitment;
971 }
972
973 int getWitnessCommitmentIndex() const override
974 {
975 return GetWitnessCommitmentIndex(m_block_template->block);
976 }
977
978 std::vector<uint256> getCoinbaseMerklePath() const override
979 {
980 return TransactionMerklePath(m_block_template->block, 0);
981 }
982
983 bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CTransactionRef coinbase) override
984 {
985 CBlock block{m_block_template->block};
986
987 if (block.vtx.size() == 0) {
988 block.vtx.push_back(coinbase);
989 } else {
990 block.vtx[0] = coinbase;
991 }
992
993 block.nVersion = version;
994 block.nTime = timestamp;
995 block.nNonce = nonce;
996
997 block.hashMerkleRoot = BlockMerkleRoot(block);
998
999 auto block_ptr = std::make_shared<const CBlock>(block);
1000 return chainman().ProcessNewBlock(block_ptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/nullptr);
1001 }
1002
1003 const std::shared_ptr<CBlockTemplate> m_block_template;
1004
1005 ChainstateManager& chainman() { return *Assert(m_node.chainman); }
1006 NodeContext& m_node;
1007 };
1008
1009 class MinerImpl : public Mining
1010 {
1011 public:
1012 explicit MinerImpl(NodeContext& node) : m_node(node) {}
1013
1014 bool isTestChain() override
1015 {
1016 return chainman().GetParams().IsTestChain();
1017 }
1018
1019 bool isInitialBlockDownload() override
1020 {
1021 return chainman().IsInitialBlockDownload();
1022 }
1023
1024 std::optional<BlockRef> getTip() override
1025 {
1026 LOCK(::cs_main);
1027 CBlockIndex* tip{chainman().ActiveChain().Tip()};
1028 if (!tip) return {};
1029 return BlockRef{tip->GetBlockHash(), tip->nHeight};
1030 }
1031
1032 std::optional<BlockRef> waitTipChanged(uint256 current_tip, MillisecondsDouble timeout) override
1033 {
1034 if (timeout > std::chrono::years{100}) timeout = std::chrono::years{100}; // Upper bound to avoid UB in std::chrono
1035 auto deadline{std::chrono::steady_clock::now() + timeout};
1036 {
1037 WAIT_LOCK(notifications().m_tip_block_mutex, lock);
1038 // For callers convenience, wait longer than the provided timeout
1039 // during startup for the tip to be non-null. That way this function
1040 // always returns valid tip information when possible and only
1041 // returns null when shutting down, not when timing out.
1042 notifications().m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(notifications().m_tip_block_mutex) {
1043 return notifications().TipBlock() || chainman().m_interrupt;
1044 });
1045 if (chainman().m_interrupt) return {};
1046 // At this point TipBlock is set, so continue to wait until it is
1047 // different then `current_tip` provided by caller.
1048 notifications().m_tip_block_cv.wait_until(lock, deadline, [&]() EXCLUSIVE_LOCKS_REQUIRED(notifications().m_tip_block_mutex) {
1049 return Assume(notifications().TipBlock()) != current_tip || chainman().m_interrupt;
1050 });
1051 }
1052
1053 if (chainman().m_interrupt) return {};
1054
1055 // Must release m_tip_block_mutex before getTip() locks cs_main, to
1056 // avoid deadlocks.
1057 return getTip();
1058 }
1059
1060 std::unique_ptr<BlockTemplate> createNewBlock(const BlockCreateOptions& options) override
1061 {
1062 // Ensure m_tip_block is set so consumers of BlockTemplate can rely on that.
1063 if (!waitTipChanged(uint256::ZERO, MillisecondsDouble::max())) return {};
1064
1065 BlockAssembler::Options assemble_options{options};
1066 ApplyArgsManOptions(*Assert(m_node.args), assemble_options);
1067 return createNewBlock2(assemble_options);
1068 }
1069
1070 std::unique_ptr<BlockTemplate> createNewBlock2(const BlockCreateOptions& assemble_options) override
1071 {
1072 return std::make_unique<BlockTemplateImpl>(BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options, m_node}.CreateNewBlock(), m_node);
1073 }
1074
1075 NodeContext* context() override { return &m_node; }
1076 ChainstateManager& chainman() { return *Assert(m_node.chainman); }
1077 KernelNotifications& notifications() { return *Assert(m_node.notifications); }
1078 NodeContext& m_node;
1079 };
1080 } // namespace
1081 } // namespace node
1082
1083 namespace interfaces {
1084 std::unique_ptr<Node> MakeNode(node::NodeContext& context) { return std::make_unique<node::NodeImpl>(context); }
1085 std::unique_ptr<Chain> MakeChain(node::NodeContext& context) { return std::make_unique<node::ChainImpl>(context); }
1086 std::unique_ptr<Mining> MakeMining(node::NodeContext& context) { return std::make_unique<node::MinerImpl>(context); }
1087 } // namespace interfaces
1088