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