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