LCOV - code coverage report
Current view: top level - src/rpc - mining.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 946 1019 92.8 %
Date: 2021-06-29 14:35:33 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: 209 284 73.6 %

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

Generated by: LCOV version 1.14