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 : }
|