Coverage Report

Created: 2026-06-16 16:41

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.40k
{
144
2.40k
    return RPCMethod{
145
2.40k
        "getnetworkhashps",
146
2.40k
        "Returns the estimated network hashes per second based on the last n blocks.\n"
147
2.40k
                "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
148
2.40k
                "Pass in [height] to estimate the network speed at the time when a certain block was found.\n",
149
2.40k
                {
150
2.40k
                    {"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.40k
                    {"height", RPCArg::Type::NUM, RPCArg::Default{-1}, "To estimate at the time of the given height."},
152
2.40k
                },
153
2.40k
                RPCResult{
154
2.40k
                    RPCResult::Type::NUM, "", "Hashes per second estimated"},
155
2.40k
                RPCExamples{
156
2.40k
                    HelpExampleCli("getnetworkhashps", "")
157
2.40k
            + HelpExampleRpc("getnetworkhashps", "")
158
2.40k
                },
159
2.40k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
160
2.40k
{
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.40k
    };
166
2.40k
}
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
37.1k
{
170
37.1k
    block_out.reset();
171
37.1k
    block.hashMerkleRoot = BlockMerkleRoot(block);
172
173
1.07M
    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
37.1k
    if (max_tries == 0 || chainman.m_interrupt) {
178
1
        return false;
179
1
    }
180
37.1k
    if (block.nNonce == std::numeric_limits<uint32_t>::max()) {
181
0
        return true;
182
0
    }
183
184
37.1k
    block_out = std::make_shared<const CBlock>(std::move(block));
185
186
37.1k
    if (!process_new_block) return true;
187
188
37.1k
    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
37.1k
    return true;
193
37.1k
}
194
195
static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const CScript& coinbase_output_script, int nGenerate, uint64_t nMaxTries)
196
2.87k
{
197
2.87k
    UniValue blockHashes(UniValue::VARR);
198
39.7k
    while (nGenerate > 0 && !chainman.m_interrupt) {
199
36.8k
        std::unique_ptr<BlockTemplate> block_template(miner.createNewBlock({ .coinbase_output_script = coinbase_output_script }, /*cooldown=*/false));
200
36.8k
        CHECK_NONFATAL(block_template);
201
202
36.8k
        std::shared_ptr<const CBlock> block_out;
203
36.8k
        if (!GenerateBlock(chainman, block_template->getBlock(), nMaxTries, block_out, /*process_new_block=*/true)) {
204
1
            break;
205
1
        }
206
207
36.8k
        if (block_out) {
208
36.8k
            --nGenerate;
209
36.8k
            blockHashes.push_back(block_out->GetHash().GetHex());
210
36.8k
        }
211
36.8k
    }
212
2.87k
    return blockHashes;
213
2.87k
}
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
861
    if (descs.size() > 1) {
221
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Multipath descriptor not accepted");
222
0
    }
223
861
    const auto& desc = descs.at(0);
224
861
    if (desc->IsRange()) {
225
1
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?");
226
1
    }
227
228
860
    FlatSigningProvider provider;
229
860
    std::vector<CScript> scripts;
230
860
    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
859
    CHECK_NONFATAL(scripts.size() > 0 && scripts.size() <= 4);
236
237
859
    if (scripts.size() == 1) {
238
857
        script = scripts.at(0);
239
857
    } 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
859
    return true;
248
860
}
249
250
static RPCMethod generatetodescriptor()
251
3.17k
{
252
3.17k
    return RPCMethod{
253
3.17k
        "generatetodescriptor",
254
3.17k
        "Mine to a specified descriptor and return the block hashes.",
255
3.17k
        {
256
3.17k
            {"num_blocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated."},
257
3.17k
            {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor to send the newly generated bitcoin to."},
258
3.17k
            {"maxtries", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_MAX_TRIES}, "How many iterations to try."},
259
3.17k
        },
260
3.17k
        RPCResult{
261
3.17k
            RPCResult::Type::ARR, "", "hashes of blocks generated",
262
3.17k
            {
263
3.17k
                {RPCResult::Type::STR_HEX, "", "blockhash"},
264
3.17k
            }
265
3.17k
        },
266
3.17k
        RPCExamples{
267
3.17k
            "\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
268
3.17k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
269
3.17k
{
270
830
    const auto num_blocks{self.Arg<int>("num_blocks")};
271
830
    const auto max_tries{self.Arg<uint64_t>("maxtries")};
272
273
830
    CScript coinbase_output_script;
274
830
    std::string error;
275
830
    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
830
    NodeContext& node = EnsureAnyNodeContext(request.context);
280
830
    Mining& miner = EnsureMining(node);
281
830
    ChainstateManager& chainman = EnsureChainman(node);
282
283
830
    return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
284
830
},
285
3.17k
    };
286
3.17k
}
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.39k
{
297
4.39k
    return RPCMethod{"generatetoaddress",
298
4.39k
        "Mine to a specified address and return the block hashes.",
299
4.39k
         {
300
4.39k
             {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated."},
301
4.39k
             {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The address to send the newly generated bitcoin to."},
302
4.39k
             {"maxtries", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_MAX_TRIES}, "How many iterations to try."},
303
4.39k
         },
304
4.39k
         RPCResult{
305
4.39k
             RPCResult::Type::ARR, "", "hashes of blocks generated",
306
4.39k
             {
307
4.39k
                 {RPCResult::Type::STR_HEX, "", "blockhash"},
308
4.39k
             }},
309
4.39k
         RPCExamples{
310
4.39k
            "\nGenerate 11 blocks to myaddress\n"
311
4.39k
            + HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
312
4.39k
            + "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.39k
            + HelpExampleCli("getnewaddress", "")
314
4.39k
                },
315
4.39k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
316
4.39k
{
317
2.04k
    const int num_blocks{request.params[0].getInt<int>()};
318
2.04k
    const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].getInt<int>()};
319
320
2.04k
    CTxDestination destination = DecodeDestination(request.params[1].get_str());
321
2.04k
    if (!IsValidDestination(destination)) {
322
2
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
323
2
    }
324
325
2.04k
    NodeContext& node = EnsureAnyNodeContext(request.context);
326
2.04k
    Mining& miner = EnsureMining(node);
327
2.04k
    ChainstateManager& chainman = EnsureChainman(node);
328
329
2.04k
    CScript coinbase_output_script = GetScriptForDestination(destination);
330
331
2.04k
    return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
332
2.04k
},
333
4.39k
    };
334
4.39k
}
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.38k
{
449
2.38k
    return RPCMethod{
450
2.38k
        "getmininginfo",
451
2.38k
        "Returns a json object containing mining-related information.",
452
2.38k
                {},
453
2.38k
                RPCResult{
454
2.38k
                    RPCResult::Type::OBJ, "", "",
455
2.38k
                    {
456
2.38k
                        {RPCResult::Type::NUM, "blocks", "The current block"},
457
2.38k
                        {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.38k
                        {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.38k
                        {RPCResult::Type::STR_HEX, "bits", "The current nBits, compact representation of the block difficulty target"},
460
2.38k
                        {RPCResult::Type::NUM, "difficulty", "The current difficulty"},
461
2.38k
                        {RPCResult::Type::STR_HEX, "target", "The current target"},
462
2.38k
                        {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"},
463
2.38k
                        {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"},
464
2.38k
                        {RPCResult::Type::STR_AMOUNT, "blockmintxfee", "Minimum feerate of packages selected for block inclusion in " + CURRENCY_UNIT + "/kvB"},
465
2.38k
                        {RPCResult::Type::STR, "chain", "current network name (" LIST_CHAIN_NAMES ")"},
466
2.38k
                        {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.38k
                        {RPCResult::Type::OBJ, "next", "The next block",
468
2.38k
                        {
469
2.38k
                            {RPCResult::Type::NUM, "height", "The next height"},
470
2.38k
                            {RPCResult::Type::STR_HEX, "bits", "The next target nBits"},
471
2.38k
                            {RPCResult::Type::NUM, "difficulty", "The next difficulty"},
472
2.38k
                            {RPCResult::Type::STR_HEX, "target", "The next target"}
473
2.38k
                        }},
474
2.38k
                        (IsDeprecatedRPCEnabled("warnings") ?
475
0
                            RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} :
476
2.38k
                            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.38k
                            {
478
2.38k
                                {RPCResult::Type::STR, "", "warning"},
479
2.38k
                            }
480
2.38k
                            }
481
2.38k
                        ),
482
2.38k
                    }},
483
2.38k
                RPCExamples{
484
2.38k
                    HelpExampleCli("getmininginfo", "")
485
2.38k
            + HelpExampleRpc("getmininginfo", "")
486
2.38k
                },
487
2.38k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
488
2.38k
{
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.38k
    };
528
2.38k
}
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.08k
{
534
3.08k
    return RPCMethod{"prioritisetransaction",
535
3.08k
                "Accepts the transaction into mined blocks at a higher (or lower) priority\n",
536
3.08k
                {
537
3.08k
                    {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id."},
538
3.08k
                    {"dummy", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "API-Compatibility for previous API. Must be zero or null.\n"
539
3.08k
            "                  DEPRECATED. For forward compatibility use named arguments and omit this parameter."},
540
3.08k
                    {"fee_delta", RPCArg::Type::NUM, RPCArg::Optional::NO, "The fee value (in satoshis) to add (or subtract, if negative).\n"
541
3.08k
            "                  Note, that this value is not a fee rate. It is a value to modify absolute fee of the TX.\n"
542
3.08k
            "                  The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
543
3.08k
            "                  considers the transaction as it would have paid a higher (or lower) fee."},
544
3.08k
                },
545
3.08k
                RPCResult{
546
3.08k
                    RPCResult::Type::BOOL, "", "Returns true"},
547
3.08k
                RPCExamples{
548
3.08k
                    HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
549
3.08k
            + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
550
3.08k
                },
551
3.08k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
552
3.08k
{
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.08k
    };
575
3.08k
}
576
577
static RPCMethod getprioritisedtransactions()
578
2.38k
{
579
2.38k
    return RPCMethod{"getprioritisedtransactions",
580
2.38k
        "Returns a map of all user-created (see prioritisetransaction) fee deltas by txid, and whether the tx is present in mempool.",
581
2.38k
        {},
582
2.38k
        RPCResult{
583
2.38k
            RPCResult::Type::OBJ_DYN, "", "prioritisation keyed by txid",
584
2.38k
            {
585
2.38k
                {RPCResult::Type::OBJ, "<transactionid>", "", {
586
2.38k
                    {RPCResult::Type::NUM, "fee_delta", "transaction fee delta in satoshis"},
587
2.38k
                    {RPCResult::Type::BOOL, "in_mempool", "whether this transaction is currently in mempool"},
588
2.38k
                    {RPCResult::Type::NUM, "modified_fee", /*optional=*/true, "modified fee in satoshis. Only returned if in_mempool=true"},
589
2.38k
                }}
590
2.38k
            },
591
2.38k
        },
592
2.38k
        RPCExamples{
593
2.38k
            HelpExampleCli("getprioritisedtransactions", "")
594
2.38k
            + HelpExampleRpc("getprioritisedtransactions", "")
595
2.38k
        },
596
2.38k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
597
2.38k
        {
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.38k
    };
613
2.38k
}
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.73k
{
619
6.73k
    if (state.IsValid())
620
3.90k
        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.75k
{
647
4.75k
    return RPCMethod{
648
4.75k
        "getblocktemplate",
649
4.75k
        "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.75k
        "It returns data needed to construct a block to work on.\n"
651
4.75k
        "For full specification, see BIPs 22, 23, 9, and 145:\n"
652
4.75k
        "    https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
653
4.75k
        "    https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
654
4.75k
        "    https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
655
4.75k
        "    https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
656
4.75k
        {
657
4.75k
            {"template_request", RPCArg::Type::OBJ, RPCArg::Optional::NO, "Format of the template",
658
4.75k
            {
659
4.75k
                {"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.75k
                {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED, "A list of strings",
661
4.75k
                {
662
4.75k
                    {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported feature, 'longpoll', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
663
4.75k
                }},
664
4.75k
                {"rules", RPCArg::Type::ARR, RPCArg::Optional::NO, "A list of strings",
665
4.75k
                {
666
4.75k
                    {"segwit", RPCArg::Type::STR, RPCArg::Optional::NO, "(literal) indicates client side segwit support"},
667
4.75k
                    {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "other client side supported softfork deployment"},
668
4.75k
                }},
669
4.75k
                {"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.75k
                {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "proposed block data to check, encoded in hexadecimal; valid only for mode=\"proposal\""},
671
4.75k
            },
672
4.75k
            },
673
4.75k
        },
674
4.75k
        {
675
4.75k
            RPCResult{"If the proposal was accepted with mode=='proposal'", RPCResult::Type::NONE, "", ""},
676
4.75k
            RPCResult{"If the proposal was not accepted with mode=='proposal'", RPCResult::Type::STR, "", "According to BIP22"},
677
4.75k
            RPCResult{"Otherwise", RPCResult::Type::OBJ, "", "",
678
4.75k
            {
679
4.75k
                {RPCResult::Type::NUM, "version", "The preferred block version"},
680
4.75k
                {RPCResult::Type::ARR, "rules", "specific block rules that are to be enforced",
681
4.75k
                {
682
4.75k
                    {RPCResult::Type::STR, "", "name of a rule the client must understand to some extent; see BIP 9 for format"},
683
4.75k
                }},
684
4.75k
                {RPCResult::Type::OBJ_DYN, "vbavailable", "set of pending, supported versionbit (BIP 9) softfork deployments",
685
4.75k
                {
686
4.75k
                    {RPCResult::Type::NUM, "rulename", "identifies the bit number as indicating acceptance and readiness for the named softfork rule"},
687
4.75k
                }},
688
4.75k
                {RPCResult::Type::ARR, "capabilities", "",
689
4.75k
                {
690
4.75k
                    {RPCResult::Type::STR, "value", "A supported feature, for example 'proposal'"},
691
4.75k
                }},
692
4.75k
                {RPCResult::Type::NUM, "vbrequired", "bit mask of versionbits the server requires set in submissions"},
693
4.75k
                {RPCResult::Type::STR, "previousblockhash", "The hash of current highest block"},
694
4.75k
                {RPCResult::Type::ARR, "transactions", "contents of non-coinbase transactions that should be included in the next block",
695
4.75k
                {
696
4.75k
                    {RPCResult::Type::OBJ, "", "",
697
4.75k
                    {
698
4.75k
                        {RPCResult::Type::STR_HEX, "data", "transaction data encoded in hexadecimal (byte-for-byte)"},
699
4.75k
                        {RPCResult::Type::STR_HEX, "txid", "transaction hash excluding witness data, shown in byte-reversed hex"},
700
4.75k
                        {RPCResult::Type::STR_HEX, "hash", "transaction hash including witness data, shown in byte-reversed hex"},
701
4.75k
                        {RPCResult::Type::ARR, "depends", "array of numbers",
702
4.75k
                        {
703
4.75k
                            {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.75k
                        }},
705
4.75k
                        {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.75k
                        {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.75k
                        {RPCResult::Type::NUM, "weight", "total transaction weight, as counted for purposes of block limits"},
708
4.75k
                    }},
709
4.75k
                }},
710
4.75k
                {RPCResult::Type::OBJ_DYN, "coinbaseaux", "data that should be included in the coinbase's scriptSig content",
711
4.75k
                {
712
4.75k
                    {RPCResult::Type::STR_HEX, "key", "values must be in the coinbase (keys may be ignored)"},
713
4.75k
                }},
714
4.75k
                {RPCResult::Type::NUM, "coinbasevalue", "maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)"},
715
4.75k
                {RPCResult::Type::STR, "longpollid", "an id to include with a request to longpoll on an update to this template"},
716
4.75k
                {RPCResult::Type::STR, "target", "The hash target"},
717
4.75k
                {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.75k
                {RPCResult::Type::ARR, "mutable", "list of ways the block template may be changed",
719
4.75k
                {
720
4.75k
                    {RPCResult::Type::STR, "value", "A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'"},
721
4.75k
                }},
722
4.75k
                {RPCResult::Type::STR_HEX, "noncerange", "A range of valid nonces"},
723
4.75k
                {RPCResult::Type::NUM, "sigoplimit", "limit of sigops in blocks"},
724
4.75k
                {RPCResult::Type::NUM, "sizelimit", "limit of block size"},
725
4.75k
                {RPCResult::Type::NUM, "weightlimit", /*optional=*/true, "limit of block weight"},
726
4.75k
                {RPCResult::Type::NUM_TIME, "curtime", "current timestamp in " + UNIX_EPOCH_TIME + ". Adjusted for the proposed BIP94 timewarp rule."},
727
4.75k
                {RPCResult::Type::STR, "bits", "compressed target of next block"},
728
4.75k
                {RPCResult::Type::NUM, "height", "The height of the next block"},
729
4.75k
                {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "Only on signet"},
730
4.75k
                {RPCResult::Type::STR_HEX, "default_witness_commitment", /*optional=*/true, "a valid witness commitment for the unmodified block template"},
731
4.75k
            }},
732
4.75k
        },
733
4.75k
        RPCExamples{
734
4.75k
                    HelpExampleCli("getblocktemplate", "'{\"rules\": [\"segwit\"]}'")
735
4.75k
            + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}")
736
4.75k
                },
737
4.75k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
738
4.75k
{
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.75k
    };
1066
4.75k
}
1067
1068
class submitblock_StateCatcher final : public CValidationInterface
1069
{
1070
public:
1071
    uint256 hash;
1072
    bool found{false};
1073
    BlockValidationState state;
1074
1075
6.66k
    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.51k
    {
1080
6.51k
        if (block->GetHash() != hash) return;
1081
6.41k
        found = true;
1082
6.41k
        state = stateIn;
1083
6.41k
    }
1084
};
1085
1086
static RPCMethod submitblock()
1087
9.02k
{
1088
    // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored.
1089
9.02k
    return RPCMethod{
1090
9.02k
        "submitblock",
1091
9.02k
        "Attempts to submit new block to network.\n"
1092
9.02k
        "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n",
1093
9.02k
        {
1094
9.02k
            {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"},
1095
9.02k
            {"dummy", RPCArg::Type::STR, RPCArg::DefaultHint{"ignored"}, "dummy value, for compatibility with BIP22. This value is ignored."},
1096
9.02k
        },
1097
9.02k
        {
1098
9.02k
            RPCResult{"If the block was accepted", RPCResult::Type::NONE, "", ""},
1099
9.02k
            RPCResult{"Otherwise", RPCResult::Type::STR, "", "According to BIP22"},
1100
9.02k
        },
1101
9.02k
        RPCExamples{
1102
9.02k
                    HelpExampleCli("submitblock", "\"mydata\"")
1103
9.02k
            + HelpExampleRpc("submitblock", "\"mydata\"")
1104
9.02k
                },
1105
9.02k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1106
9.02k
{
1107
6.66k
    std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
1108
6.66k
    CBlock& block = *blockptr;
1109
6.66k
    if (!DecodeHexBlk(block, request.params[0].get_str())) {
1110
2
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
1111
2
    }
1112
1113
6.66k
    ChainstateManager& chainman = EnsureAnyChainman(request.context);
1114
6.66k
    {
1115
6.66k
        LOCK(cs_main);
1116
6.66k
        const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
1117
6.66k
        if (pindex) {
1118
6.66k
            chainman.UpdateUncommittedBlockStructures(block, pindex);
1119
6.66k
        }
1120
6.66k
    }
1121
1122
6.66k
    bool new_block;
1123
6.66k
    auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
1124
6.66k
    CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
1125
6.66k
    bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
1126
6.66k
    CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
1127
6.66k
    if (!new_block && accepted) {
1128
121
        return "duplicate";
1129
121
    }
1130
6.54k
    if (!sc->found) {
1131
126
        return "inconclusive";
1132
126
    }
1133
6.41k
    return BIP22ValidationResult(sc->state);
1134
6.54k
},
1135
9.02k
    };
1136
9.02k
}
1137
1138
static RPCMethod submitheader()
1139
4.19k
{
1140
4.19k
    return RPCMethod{
1141
4.19k
        "submitheader",
1142
4.19k
        "Decode the given hexdata as a header and submit it as a candidate chain tip if valid."
1143
4.19k
                "\nThrows when the header is invalid.\n",
1144
4.19k
                {
1145
4.19k
                    {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"},
1146
4.19k
                },
1147
4.19k
                RPCResult{
1148
4.19k
                    RPCResult::Type::NONE, "", "None"},
1149
4.19k
                RPCExamples{
1150
4.19k
                    HelpExampleCli("submitheader", "\"aabbcc\"") +
1151
4.19k
                    HelpExampleRpc("submitheader", "\"aabbcc\"")
1152
4.19k
                },
1153
4.19k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1154
4.19k
{
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.84k
    ChainstateManager& chainman = EnsureAnyChainman(request.context);
1160
1.84k
    {
1161
1.84k
        LOCK(cs_main);
1162
1.84k
        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.84k
    }
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.19k
    };
1176
4.19k
}
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
}