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