LCOV - code coverage report
Current view: top level - src/rpc - mining.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 946 1015 93.2 %
Date: 2022-04-21 14:51:19 Functions: 33 33 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 211 280 75.4 %

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

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a