mining.cpp raw

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