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