LCOV - code coverage report
Current view: top level - src/rpc - mining.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 222 717 31.0 %
Date: 2023-09-26 12:08:55 Functions: 17 37 45.9 %

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

Generated by: LCOV version 1.14