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