/ src / rpc / mining.cpp
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  }