Coverage Report

Created: 2026-05-30 09:47

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