mining.cpp raw
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-present The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include <bitcoin-build-config.h> // IWYU pragma: keep
7
8 #include <interfaces/mining.h>
9
10 #include <addresstype.h>
11 #include <arith_uint256.h>
12 #include <chain.h>
13 #include <chainparams.h>
14 #include <chainparamsbase.h>
15 #include <consensus/amount.h>
16 #include <consensus/consensus.h>
17 #include <consensus/merkle.h>
18 #include <consensus/params.h>
19 #include <consensus/validation.h>
20 #include <core_io.h>
21 #include <crypto/hex_base.h>
22 #include <interfaces/types.h>
23 #include <key_io.h>
24 #include <net.h>
25 #include <netbase.h>
26 #include <node/blockstorage.h>
27 #include <node/context.h>
28 #include <node/miner.h>
29 #include <node/mining_args.h>
30 #include <node/mining_types.h>
31 #include <node/warnings.h>
32 #include <policy/feerate.h>
33 #include <policy/policy.h>
34 #include <pow.h>
35 #include <primitives/block.h>
36 #include <primitives/transaction.h>
37 #include <rpc/blockchain.h>
38 #include <rpc/mining.h>
39 #include <rpc/protocol.h>
40 #include <rpc/request.h>
41 #include <rpc/server.h>
42 #include <rpc/server_util.h>
43 #include <rpc/util.h>
44 #include <script/descriptor.h>
45 #include <script/script.h>
46 #include <script/signingprovider.h>
47 #include <serialize.h>
48 #include <streams.h>
49 #include <sync.h>
50 #include <tinyformat.h>
51 #include <txmempool.h>
52 #include <uint256.h>
53 #include <univalue.h>
54 #include <util/chaintype.h>
55 #include <util/check.h>
56 #include <util/signalinterrupt.h>
57 #include <util/strencodings.h>
58 #include <util/string.h>
59 #include <util/time.h>
60 #include <validation.h>
61 #include <validationinterface.h>
62 #include <versionbits.h>
63
64 #include <algorithm>
65 #include <cstddef>
66 #include <cstdint>
67 #include <functional>
68 #include <initializer_list>
69 #include <limits>
70 #include <map>
71 #include <memory>
72 #include <optional>
73 #include <set>
74 #include <span>
75 #include <string>
76 #include <string_view>
77 #include <utility>
78 #include <vector>
79
80 using interfaces::BlockRef;
81 using interfaces::BlockTemplate;
82 using interfaces::Mining;
83 using node::BlockAssembler;
84 using node::GetMinimumTime;
85 using node::NodeContext;
86 using node::RegenerateCommitments;
87 using node::UpdateTime;
88 using util::ToString;
89
90 /**
91 * Return average network hashes per second based on the last 'lookup' blocks,
92 * or from the last difficulty change if 'lookup' is -1.
93 * If 'height' is -1, compute the estimate from current chain tip.
94 * If 'height' is a valid block height, compute the estimate at the time when a given block was found.
95 */
96 static UniValue GetNetworkHashPS(int lookup, int height, const CChain& active_chain) {
97 if (lookup < -1 || lookup == 0) {
98 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid nblocks. Must be a positive number or -1.");
99 }
100
101 if (height < -1 || height > active_chain.Height()) {
102 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block does not exist at specified height");
103 }
104
105 const CBlockIndex* pb = active_chain.Tip();
106
107 if (height >= 0) {
108 pb = active_chain[height];
109 }
110
111 if (pb == nullptr || !pb->nHeight)
112 return 0;
113
114 // If lookup is -1, then use blocks since last difficulty change.
115 if (lookup == -1)
116 lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval() + 1;
117
118 // If lookup is larger than chain, then set it to chain length.
119 if (lookup > pb->nHeight)
120 lookup = pb->nHeight;
121
122 const CBlockIndex* pb0 = pb;
123 int64_t minTime = pb0->GetBlockTime();
124 int64_t maxTime = minTime;
125 for (int i = 0; i < lookup; i++) {
126 pb0 = pb0->pprev;
127 int64_t time = pb0->GetBlockTime();
128 minTime = std::min(time, minTime);
129 maxTime = std::max(time, maxTime);
130 }
131
132 // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
133 if (minTime == maxTime)
134 return 0;
135
136 arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork;
137 int64_t timeDiff = maxTime - minTime;
138
139 return workDiff.getdouble() / timeDiff;
140 }
141
142 static RPCMethod getnetworkhashps()
143 {
144 return RPCMethod{
145 "getnetworkhashps",
146 "Returns the estimated network hashes per second based on the last n blocks.\n"
147 "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
148 "Pass in [height] to estimate the network speed at the time when a certain block was found.\n",
149 {
150 {"nblocks", RPCArg::Type::NUM, RPCArg::Default{120}, "The number of previous blocks to calculate estimate from, or -1 for blocks since last difficulty change."},
151 {"height", RPCArg::Type::NUM, RPCArg::Default{-1}, "To estimate at the time of the given height."},
152 },
153 RPCResult{
154 RPCResult::Type::NUM, "", "Hashes per second estimated"},
155 RPCExamples{
156 HelpExampleCli("getnetworkhashps", "")
157 + HelpExampleRpc("getnetworkhashps", "")
158 },
159 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
160 {
161 ChainstateManager& chainman = EnsureAnyChainman(request.context);
162 LOCK(cs_main);
163 return GetNetworkHashPS(self.Arg<int>("nblocks"), self.Arg<int>("height"), chainman.ActiveChain());
164 },
165 };
166 }
167
168 static bool GenerateBlock(ChainstateManager& chainman, CBlock&& block, uint64_t& max_tries, std::shared_ptr<const CBlock>& block_out, bool process_new_block)
169 {
170 block_out.reset();
171 block.hashMerkleRoot = BlockMerkleRoot(block);
172
173 while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainman.GetConsensus()) && !chainman.m_interrupt) {
174 ++block.nNonce;
175 --max_tries;
176 }
177 if (max_tries == 0 || chainman.m_interrupt) {
178 return false;
179 }
180 if (block.nNonce == std::numeric_limits<uint32_t>::max()) {
181 return true;
182 }
183
184 block_out = std::make_shared<const CBlock>(std::move(block));
185
186 if (!process_new_block) return true;
187
188 if (!chainman.ProcessNewBlock(block_out, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) {
189 throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
190 }
191
192 return true;
193 }
194
195 static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const CScript& coinbase_output_script, int nGenerate, uint64_t nMaxTries)
196 {
197 UniValue blockHashes(UniValue::VARR);
198 while (nGenerate > 0 && !chainman.m_interrupt) {
199 std::unique_ptr<BlockTemplate> block_template(miner.createNewBlock({ .coinbase_output_script = coinbase_output_script }, /*cooldown=*/false));
200 CHECK_NONFATAL(block_template);
201
202 std::shared_ptr<const CBlock> block_out;
203 if (!GenerateBlock(chainman, block_template->getBlock(), nMaxTries, block_out, /*process_new_block=*/true)) {
204 break;
205 }
206
207 if (block_out) {
208 --nGenerate;
209 blockHashes.push_back(block_out->GetHash().GetHex());
210 }
211 }
212 return blockHashes;
213 }
214
215 static bool getScriptFromDescriptor(std::string_view descriptor, CScript& script, std::string& error)
216 {
217 FlatSigningProvider key_provider;
218 const auto descs = Parse(descriptor, key_provider, error, /* require_checksum = */ false);
219 if (descs.empty()) return false;
220 if (descs.size() > 1) {
221 throw JSONRPCError(RPC_INVALID_PARAMETER, "Multipath descriptor not accepted");
222 }
223 const auto& desc = descs.at(0);
224 if (desc->IsRange()) {
225 throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?");
226 }
227
228 FlatSigningProvider provider;
229 std::vector<CScript> scripts;
230 if (!desc->Expand(0, key_provider, scripts, provider)) {
231 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot derive script without private keys");
232 }
233
234 // Combo descriptors can have 2 or 4 scripts, so we can't just check scripts.size() == 1
235 CHECK_NONFATAL(scripts.size() > 0 && scripts.size() <= 4);
236
237 if (scripts.size() == 1) {
238 script = scripts.at(0);
239 } else if (scripts.size() == 4) {
240 // For uncompressed keys, take the 3rd script, since it is p2wpkh
241 script = scripts.at(2);
242 } else {
243 // Else take the 2nd script, since it is p2pkh
244 script = scripts.at(1);
245 }
246
247 return true;
248 }
249
250 static RPCMethod generatetodescriptor()
251 {
252 return RPCMethod{
253 "generatetodescriptor",
254 "Mine to a specified descriptor and return the block hashes.",
255 {
256 {"num_blocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated."},
257 {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor to send the newly generated bitcoin to."},
258 {"maxtries", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_MAX_TRIES}, "How many iterations to try."},
259 },
260 RPCResult{
261 RPCResult::Type::ARR, "", "hashes of blocks generated",
262 {
263 {RPCResult::Type::STR_HEX, "", "blockhash"},
264 }
265 },
266 RPCExamples{
267 "\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
268 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
269 {
270 const auto num_blocks{self.Arg<int>("num_blocks")};
271 const auto max_tries{self.Arg<uint64_t>("maxtries")};
272
273 CScript coinbase_output_script;
274 std::string error;
275 if (!getScriptFromDescriptor(self.Arg<std::string_view>("descriptor"), coinbase_output_script, error)) {
276 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
277 }
278
279 NodeContext& node = EnsureAnyNodeContext(request.context);
280 Mining& miner = EnsureMining(node);
281 ChainstateManager& chainman = EnsureChainman(node);
282
283 return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
284 },
285 };
286 }
287
288 static RPCMethod generate()
289 {
290 return RPCMethod{"generate", "has been replaced by the -generate cli option. Refer to -help for more information.", {}, {}, RPCExamples{""}, [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue {
291 throw JSONRPCError(RPC_METHOD_NOT_FOUND, self.ToString());
292 }};
293 }
294
295 static RPCMethod generatetoaddress()
296 {
297 return RPCMethod{"generatetoaddress",
298 "Mine to a specified address and return the block hashes.",
299 {
300 {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated."},
301 {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The address to send the newly generated bitcoin to."},
302 {"maxtries", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_MAX_TRIES}, "How many iterations to try."},
303 },
304 RPCResult{
305 RPCResult::Type::ARR, "", "hashes of blocks generated",
306 {
307 {RPCResult::Type::STR_HEX, "", "blockhash"},
308 }},
309 RPCExamples{
310 "\nGenerate 11 blocks to myaddress\n"
311 + HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
312 + "If you are using the " CLIENT_NAME " wallet, you can get a new address to send the newly generated bitcoin to with:\n"
313 + HelpExampleCli("getnewaddress", "")
314 },
315 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
316 {
317 const int num_blocks{request.params[0].getInt<int>()};
318 const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].getInt<int>()};
319
320 CTxDestination destination = DecodeDestination(request.params[1].get_str());
321 if (!IsValidDestination(destination)) {
322 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
323 }
324
325 NodeContext& node = EnsureAnyNodeContext(request.context);
326 Mining& miner = EnsureMining(node);
327 ChainstateManager& chainman = EnsureChainman(node);
328
329 CScript coinbase_output_script = GetScriptForDestination(destination);
330
331 return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
332 },
333 };
334 }
335
336 static RPCMethod generateblock()
337 {
338 return RPCMethod{"generateblock",
339 "Mine a set of ordered transactions to a specified address or descriptor and return the block hash.\n"
340 "Transaction fees are not collected in the block reward.",
341 {
342 {"output", RPCArg::Type::STR, RPCArg::Optional::NO, "The address or descriptor to send the newly generated bitcoin to."},
343 {"transactions", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings which are either txids or raw transactions.\n"
344 "Txids must reference transactions currently in the mempool.\n"
345 "All transactions must be valid and in valid order, otherwise the block will be rejected.",
346 {
347 {"rawtx/txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
348 },
349 },
350 {"submit", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to submit the block before the RPC call returns or to return it as hex."},
351 },
352 RPCResult{
353 RPCResult::Type::OBJ, "", "",
354 {
355 {RPCResult::Type::STR_HEX, "hash", "hash of generated block"},
356 {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "hex of generated block, only present when submit=false"},
357 }
358 },
359 RPCExamples{
360 "\nGenerate a block to myaddress, with txs rawtx and mempool_txid\n"
361 + HelpExampleCli("generateblock", R"("myaddress" '["rawtx", "mempool_txid"]')")
362 },
363 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
364 {
365 const auto address_or_descriptor = request.params[0].get_str();
366 CScript coinbase_output_script;
367 std::string error;
368
369 if (!getScriptFromDescriptor(address_or_descriptor, coinbase_output_script, error)) {
370 const auto destination = DecodeDestination(address_or_descriptor);
371 if (!IsValidDestination(destination)) {
372 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address or descriptor");
373 }
374
375 coinbase_output_script = GetScriptForDestination(destination);
376 }
377
378 NodeContext& node = EnsureAnyNodeContext(request.context);
379 Mining& miner = EnsureMining(node);
380 const CTxMemPool& mempool = EnsureMemPool(node);
381
382 std::vector<CTransactionRef> txs;
383 const auto raw_txs_or_txids = request.params[1].get_array();
384 for (size_t i = 0; i < raw_txs_or_txids.size(); i++) {
385 const auto& str{raw_txs_or_txids[i].get_str()};
386
387 CMutableTransaction mtx;
388 if (auto txid{Txid::FromHex(str)}) {
389 const auto tx{mempool.get(*txid)};
390 if (!tx) {
391 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Transaction %s not in mempool.", str));
392 }
393
394 txs.emplace_back(tx);
395
396 } else if (DecodeHexTx(mtx, str)) {
397 txs.push_back(MakeTransactionRef(std::move(mtx)));
398
399 } else {
400 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("Transaction decode failed for %s. Make sure the tx has at least one input.", str));
401 }
402 }
403
404 const bool process_new_block{request.params[2].isNull() ? true : request.params[2].get_bool()};
405 CBlock block;
406
407 ChainstateManager& chainman = EnsureChainman(node);
408 {
409 LOCK(chainman.GetMutex());
410 {
411 std::unique_ptr<BlockTemplate> block_template{miner.createNewBlock({.use_mempool = false, .coinbase_output_script = coinbase_output_script}, /*cooldown=*/false)};
412 CHECK_NONFATAL(block_template);
413
414 block = block_template->getBlock();
415 }
416
417 CHECK_NONFATAL(block.vtx.size() == 1);
418
419 // Add transactions
420 block.vtx.insert(block.vtx.end(), txs.begin(), txs.end());
421 RegenerateCommitments(block, chainman);
422
423 if (BlockValidationState state{TestBlockValidity(chainman.ActiveChainstate(), block, /*check_pow=*/false, /*check_merkle_root=*/false)}; !state.IsValid()) {
424 throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
425 }
426 }
427
428 std::shared_ptr<const CBlock> block_out;
429 uint64_t max_tries{DEFAULT_MAX_TRIES};
430
431 if (!GenerateBlock(chainman, std::move(block), max_tries, block_out, process_new_block) || !block_out) {
432 throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
433 }
434
435 UniValue obj(UniValue::VOBJ);
436 obj.pushKV("hash", block_out->GetHash().GetHex());
437 if (!process_new_block) {
438 DataStream block_ser;
439 block_ser << TX_WITH_WITNESS(*block_out);
440 obj.pushKV("hex", HexStr(block_ser));
441 }
442 return obj;
443 },
444 };
445 }
446
447 static RPCMethod getmininginfo()
448 {
449 return RPCMethod{
450 "getmininginfo",
451 "Returns a json object containing mining-related information.",
452 {},
453 RPCResult{
454 RPCResult::Type::OBJ, "", "",
455 {
456 {RPCResult::Type::NUM, "blocks", "The current block"},
457 {RPCResult::Type::NUM, "currentblockweight", /*optional=*/true, "The block weight (including reserved weight for block header, txs count and coinbase tx) of the last assembled block (only present if a block was ever assembled)"},
458 {RPCResult::Type::NUM, "currentblocktx", /*optional=*/true, "The number of block transactions (excluding coinbase) of the last assembled block (only present if a block was ever assembled)"},
459 {RPCResult::Type::STR_HEX, "bits", "The current nBits, compact representation of the block difficulty target"},
460 {RPCResult::Type::NUM, "difficulty", "The current difficulty"},
461 {RPCResult::Type::STR_HEX, "target", "The current target"},
462 {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"},
463 {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"},
464 {RPCResult::Type::STR_AMOUNT, "blockmintxfee", "Minimum feerate of packages selected for block inclusion in " + CURRENCY_UNIT + "/kvB"},
465 {RPCResult::Type::STR, "chain", "current network name (" LIST_CHAIN_NAMES ")"},
466 {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "The block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)"},
467 {RPCResult::Type::OBJ, "next", "The next block",
468 {
469 {RPCResult::Type::NUM, "height", "The next height"},
470 {RPCResult::Type::STR_HEX, "bits", "The next target nBits"},
471 {RPCResult::Type::NUM, "difficulty", "The next difficulty"},
472 {RPCResult::Type::STR_HEX, "target", "The next target"}
473 }},
474 (IsDeprecatedRPCEnabled("warnings") ?
475 RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} :
476 RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)",
477 {
478 {RPCResult::Type::STR, "", "warning"},
479 }
480 }
481 ),
482 }},
483 RPCExamples{
484 HelpExampleCli("getmininginfo", "")
485 + HelpExampleRpc("getmininginfo", "")
486 },
487 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
488 {
489 NodeContext& node = EnsureAnyNodeContext(request.context);
490 const CTxMemPool& mempool = EnsureMemPool(node);
491 ChainstateManager& chainman = EnsureChainman(node);
492 LOCK(cs_main);
493 const CChain& active_chain = chainman.ActiveChain();
494 CBlockIndex& tip{*CHECK_NONFATAL(active_chain.Tip())};
495
496 UniValue obj(UniValue::VOBJ);
497 obj.pushKV("blocks", active_chain.Height());
498 if (BlockAssembler::m_last_block_weight) obj.pushKV("currentblockweight", *BlockAssembler::m_last_block_weight);
499 if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs);
500 obj.pushKV("bits", strprintf("%08x", tip.nBits));
501 obj.pushKV("difficulty", GetDifficulty(tip));
502 obj.pushKV("target", GetTarget(tip, chainman.GetConsensus().powLimit).GetHex());
503 obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request));
504 obj.pushKV("pooledtx", mempool.size());
505 const auto mining_options{node::FlattenMiningOptions(node.mining_args)};
506 obj.pushKV("blockmintxfee", ValueFromAmount(CHECK_NONFATAL(mining_options.block_min_fee_rate)->GetFeePerK()));
507 obj.pushKV("chain", chainman.GetParams().GetChainTypeString());
508
509 UniValue next(UniValue::VOBJ);
510 CBlockIndex next_index;
511 NextEmptyBlockIndex(tip, chainman.GetConsensus(), next_index);
512
513 next.pushKV("height", next_index.nHeight);
514 next.pushKV("bits", strprintf("%08x", next_index.nBits));
515 next.pushKV("difficulty", GetDifficulty(next_index));
516 next.pushKV("target", GetTarget(next_index, chainman.GetConsensus().powLimit).GetHex());
517 obj.pushKV("next", next);
518
519 if (chainman.GetParams().GetChainType() == ChainType::SIGNET) {
520 const std::vector<uint8_t>& signet_challenge =
521 chainman.GetConsensus().signet_challenge;
522 obj.pushKV("signet_challenge", HexStr(signet_challenge));
523 }
524 obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings")));
525 return obj;
526 },
527 };
528 }
529
530
531 // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
532 static RPCMethod prioritisetransaction()
533 {
534 return RPCMethod{"prioritisetransaction",
535 "Accepts the transaction into mined blocks at a higher (or lower) priority\n",
536 {
537 {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id."},
538 {"dummy", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "API-Compatibility for previous API. Must be zero or null.\n"
539 " DEPRECATED. For forward compatibility use named arguments and omit this parameter."},
540 {"fee_delta", RPCArg::Type::NUM, RPCArg::Optional::NO, "The fee value (in satoshis) to add (or subtract, if negative).\n"
541 " Note, that this value is not a fee rate. It is a value to modify absolute fee of the TX.\n"
542 " The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
543 " considers the transaction as it would have paid a higher (or lower) fee."},
544 },
545 RPCResult{
546 RPCResult::Type::BOOL, "", "Returns true"},
547 RPCExamples{
548 HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
549 + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
550 },
551 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
552 {
553 LOCK(cs_main);
554
555 auto txid{Txid::FromUint256(ParseHashV(request.params[0], "txid"))};
556 const auto dummy{self.MaybeArg<double>("dummy")};
557 CAmount nAmount = request.params[2].getInt<int64_t>();
558
559 if (dummy && *dummy != 0) {
560 throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.");
561 }
562
563 CTxMemPool& mempool = EnsureAnyMemPool(request.context);
564
565 // Non-0 fee dust transactions are not allowed for entry, and modification not allowed afterwards
566 const auto& tx = mempool.get(txid);
567 if (mempool.m_opts.require_standard && tx && !GetDust(*tx, mempool.m_opts.dust_relay_feerate).empty()) {
568 throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is not supported for transactions with dust outputs.");
569 }
570
571 mempool.PrioritiseTransaction(txid, nAmount);
572 return true;
573 },
574 };
575 }
576
577 static RPCMethod getprioritisedtransactions()
578 {
579 return RPCMethod{"getprioritisedtransactions",
580 "Returns a map of all user-created (see prioritisetransaction) fee deltas by txid, and whether the tx is present in mempool.",
581 {},
582 RPCResult{
583 RPCResult::Type::OBJ_DYN, "", "prioritisation keyed by txid",
584 {
585 {RPCResult::Type::OBJ, "<transactionid>", "", {
586 {RPCResult::Type::NUM, "fee_delta", "transaction fee delta in satoshis"},
587 {RPCResult::Type::BOOL, "in_mempool", "whether this transaction is currently in mempool"},
588 {RPCResult::Type::NUM, "modified_fee", /*optional=*/true, "modified fee in satoshis. Only returned if in_mempool=true"},
589 }}
590 },
591 },
592 RPCExamples{
593 HelpExampleCli("getprioritisedtransactions", "")
594 + HelpExampleRpc("getprioritisedtransactions", "")
595 },
596 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
597 {
598 NodeContext& node = EnsureAnyNodeContext(request.context);
599 CTxMemPool& mempool = EnsureMemPool(node);
600 UniValue rpc_result{UniValue::VOBJ};
601 for (const auto& delta_info : mempool.GetPrioritisedTransactions()) {
602 UniValue result_inner{UniValue::VOBJ};
603 result_inner.pushKV("fee_delta", delta_info.delta);
604 result_inner.pushKV("in_mempool", delta_info.in_mempool);
605 if (delta_info.in_mempool) {
606 result_inner.pushKV("modified_fee", *delta_info.modified_fee);
607 }
608 rpc_result.pushKV(delta_info.txid.GetHex(), std::move(result_inner));
609 }
610 return rpc_result;
611 },
612 };
613 }
614
615
616 // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
617 static UniValue BIP22ValidationResult(const BlockValidationState& state)
618 {
619 if (state.IsValid())
620 return UniValue::VNULL;
621
622 if (state.IsError())
623 throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
624 if (state.IsInvalid())
625 {
626 std::string strRejectReason = state.GetRejectReason();
627 if (strRejectReason.empty())
628 return "rejected";
629 return strRejectReason;
630 }
631 // Should be impossible
632 return "valid?";
633 }
634
635 // Prefix rule name with ! if not optional, see BIP9
636 static std::string gbt_rule_value(const std::string& name, bool gbt_optional_rule)
637 {
638 std::string s{name};
639 if (!gbt_optional_rule) {
640 s.insert(s.begin(), '!');
641 }
642 return s;
643 }
644
645 static RPCMethod getblocktemplate()
646 {
647 return RPCMethod{
648 "getblocktemplate",
649 "If the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
650 "It returns data needed to construct a block to work on.\n"
651 "For full specification, see BIPs 22, 23, 9, and 145:\n"
652 " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
653 " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
654 " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
655 " https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
656 {
657 {"template_request", RPCArg::Type::OBJ, RPCArg::Optional::NO, "Format of the template",
658 {
659 {"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
660 {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED, "A list of strings",
661 {
662 {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported feature, 'longpoll', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
663 }},
664 {"rules", RPCArg::Type::ARR, RPCArg::Optional::NO, "A list of strings",
665 {
666 {"segwit", RPCArg::Type::STR, RPCArg::Optional::NO, "(literal) indicates client side segwit support"},
667 {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "other client side supported softfork deployment"},
668 }},
669 {"longpollid", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "delay processing request until the result would vary significantly from the \"longpollid\" of a prior template"},
670 {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "proposed block data to check, encoded in hexadecimal; valid only for mode=\"proposal\""},
671 },
672 },
673 },
674 {
675 RPCResult{"If the proposal was accepted with mode=='proposal'", RPCResult::Type::NONE, "", ""},
676 RPCResult{"If the proposal was not accepted with mode=='proposal'", RPCResult::Type::STR, "", "According to BIP22"},
677 RPCResult{"Otherwise", RPCResult::Type::OBJ, "", "",
678 {
679 {RPCResult::Type::NUM, "version", "The preferred block version"},
680 {RPCResult::Type::ARR, "rules", "specific block rules that are to be enforced",
681 {
682 {RPCResult::Type::STR, "", "name of a rule the client must understand to some extent; see BIP 9 for format"},
683 }},
684 {RPCResult::Type::OBJ_DYN, "vbavailable", "set of pending, supported versionbit (BIP 9) softfork deployments",
685 {
686 {RPCResult::Type::NUM, "rulename", "identifies the bit number as indicating acceptance and readiness for the named softfork rule"},
687 }},
688 {RPCResult::Type::ARR, "capabilities", "",
689 {
690 {RPCResult::Type::STR, "value", "A supported feature, for example 'proposal'"},
691 }},
692 {RPCResult::Type::NUM, "vbrequired", "bit mask of versionbits the server requires set in submissions"},
693 {RPCResult::Type::STR, "previousblockhash", "The hash of current highest block"},
694 {RPCResult::Type::ARR, "transactions", "contents of non-coinbase transactions that should be included in the next block",
695 {
696 {RPCResult::Type::OBJ, "", "",
697 {
698 {RPCResult::Type::STR_HEX, "data", "transaction data encoded in hexadecimal (byte-for-byte)"},
699 {RPCResult::Type::STR_HEX, "txid", "transaction hash excluding witness data, shown in byte-reversed hex"},
700 {RPCResult::Type::STR_HEX, "hash", "transaction hash including witness data, shown in byte-reversed hex"},
701 {RPCResult::Type::ARR, "depends", "array of numbers",
702 {
703 {RPCResult::Type::NUM, "", "transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is"},
704 }},
705 {RPCResult::Type::NUM, "fee", "difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one"},
706 {RPCResult::Type::NUM, "sigops", "total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero"},
707 {RPCResult::Type::NUM, "weight", "total transaction weight, as counted for purposes of block limits"},
708 }},
709 }},
710 {RPCResult::Type::OBJ_DYN, "coinbaseaux", "data that should be included in the coinbase's scriptSig content",
711 {
712 {RPCResult::Type::STR_HEX, "key", "values must be in the coinbase (keys may be ignored)"},
713 }},
714 {RPCResult::Type::NUM, "coinbasevalue", "maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)"},
715 {RPCResult::Type::STR, "longpollid", "an id to include with a request to longpoll on an update to this template"},
716 {RPCResult::Type::STR, "target", "The hash target"},
717 {RPCResult::Type::NUM_TIME, "mintime", "The minimum timestamp appropriate for the next block time, expressed in " + UNIX_EPOCH_TIME + ". Adjusted for the proposed BIP94 timewarp rule."},
718 {RPCResult::Type::ARR, "mutable", "list of ways the block template may be changed",
719 {
720 {RPCResult::Type::STR, "value", "A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'"},
721 }},
722 {RPCResult::Type::STR_HEX, "noncerange", "A range of valid nonces"},
723 {RPCResult::Type::NUM, "sigoplimit", "limit of sigops in blocks"},
724 {RPCResult::Type::NUM, "sizelimit", "limit of block size"},
725 {RPCResult::Type::NUM, "weightlimit", /*optional=*/true, "limit of block weight"},
726 {RPCResult::Type::NUM_TIME, "curtime", "current timestamp in " + UNIX_EPOCH_TIME + ". Adjusted for the proposed BIP94 timewarp rule."},
727 {RPCResult::Type::STR, "bits", "compressed target of next block"},
728 {RPCResult::Type::NUM, "height", "The height of the next block"},
729 {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "Only on signet"},
730 {RPCResult::Type::STR_HEX, "default_witness_commitment", /*optional=*/true, "a valid witness commitment for the unmodified block template"},
731 }},
732 },
733 RPCExamples{
734 HelpExampleCli("getblocktemplate", "'{\"rules\": [\"segwit\"]}'")
735 + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}")
736 },
737 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
738 {
739 NodeContext& node = EnsureAnyNodeContext(request.context);
740 ChainstateManager& chainman = EnsureChainman(node);
741 Mining& miner = EnsureMining(node);
742
743 std::string strMode = "template";
744 UniValue lpval = NullUniValue;
745 std::set<std::string> setClientRules;
746 if (!request.params[0].isNull())
747 {
748 const UniValue& oparam = request.params[0].get_obj();
749 const UniValue& modeval = oparam.find_value("mode");
750 if (modeval.isStr())
751 strMode = modeval.get_str();
752 else if (modeval.isNull())
753 {
754 /* Do nothing */
755 }
756 else
757 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
758 lpval = oparam.find_value("longpollid");
759
760 if (strMode == "proposal")
761 {
762 const UniValue& dataval = oparam.find_value("data");
763 if (!dataval.isStr())
764 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
765
766 CBlock block;
767 if (!DecodeHexBlk(block, dataval.get_str()))
768 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
769
770 uint256 hash = block.GetHash();
771 LOCK(cs_main);
772 const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
773 if (pindex) {
774 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
775 return "duplicate";
776 if (pindex->nStatus & BLOCK_FAILED_VALID)
777 return "duplicate-invalid";
778 return "duplicate-inconclusive";
779 }
780
781 return BIP22ValidationResult(TestBlockValidity(chainman.ActiveChainstate(), block, /*check_pow=*/false, /*check_merkle_root=*/true));
782 }
783
784 const UniValue& aClientRules = oparam.find_value("rules");
785 if (aClientRules.isArray()) {
786 for (unsigned int i = 0; i < aClientRules.size(); ++i) {
787 const UniValue& v = aClientRules[i];
788 setClientRules.insert(v.get_str());
789 }
790 }
791 }
792
793 if (strMode != "template")
794 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
795
796 if (!miner.isTestChain()) {
797 const CConnman& connman = EnsureConnman(node);
798 if (connman.GetNodeCount(ConnectionDirection::Both) == 0) {
799 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, CLIENT_NAME " is not connected!");
800 }
801
802 if (miner.isInitialBlockDownload()) {
803 throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, CLIENT_NAME " is in initial sync and waiting for blocks...");
804 }
805 }
806
807 static unsigned int nTransactionsUpdatedLast;
808 const CTxMemPool& mempool = EnsureMemPool(node);
809
810 WAIT_LOCK(cs_main, cs_main_lock);
811 uint256 tip{CHECK_NONFATAL(miner.getTip()).value().hash};
812
813 // Long Polling (BIP22)
814 if (!lpval.isNull()) {
815 /**
816 * Wait to respond until either the best block changes, OR there are more
817 * transactions.
818 *
819 * The check for new transactions first happens after 1 minute and
820 * subsequently every 10 seconds. BIP22 does not require this particular interval.
821 * On mainnet the mempool changes frequently enough that in practice this RPC
822 * returns after 60 seconds, or sooner if the best block changes.
823 *
824 * getblocktemplate is unlikely to be called by bitcoin-cli, so
825 * -rpcclienttimeout is not a concern. BIP22 recommends a long request timeout.
826 *
827 * The longpollid is assumed to be a tip hash if it has the right format.
828 */
829 uint256 hashWatchedChain;
830 unsigned int nTransactionsUpdatedLastLP;
831
832 if (lpval.isStr())
833 {
834 // Format: <hashBestChain><nTransactionsUpdatedLast>
835 const std::string& lpstr = lpval.get_str();
836
837 // Assume the longpollid is a block hash. If it's not then we return
838 // early below.
839 hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
840 nTransactionsUpdatedLastLP = LocaleIndependentAtoi<int64_t>(lpstr.substr(64));
841 }
842 else
843 {
844 // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
845 hashWatchedChain = tip;
846 nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
847 }
848
849 // Release lock while waiting
850 {
851 REVERSE_LOCK(cs_main_lock, cs_main);
852 MillisecondsDouble checktxtime{std::chrono::minutes(1)};
853 while (IsRPCRunning()) {
854 // If hashWatchedChain is not a real block hash, this will
855 // return immediately.
856 std::optional<BlockRef> maybe_tip{miner.waitTipChanged(hashWatchedChain, checktxtime)};
857 // Node is shutting down
858 if (!maybe_tip) break;
859 tip = maybe_tip->hash;
860 if (tip != hashWatchedChain) break;
861
862 // Check transactions for update without holding the mempool
863 // lock to avoid deadlocks.
864 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP) {
865 break;
866 }
867 checktxtime = std::chrono::seconds(10);
868 }
869 }
870 tip = CHECK_NONFATAL(miner.getTip()).value().hash;
871
872 if (!IsRPCRunning())
873 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
874 // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
875 }
876
877 const Consensus::Params& consensusParams = chainman.GetParams().GetConsensus();
878
879 // GBT must be called with 'signet' set in the rules for signet chains
880 if (consensusParams.signet_blocks && !setClientRules.contains("signet")) {
881 throw JSONRPCError(RPC_INVALID_PARAMETER, "getblocktemplate must be called with the signet rule set (call with {\"rules\": [\"segwit\", \"signet\"]})");
882 }
883
884 // GBT must be called with 'segwit' set in the rules
885 if (!setClientRules.contains("segwit")) {
886 throw JSONRPCError(RPC_INVALID_PARAMETER, "getblocktemplate must be called with the segwit rule set (call with {\"rules\": [\"segwit\"]})");
887 }
888
889 // Update block
890 static CBlockIndex* pindexPrev;
891 static int64_t time_start;
892 static std::unique_ptr<BlockTemplate> block_template;
893 if (!pindexPrev || pindexPrev->GetBlockHash() != tip ||
894 (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
895 {
896 // Clear pindexPrev so future calls make a new block, despite any failures from here on
897 pindexPrev = nullptr;
898
899 // Store the pindexBest used before createNewBlock, to avoid races
900 nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
901 CBlockIndex* pindexPrevNew = chainman.m_blockman.LookupBlockIndex(tip);
902 time_start = GetTime();
903
904 // Create new block. Opt-out of cooldown mechanism, because it would add
905 // a delay to each getblocktemplate call. This differs from typical
906 // long-lived IPC usage, where the overhead is paid only when creating
907 // the initial template.
908 block_template = miner.createNewBlock({}, /*cooldown=*/false);
909 CHECK_NONFATAL(block_template);
910
911
912 // Need to update only after we know createNewBlock succeeded
913 pindexPrev = pindexPrevNew;
914 }
915 CHECK_NONFATAL(pindexPrev);
916 CBlock block{block_template->getBlock()};
917
918 // Update nTime
919 UpdateTime(&block, consensusParams, pindexPrev);
920 block.nNonce = 0;
921
922 // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
923 const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT);
924
925 UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
926
927 UniValue transactions(UniValue::VARR);
928 std::map<Txid, int64_t> setTxIndex;
929 std::vector<CAmount> tx_fees{block_template->getTxFees()};
930 std::vector<int64_t> tx_sigops{block_template->getTxSigops()};
931
932 int i = 0;
933 for (const auto& it : block.vtx) {
934 const CTransaction& tx = *it;
935 Txid txHash = tx.GetHash();
936 setTxIndex[txHash] = i++;
937
938 if (tx.IsCoinBase())
939 continue;
940
941 UniValue entry(UniValue::VOBJ);
942
943 entry.pushKV("data", EncodeHexTx(tx));
944 entry.pushKV("txid", txHash.GetHex());
945 entry.pushKV("hash", tx.GetWitnessHash().GetHex());
946
947 UniValue deps(UniValue::VARR);
948 for (const CTxIn &in : tx.vin)
949 {
950 if (setTxIndex.contains(in.prevout.hash))
951 deps.push_back(setTxIndex[in.prevout.hash]);
952 }
953 entry.pushKV("depends", std::move(deps));
954
955 int index_in_template = i - 2;
956 entry.pushKV("fee", tx_fees.at(index_in_template));
957 int64_t nTxSigOps{tx_sigops.at(index_in_template)};
958 if (fPreSegWit) {
959 CHECK_NONFATAL(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
960 nTxSigOps /= WITNESS_SCALE_FACTOR;
961 }
962 entry.pushKV("sigops", nTxSigOps);
963 entry.pushKV("weight", GetTransactionWeight(tx));
964
965 transactions.push_back(std::move(entry));
966 }
967
968 UniValue aux(UniValue::VOBJ);
969
970 arith_uint256 hashTarget = arith_uint256().SetCompact(block.nBits);
971
972 UniValue aMutable(UniValue::VARR);
973 aMutable.push_back("time");
974 aMutable.push_back("transactions");
975 aMutable.push_back("prevblock");
976
977 UniValue result(UniValue::VOBJ);
978 result.pushKV("capabilities", std::move(aCaps));
979
980 UniValue aRules(UniValue::VARR);
981 // See getblocktemplate changes in BIP 9:
982 // ! indicates a more subtle change to the block structure or generation transaction
983 // Otherwise clients may assume the rule will not impact usage of the template as-is.
984 aRules.push_back("csv");
985 if (!fPreSegWit) {
986 aRules.push_back("!segwit");
987 aRules.push_back("taproot");
988 }
989 if (consensusParams.signet_blocks) {
990 // indicate to miner that they must understand signet rules
991 // when attempting to mine with this template
992 aRules.push_back("!signet");
993 }
994
995 UniValue vbavailable(UniValue::VOBJ);
996 const auto gbtstatus = chainman.m_versionbitscache.GBTStatus(*pindexPrev, consensusParams);
997
998 for (const auto& [name, info] : gbtstatus.signalling) {
999 vbavailable.pushKV(gbt_rule_value(name, info.gbt_optional_rule), info.bit);
1000 if (!info.gbt_optional_rule && !setClientRules.contains(name)) {
1001 // If the client doesn't support this, don't indicate it in the [default] version
1002 block.nVersion &= ~info.mask;
1003 }
1004 }
1005
1006 for (const auto& [name, info] : gbtstatus.locked_in) {
1007 block.nVersion |= info.mask;
1008 vbavailable.pushKV(gbt_rule_value(name, info.gbt_optional_rule), info.bit);
1009 if (!info.gbt_optional_rule && !setClientRules.contains(name)) {
1010 // If the client doesn't support this, don't indicate it in the [default] version
1011 block.nVersion &= ~info.mask;
1012 }
1013 }
1014
1015 for (const auto& [name, info] : gbtstatus.active) {
1016 aRules.push_back(gbt_rule_value(name, info.gbt_optional_rule));
1017 if (!info.gbt_optional_rule && !setClientRules.contains(name)) {
1018 // Not supported by the client; make sure it's safe to proceed
1019 throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", name));
1020 }
1021 }
1022
1023 result.pushKV("version", block.nVersion);
1024 result.pushKV("rules", std::move(aRules));
1025 result.pushKV("vbavailable", std::move(vbavailable));
1026 result.pushKV("vbrequired", 0);
1027
1028 result.pushKV("previousblockhash", block.hashPrevBlock.GetHex());
1029 result.pushKV("transactions", std::move(transactions));
1030 result.pushKV("coinbaseaux", std::move(aux));
1031 result.pushKV("coinbasevalue", block.vtx[0]->vout[0].nValue);
1032 result.pushKV("longpollid", tip.GetHex() + ToString(nTransactionsUpdatedLast));
1033 result.pushKV("target", hashTarget.GetHex());
1034 result.pushKV("mintime", GetMinimumTime(pindexPrev, consensusParams.DifficultyAdjustmentInterval()));
1035 result.pushKV("mutable", std::move(aMutable));
1036 result.pushKV("noncerange", "00000000ffffffff");
1037 int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
1038 int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE;
1039 if (fPreSegWit) {
1040 CHECK_NONFATAL(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
1041 nSigOpLimit /= WITNESS_SCALE_FACTOR;
1042 CHECK_NONFATAL(nSizeLimit % WITNESS_SCALE_FACTOR == 0);
1043 nSizeLimit /= WITNESS_SCALE_FACTOR;
1044 }
1045 result.pushKV("sigoplimit", nSigOpLimit);
1046 result.pushKV("sizelimit", nSizeLimit);
1047 if (!fPreSegWit) {
1048 result.pushKV("weightlimit", MAX_BLOCK_WEIGHT);
1049 }
1050 result.pushKV("curtime", block.GetBlockTime());
1051 result.pushKV("bits", strprintf("%08x", block.nBits));
1052 result.pushKV("height", pindexPrev->nHeight + 1);
1053
1054 if (consensusParams.signet_blocks) {
1055 result.pushKV("signet_challenge", HexStr(consensusParams.signet_challenge));
1056 }
1057
1058 if (auto coinbase{block_template->getCoinbaseTx()}; coinbase.required_outputs.size() > 0) {
1059 CHECK_NONFATAL(coinbase.required_outputs.size() == 1); // Only one output is currently expected
1060 result.pushKV("default_witness_commitment", HexStr(coinbase.required_outputs[0].scriptPubKey));
1061 }
1062
1063 return result;
1064 },
1065 };
1066 }
1067
1068 class submitblock_StateCatcher final : public CValidationInterface
1069 {
1070 public:
1071 uint256 hash;
1072 bool found{false};
1073 BlockValidationState state;
1074
1075 explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), state() {}
1076
1077 protected:
1078 void BlockChecked(const std::shared_ptr<const CBlock>& block, const BlockValidationState& stateIn) override
1079 {
1080 if (block->GetHash() != hash) return;
1081 found = true;
1082 state = stateIn;
1083 }
1084 };
1085
1086 static RPCMethod submitblock()
1087 {
1088 // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored.
1089 return RPCMethod{
1090 "submitblock",
1091 "Attempts to submit new block to network.\n"
1092 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n",
1093 {
1094 {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"},
1095 {"dummy", RPCArg::Type::STR, RPCArg::DefaultHint{"ignored"}, "dummy value, for compatibility with BIP22. This value is ignored."},
1096 },
1097 {
1098 RPCResult{"If the block was accepted", RPCResult::Type::NONE, "", ""},
1099 RPCResult{"Otherwise", RPCResult::Type::STR, "", "According to BIP22"},
1100 },
1101 RPCExamples{
1102 HelpExampleCli("submitblock", "\"mydata\"")
1103 + HelpExampleRpc("submitblock", "\"mydata\"")
1104 },
1105 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1106 {
1107 std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
1108 CBlock& block = *blockptr;
1109 if (!DecodeHexBlk(block, request.params[0].get_str())) {
1110 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
1111 }
1112
1113 ChainstateManager& chainman = EnsureAnyChainman(request.context);
1114 {
1115 LOCK(cs_main);
1116 const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
1117 if (pindex) {
1118 chainman.UpdateUncommittedBlockStructures(block, pindex);
1119 }
1120 }
1121
1122 bool new_block;
1123 auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
1124 CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
1125 bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
1126 CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
1127 if (!new_block && accepted) {
1128 return "duplicate";
1129 }
1130 if (!sc->found) {
1131 return "inconclusive";
1132 }
1133 return BIP22ValidationResult(sc->state);
1134 },
1135 };
1136 }
1137
1138 static RPCMethod submitheader()
1139 {
1140 return RPCMethod{
1141 "submitheader",
1142 "Decode the given hexdata as a header and submit it as a candidate chain tip if valid."
1143 "\nThrows when the header is invalid.\n",
1144 {
1145 {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"},
1146 },
1147 RPCResult{
1148 RPCResult::Type::NONE, "", "None"},
1149 RPCExamples{
1150 HelpExampleCli("submitheader", "\"aabbcc\"") +
1151 HelpExampleRpc("submitheader", "\"aabbcc\"")
1152 },
1153 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1154 {
1155 CBlockHeader h;
1156 if (!DecodeHexBlockHeader(h, request.params[0].get_str())) {
1157 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block header decode failed");
1158 }
1159 ChainstateManager& chainman = EnsureAnyChainman(request.context);
1160 {
1161 LOCK(cs_main);
1162 if (!chainman.m_blockman.LookupBlockIndex(h.hashPrevBlock)) {
1163 throw JSONRPCError(RPC_VERIFY_ERROR, "Must submit previous header (" + h.hashPrevBlock.GetHex() + ") first");
1164 }
1165 }
1166
1167 BlockValidationState state;
1168 chainman.ProcessNewBlockHeaders({{h}}, /*min_pow_checked=*/true, state);
1169 if (state.IsValid()) return UniValue::VNULL;
1170 if (state.IsError()) {
1171 throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
1172 }
1173 throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason());
1174 },
1175 };
1176 }
1177
1178 void RegisterMiningRPCCommands(CRPCTable& t)
1179 {
1180 static const CRPCCommand commands[]{
1181 {"mining", &getnetworkhashps},
1182 {"mining", &getmininginfo},
1183 {"mining", &prioritisetransaction},
1184 {"mining", &getprioritisedtransactions},
1185 {"mining", &getblocktemplate},
1186 {"mining", &submitblock},
1187 {"mining", &submitheader},
1188
1189 {"hidden", &generatetoaddress},
1190 {"hidden", &generatetodescriptor},
1191 {"hidden", &generateblock},
1192 {"hidden", &generate},
1193 };
1194 for (const auto& c : commands) {
1195 t.appendCommand(c.name, &c);
1196 }
1197 }
1198