Coverage Report

Created: 2026-07-14 18:13

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