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