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