Coverage Report

Created: 2026-09-02 14:16

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