Coverage Report

Created: 2026-07-23 20:35

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.42k
{
144
2.42k
    return RPCMethod{
145
2.42k
        "getnetworkhashps",
146
2.42k
        "Returns the estimated network hashes per second based on the last n blocks.\n"
147
2.42k
                "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
148
2.42k
                "Pass in [height] to estimate the network speed at the time when a certain block was found.\n",
149
2.42k
                {
150
2.42k
                    {"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.42k
                    {"height", RPCArg::Type::NUM, RPCArg::Default{-1}, "To estimate at the time of the given height."},
152
2.42k
                },
153
2.42k
                RPCResult{
154
2.42k
                    RPCResult::Type::NUM, "", "Hashes per second estimated"},
155
2.42k
                RPCExamples{
156
2.42k
                    HelpExampleCli("getnetworkhashps", "")
157
2.42k
            + HelpExampleRpc("getnetworkhashps", "")
158
2.42k
                },
159
2.42k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
160
2.42k
{
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.42k
    };
166
2.42k
}
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
39.4k
{
170
39.4k
    block_out.reset();
171
39.4k
    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
39.4k
    if (max_tries == 0 || chainman.m_interrupt) {
178
1
        return false;
179
1
    }
180
39.4k
    if (block.nNonce == std::numeric_limits<uint32_t>::max()) {
181
0
        return true;
182
0
    }
183
184
39.4k
    block_out = std::make_shared<const CBlock>(std::move(block));
185
186
39.4k
    if (!process_new_block) return true;
187
188
39.4k
    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
39.4k
    return true;
193
39.4k
}
194
195
static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const CScript& coinbase_output_script, int nGenerate, uint64_t nMaxTries)
196
2.88k
{
197
2.88k
    UniValue blockHashes(UniValue::VARR);
198
41.9k
    while (nGenerate > 0 && !chainman.m_interrupt) {
199
39.0k
        std::unique_ptr<BlockTemplate> block_template(miner.createNewBlock({ .coinbase_output_script = coinbase_output_script }, /*cooldown=*/false));
200
39.0k
        CHECK_NONFATAL(block_template);
201
202
39.0k
        std::shared_ptr<const CBlock> block_out;
203
39.0k
        if (!GenerateBlock(chainman, block_template->getBlock(), nMaxTries, block_out, /*process_new_block=*/true)) {
204
1
            break;
205
1
        }
206
207
39.0k
        if (block_out) {
208
39.0k
            --nGenerate;
209
39.0k
            blockHashes.push_back(block_out->GetHash().GetHex());
210
39.0k
        }
211
39.0k
    }
212
2.88k
    return blockHashes;
213
2.88k
}
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
858
    if (descs.size() > 1) {
221
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Multipath descriptor not accepted");
222
0
    }
223
858
    const auto& desc = descs.at(0);
224
858
    if (desc->IsRange()) {
225
1
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?");
226
1
    }
227
228
857
    FlatSigningProvider provider;
229
857
    std::vector<CScript> scripts;
230
857
    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
856
    CHECK_NONFATAL(scripts.size() > 0 && scripts.size() <= 4);
236
237
856
    if (scripts.size() == 1) {
238
854
        script = scripts.at(0);
239
854
    } 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
856
    return true;
248
857
}
249
250
static RPCMethod generatetodescriptor()
251
3.19k
{
252
3.19k
    return RPCMethod{
253
3.19k
        "generatetodescriptor",
254
3.19k
        "Mine to a specified descriptor and return the block hashes.",
255
3.19k
        {
256
3.19k
            {"num_blocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated."},
257
3.19k
            {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor to send the newly generated bitcoin to."},
258
3.19k
            {"maxtries", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_MAX_TRIES}, "How many iterations to try."},
259
3.19k
        },
260
3.19k
        RPCResult{
261
3.19k
            RPCResult::Type::ARR, "", "hashes of blocks generated",
262
3.19k
            {
263
3.19k
                {RPCResult::Type::STR_HEX, "", "blockhash"},
264
3.19k
            }
265
3.19k
        },
266
3.19k
        RPCExamples{
267
3.19k
            "\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
268
3.19k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
269
3.19k
{
270
827
    const auto num_blocks{self.Arg<int>("num_blocks")};
271
827
    const auto max_tries{self.Arg<uint64_t>("maxtries")};
272
273
827
    CScript coinbase_output_script;
274
827
    std::string error;
275
827
    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
827
    NodeContext& node = EnsureAnyNodeContext(request.context);
280
827
    Mining& miner = EnsureMining(node);
281
827
    ChainstateManager& chainman = EnsureChainman(node);
282
283
827
    return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
284
827
},
285
3.19k
    };
286
3.19k
}
287
288
static RPCMethod generate()
289
2.36k
{
290
2.36k
    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.36k
}
294
295
static RPCMethod generatetoaddress()
296
4.42k
{
297
4.42k
    return RPCMethod{"generatetoaddress",
298
4.42k
        "Mine to a specified address and return the block hashes.",
299
4.42k
         {
300
4.42k
             {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated."},
301
4.42k
             {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The address to send the newly generated bitcoin to."},
302
4.42k
             {"maxtries", RPCArg::Type::NUM, RPCArg::Default{DEFAULT_MAX_TRIES}, "How many iterations to try."},
303
4.42k
         },
304
4.42k
         RPCResult{
305
4.42k
             RPCResult::Type::ARR, "", "hashes of blocks generated",
306
4.42k
             {
307
4.42k
                 {RPCResult::Type::STR_HEX, "", "blockhash"},
308
4.42k
             }},
309
4.42k
         RPCExamples{
310
4.42k
            "\nGenerate 11 blocks to myaddress\n"
311
4.42k
            + HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
312
4.42k
            + "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.42k
            + HelpExampleCli("getnewaddress", "")
314
4.42k
                },
315
4.42k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
316
4.42k
{
317
2.06k
    const int num_blocks{request.params[0].getInt<int>()};
318
2.06k
    const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].getInt<int>()};
319
320
2.06k
    CTxDestination destination = DecodeDestination(request.params[1].get_str());
321
2.06k
    if (!IsValidDestination(destination)) {
322
2
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
323
2
    }
324
325
2.06k
    NodeContext& node = EnsureAnyNodeContext(request.context);
326
2.06k
    Mining& miner = EnsureMining(node);
327
2.06k
    ChainstateManager& chainman = EnsureChainman(node);
328
329
2.06k
    CScript coinbase_output_script = GetScriptForDestination(destination);
330
331
2.06k
    return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
332
2.06k
},
333
4.42k
    };
334
4.42k
}
335
336
static RPCMethod generateblock()
337
2.71k
{
338
2.71k
    return RPCMethod{"generateblock",
339
2.71k
        "Mine a set of ordered transactions to a specified address or descriptor and return the block hash.\n"
340
2.71k
        "Transaction fees are not collected in the block reward.",
341
2.71k
        {
342
2.71k
            {"output", RPCArg::Type::STR, RPCArg::Optional::NO, "The address or descriptor to send the newly generated bitcoin to."},
343
2.71k
            {"transactions", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings which are either txids or raw transactions.\n"
344
2.71k
                "Txids must reference transactions currently in the mempool.\n"
345
2.71k
                "All transactions must be valid and in valid order, otherwise the block will be rejected.",
346
2.71k
                {
347
2.71k
                    {"rawtx/txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
348
2.71k
                },
349
2.71k
            },
350
2.71k
            {"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.71k
        },
352
2.71k
        RPCResult{
353
2.71k
            RPCResult::Type::OBJ, "", "",
354
2.71k
            {
355
2.71k
                {RPCResult::Type::STR_HEX, "hash", "hash of generated block"},
356
2.71k
                {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "hex of generated block, only present when submit=false"},
357
2.71k
            }
358
2.71k
        },
359
2.71k
        RPCExamples{
360
2.71k
            "\nGenerate a block to myaddress, with txs rawtx and mempool_txid\n"
361
2.71k
            + HelpExampleCli("generateblock", R"("myaddress" '["rawtx", "mempool_txid"]')")
362
2.71k
        },
363
2.71k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
364
2.71k
{
365
353
    const auto address_or_descriptor = request.params[0].get_str();
366
353
    CScript coinbase_output_script;
367
353
    std::string error;
368
369
353
    if (!getScriptFromDescriptor(address_or_descriptor, coinbase_output_script, error)) {
370
322
        const auto destination = DecodeDestination(address_or_descriptor);
371
322
        if (!IsValidDestination(destination)) {
372
1
            throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address or descriptor");
373
1
        }
374
375
321
        coinbase_output_script = GetScriptForDestination(destination);
376
321
    }
377
378
352
    NodeContext& node = EnsureAnyNodeContext(request.context);
379
352
    Mining& miner = EnsureMining(node);
380
352
    const CTxMemPool& mempool = EnsureMemPool(node);
381
382
352
    std::vector<CTransactionRef> txs;
383
352
    const auto raw_txs_or_txids = request.params[1].get_array();
384
459
    for (size_t i = 0; i < raw_txs_or_txids.size(); i++) {
385
109
        const auto& str{raw_txs_or_txids[i].get_str()};
386
387
109
        CMutableTransaction mtx;
388
109
        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
105
        } else if (DecodeHexTx(mtx, str)) {
397
104
            txs.push_back(MakeTransactionRef(std::move(mtx)));
398
399
104
        } 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
109
    }
403
404
350
    const bool process_new_block{request.params[2].isNull() ? true : request.params[2].get_bool()};
405
350
    CBlock block;
406
407
350
    ChainstateManager& chainman = EnsureChainman(node);
408
350
    {
409
350
        LOCK(chainman.GetMutex());
410
350
        {
411
350
            std::unique_ptr<BlockTemplate> block_template{miner.createNewBlock({.use_mempool = false, .coinbase_output_script = coinbase_output_script}, /*cooldown=*/false)};
412
350
            CHECK_NONFATAL(block_template);
413
414
350
            block = block_template->getBlock();
415
350
        }
416
417
350
        CHECK_NONFATAL(block.vtx.size() == 1);
418
419
        // Add transactions
420
350
        block.vtx.insert(block.vtx.end(), txs.begin(), txs.end());
421
350
        RegenerateCommitments(block, chainman);
422
423
350
        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
350
    }
427
428
348
    std::shared_ptr<const CBlock> block_out;
429
348
    uint64_t max_tries{DEFAULT_MAX_TRIES};
430
431
348
    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
348
    UniValue obj(UniValue::VOBJ);
436
348
    obj.pushKV("hash", block_out->GetHash().GetHex());
437
348
    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
348
    return obj;
443
348
},
444
2.71k
    };
445
2.71k
}
446
447
static RPCMethod getmininginfo()
448
2.40k
{
449
2.40k
    return RPCMethod{
450
2.40k
        "getmininginfo",
451
2.40k
        "Returns a json object containing mining-related information.",
452
2.40k
                {},
453
2.40k
                RPCResult{
454
2.40k
                    RPCResult::Type::OBJ, "", "",
455
2.40k
                    {
456
2.40k
                        {RPCResult::Type::NUM, "blocks", "The current block"},
457
2.40k
                        {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.40k
                        {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.40k
                        {RPCResult::Type::STR_HEX, "bits", "The current nBits, compact representation of the block difficulty target"},
460
2.40k
                        {RPCResult::Type::NUM, "difficulty", "The current difficulty"},
461
2.40k
                        {RPCResult::Type::STR_HEX, "target", "The current target"},
462
2.40k
                        {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"},
463
2.40k
                        {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"},
464
2.40k
                        {RPCResult::Type::STR_AMOUNT, "blockmintxfee", "Minimum feerate of packages selected for block inclusion in " + CURRENCY_UNIT + "/kvB"},
465
2.40k
                        {RPCResult::Type::STR, "chain", "current network name (" LIST_CHAIN_NAMES ")"},
466
2.40k
                        {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.40k
                        {RPCResult::Type::OBJ, "next", "The next block",
468
2.40k
                        {
469
2.40k
                            {RPCResult::Type::NUM, "height", "The next height"},
470
2.40k
                            {RPCResult::Type::STR_HEX, "bits", "The next target nBits"},
471
2.40k
                            {RPCResult::Type::NUM, "difficulty", "The next difficulty"},
472
2.40k
                            {RPCResult::Type::STR_HEX, "target", "The next target"}
473
2.40k
                        }},
474
2.40k
                        (IsDeprecatedRPCEnabled("warnings") ?
475
0
                            RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} :
476
2.40k
                            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.40k
                            {
478
2.40k
                                {RPCResult::Type::STR, "", "warning"},
479
2.40k
                            }
480
2.40k
                            }
481
2.40k
                        ),
482
2.40k
                    }},
483
2.40k
                RPCExamples{
484
2.40k
                    HelpExampleCli("getmininginfo", "")
485
2.40k
            + HelpExampleRpc("getmininginfo", "")
486
2.40k
                },
487
2.40k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
488
2.40k
{
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.40k
    };
528
2.40k
}
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.10k
{
534
3.10k
    return RPCMethod{"prioritisetransaction",
535
3.10k
                "Accepts the transaction into mined blocks at a higher (or lower) priority\n",
536
3.10k
                {
537
3.10k
                    {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id."},
538
3.10k
                    {"dummy", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "API-Compatibility for previous API. Must be zero or null.\n"
539
3.10k
            "                  DEPRECATED. For forward compatibility use named arguments and omit this parameter.",
540
3.10k
                        RPCArgOptions{.placeholder = true}},
541
3.10k
                    {"fee_delta", RPCArg::Type::NUM, RPCArg::Optional::NO, "The fee value (in satoshis) to add (or subtract, if negative).\n"
542
3.10k
            "                  Note, that this value is not a fee rate. It is a value to modify absolute fee of the TX.\n"
543
3.10k
            "                  The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
544
3.10k
            "                  considers the transaction as it would have paid a higher (or lower) fee."},
545
3.10k
                },
546
3.10k
                RPCResult{
547
3.10k
                    RPCResult::Type::BOOL, "", "Returns true"},
548
3.10k
                RPCExamples{
549
3.10k
                    HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
550
3.10k
            + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
551
3.10k
                },
552
3.10k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
553
3.10k
{
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.10k
    };
576
3.10k
}
577
578
static RPCMethod getprioritisedtransactions()
579
2.40k
{
580
2.40k
    return RPCMethod{"getprioritisedtransactions",
581
2.40k
        "Returns a map of all user-created (see prioritisetransaction) fee deltas by txid, and whether the tx is present in mempool.",
582
2.40k
        {},
583
2.40k
        RPCResult{
584
2.40k
            RPCResult::Type::OBJ_DYN, "", "prioritisation keyed by txid",
585
2.40k
            {
586
2.40k
                {RPCResult::Type::OBJ, "<transactionid>", "", {
587
2.40k
                    {RPCResult::Type::NUM, "fee_delta", "transaction fee delta in satoshis"},
588
2.40k
                    {RPCResult::Type::BOOL, "in_mempool", "whether this transaction is currently in mempool"},
589
2.40k
                    {RPCResult::Type::NUM, "modified_fee", /*optional=*/true, "modified fee in satoshis. Only returned if in_mempool=true"},
590
2.40k
                }}
591
2.40k
            },
592
2.40k
        },
593
2.40k
        RPCExamples{
594
2.40k
            HelpExampleCli("getprioritisedtransactions", "")
595
2.40k
            + HelpExampleRpc("getprioritisedtransactions", "")
596
2.40k
        },
597
2.40k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
598
2.40k
        {
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.40k
    };
614
2.40k
}
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
6.73k
{
620
6.73k
    if (state.IsValid())
621
3.90k
        return UniValue::VNULL;
622
623
2.82k
    if (state.IsError())
624
0
        throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
625
2.82k
    if (state.IsInvalid())
626
2.82k
    {
627
2.82k
        std::string strRejectReason = state.GetRejectReason();
628
2.82k
        if (strRejectReason.empty())
629
0
            return "rejected";
630
2.82k
        return strRejectReason;
631
2.82k
    }
632
    // Should be impossible
633
0
    return "valid?";
634
2.82k
}
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
2.07k
{
639
2.07k
    std::string s{name};
640
2.07k
    if (!gbt_optional_rule) {
641
0
        s.insert(s.begin(), '!');
642
0
    }
643
2.07k
    return s;
644
2.07k
}
645
646
static RPCMethod getblocktemplate()
647
4.78k
{
648
4.78k
    return RPCMethod{
649
4.78k
        "getblocktemplate",
650
4.78k
        "If the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
651
4.78k
        "It returns data needed to construct a block to work on.\n"
652
4.78k
        "For full specification, see BIPs 22, 23, 9, and 145:\n"
653
4.78k
        "    https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
654
4.78k
        "    https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n"
655
4.78k
        "    https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
656
4.78k
        "    https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n",
657
4.78k
        {
658
4.78k
            {"template_request", RPCArg::Type::OBJ, RPCArg::Optional::NO, "Format of the template",
659
4.78k
            {
660
4.78k
                {"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"},
661
4.78k
                {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED, "A list of strings",
662
4.78k
                {
663
4.78k
                    {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported feature, 'longpoll', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"},
664
4.78k
                }},
665
4.78k
                {"rules", RPCArg::Type::ARR, RPCArg::Optional::NO, "A list of strings",
666
4.78k
                {
667
4.78k
                    {"segwit", RPCArg::Type::STR, RPCArg::Optional::NO, "(literal) indicates client side segwit support"},
668
4.78k
                    {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "other client side supported softfork deployment"},
669
4.78k
                }},
670
4.78k
                {"longpollid", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "delay processing request until the result would vary significantly from the \"longpollid\" of a prior template"},
671
4.78k
                {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "proposed block data to check, encoded in hexadecimal; valid only for mode=\"proposal\""},
672
4.78k
            },
673
4.78k
            },
674
4.78k
        },
675
4.78k
        {
676
4.78k
            RPCResult{"If the proposal was accepted with mode=='proposal'", RPCResult::Type::NONE, "", ""},
677
4.78k
            RPCResult{"If the proposal was not accepted with mode=='proposal'", RPCResult::Type::STR, "", "According to BIP22"},
678
4.78k
            RPCResult{"Otherwise", RPCResult::Type::OBJ, "", "",
679
4.78k
            {
680
4.78k
                {RPCResult::Type::NUM, "version", "The preferred block version"},
681
4.78k
                {RPCResult::Type::ARR, "rules", "specific block rules that are to be enforced",
682
4.78k
                {
683
4.78k
                    {RPCResult::Type::STR, "", "name of a rule the client must understand to some extent; see BIP 9 for format"},
684
4.78k
                }},
685
4.78k
                {RPCResult::Type::OBJ_DYN, "vbavailable", "set of pending, supported versionbit (BIP 9) softfork deployments",
686
4.78k
                {
687
4.78k
                    {RPCResult::Type::NUM, "rulename", "identifies the bit number as indicating acceptance and readiness for the named softfork rule"},
688
4.78k
                }},
689
4.78k
                {RPCResult::Type::ARR, "capabilities", "",
690
4.78k
                {
691
4.78k
                    {RPCResult::Type::STR, "value", "A supported feature, for example 'proposal'"},
692
4.78k
                }},
693
4.78k
                {RPCResult::Type::NUM, "vbrequired", "bit mask of versionbits the server requires set in submissions"},
694
4.78k
                {RPCResult::Type::STR, "previousblockhash", "The hash of current highest block"},
695
4.78k
                {RPCResult::Type::ARR, "transactions", "contents of non-coinbase transactions that should be included in the next block",
696
4.78k
                {
697
4.78k
                    {RPCResult::Type::OBJ, "", "",
698
4.78k
                    {
699
4.78k
                        {RPCResult::Type::STR_HEX, "data", "transaction data encoded in hexadecimal (byte-for-byte)"},
700
4.78k
                        {RPCResult::Type::STR_HEX, "txid", "transaction hash excluding witness data, shown in byte-reversed hex"},
701
4.78k
                        {RPCResult::Type::STR_HEX, "hash", "transaction hash including witness data, shown in byte-reversed hex"},
702
4.78k
                        {RPCResult::Type::ARR, "depends", "array of numbers",
703
4.78k
                        {
704
4.78k
                            {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
4.78k
                        }},
706
4.78k
                        {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
4.78k
                        {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
4.78k
                        {RPCResult::Type::NUM, "weight", "total transaction weight, as counted for purposes of block limits"},
709
4.78k
                    }},
710
4.78k
                }},
711
4.78k
                {RPCResult::Type::OBJ_DYN, "coinbaseaux", "data that should be included in the coinbase's scriptSig content",
712
4.78k
                {
713
4.78k
                    {RPCResult::Type::STR_HEX, "key", "values must be in the coinbase (keys may be ignored)"},
714
4.78k
                }},
715
4.78k
                {RPCResult::Type::NUM, "coinbasevalue", "maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)"},
716
4.78k
                {RPCResult::Type::STR, "longpollid", "an id to include with a request to longpoll on an update to this template"},
717
4.78k
                {RPCResult::Type::STR, "target", "The hash target"},
718
4.78k
                {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
4.78k
                {RPCResult::Type::ARR, "mutable", "list of ways the block template may be changed",
720
4.78k
                {
721
4.78k
                    {RPCResult::Type::STR, "value", "A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'"},
722
4.78k
                }},
723
4.78k
                {RPCResult::Type::STR_HEX, "noncerange", "A range of valid nonces"},
724
4.78k
                {RPCResult::Type::NUM, "sigoplimit", "limit of sigops in blocks"},
725
4.78k
                {RPCResult::Type::NUM, "sizelimit", "limit of block size"},
726
4.78k
                {RPCResult::Type::NUM, "weightlimit", /*optional=*/true, "limit of block weight"},
727
4.78k
                {RPCResult::Type::NUM_TIME, "curtime", "current timestamp in " + UNIX_EPOCH_TIME + ". Adjusted for the proposed BIP94 timewarp rule."},
728
4.78k
                {RPCResult::Type::STR, "bits", "compressed target of next block"},
729
4.78k
                {RPCResult::Type::NUM, "height", "The height of the next block"},
730
4.78k
                {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "Only on signet"},
731
4.78k
                {RPCResult::Type::STR_HEX, "default_witness_commitment", /*optional=*/true, "a valid witness commitment for the unmodified block template"},
732
4.78k
            }},
733
4.78k
        },
734
4.78k
        RPCExamples{
735
4.78k
                    HelpExampleCli("getblocktemplate", "'{\"rules\": [\"segwit\"]}'")
736
4.78k
            + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}")
737
4.78k
                },
738
4.78k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
739
4.78k
{
740
2.41k
    NodeContext& node = EnsureAnyNodeContext(request.context);
741
2.41k
    ChainstateManager& chainman = EnsureChainman(node);
742
2.41k
    Mining& miner = EnsureMining(node);
743
744
2.41k
    std::string strMode = "template";
745
2.41k
    UniValue lpval = NullUniValue;
746
2.41k
    std::set<std::string> setClientRules;
747
2.41k
    if (!request.params[0].isNull())
748
2.41k
    {
749
2.41k
        const UniValue& oparam = request.params[0].get_obj();
750
2.41k
        const UniValue& modeval = oparam.find_value("mode");
751
2.41k
        if (modeval.isStr())
752
321
            strMode = modeval.get_str();
753
2.09k
        else if (modeval.isNull())
754
2.09k
        {
755
            /* Do nothing */
756
2.09k
        }
757
0
        else
758
0
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
759
2.41k
        lpval = oparam.find_value("longpollid");
760
761
2.41k
        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
2.09k
        const UniValue& aClientRules = oparam.find_value("rules");
786
2.09k
        if (aClientRules.isArray()) {
787
4.18k
            for (unsigned int i = 0; i < aClientRules.size(); ++i) {
788
2.09k
                const UniValue& v = aClientRules[i];
789
2.09k
                setClientRules.insert(v.get_str());
790
2.09k
            }
791
2.09k
        }
792
2.09k
    }
793
794
2.09k
    if (strMode != "template")
795
0
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
796
797
2.09k
    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
2.09k
    static unsigned int nTransactionsUpdatedLast;
809
2.09k
    const CTxMemPool& mempool = EnsureMemPool(node);
810
811
2.09k
    WAIT_LOCK(cs_main, cs_main_lock);
812
2.09k
    uint256 tip{CHECK_NONFATAL(miner.getTip()).value().hash};
813
814
    // Long Polling (BIP22)
815
2.09k
    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
2.09k
    const Consensus::Params& consensusParams = chainman.GetParams().GetConsensus();
879
880
    // GBT must be called with 'signet' set in the rules for signet chains
881
2.09k
    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
2.09k
    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
2.09k
    static CBlockIndex* pindexPrev;
892
2.09k
    static int64_t time_start;
893
2.09k
    static std::unique_ptr<BlockTemplate> block_template;
894
2.09k
    if (!pindexPrev || pindexPrev->GetBlockHash() != tip ||
895
2.09k
        (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
896
75
    {
897
        // Clear pindexPrev so future calls make a new block, despite any failures from here on
898
75
        pindexPrev = nullptr;
899
900
        // Store the pindexBest used before createNewBlock, to avoid races
901
75
        nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
902
75
        CBlockIndex* pindexPrevNew = chainman.m_blockman.LookupBlockIndex(tip);
903
75
        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
75
        block_template = miner.createNewBlock({}, /*cooldown=*/false);
910
75
        CHECK_NONFATAL(block_template);
911
912
913
        // Need to update only after we know createNewBlock succeeded
914
75
        pindexPrev = pindexPrevNew;
915
75
    }
916
2.09k
    CHECK_NONFATAL(pindexPrev);
917
2.09k
    CBlock block{block_template->getBlock()};
918
919
    // Update nTime
920
2.09k
    UpdateTime(&block, consensusParams, pindexPrev);
921
2.09k
    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
2.09k
    const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT);
925
926
2.09k
    UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
927
928
2.09k
    UniValue transactions(UniValue::VARR);
929
2.09k
    std::map<Txid, int64_t> setTxIndex;
930
2.09k
    std::vector<CAmount> tx_fees{block_template->getTxFees()};
931
2.09k
    std::vector<int64_t> tx_sigops{block_template->getTxSigops()};
932
933
2.09k
    int i = 0;
934
2.19k
    for (const auto& it : block.vtx) {
935
2.19k
        const CTransaction& tx = *it;
936
2.19k
        Txid txHash = tx.GetHash();
937
2.19k
        setTxIndex[txHash] = i++;
938
939
2.19k
        if (tx.IsCoinBase())
940
2.09k
            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
2.09k
    UniValue aux(UniValue::VOBJ);
970
971
2.09k
    arith_uint256 hashTarget = arith_uint256().SetCompact(block.nBits);
972
973
2.09k
    UniValue aMutable(UniValue::VARR);
974
2.09k
    aMutable.push_back("time");
975
2.09k
    aMutable.push_back("transactions");
976
2.09k
    aMutable.push_back("prevblock");
977
978
2.09k
    UniValue result(UniValue::VOBJ);
979
2.09k
    result.pushKV("capabilities", std::move(aCaps));
980
981
2.09k
    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
2.09k
    aRules.push_back("csv");
986
2.09k
    if (!fPreSegWit) {
987
2.08k
        aRules.push_back("!segwit");
988
2.08k
        aRules.push_back("taproot");
989
2.08k
    }
990
2.09k
    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
2.09k
    UniValue vbavailable(UniValue::VOBJ);
997
2.09k
    const auto gbtstatus = chainman.m_versionbitscache.GBTStatus(*pindexPrev, consensusParams);
998
999
2.09k
    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
2.09k
    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
2.09k
    for (const auto& [name, info] : gbtstatus.active) {
1017
2.00k
        aRules.push_back(gbt_rule_value(name, info.gbt_optional_rule));
1018
2.00k
        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
2.00k
    }
1023
1024
2.09k
    result.pushKV("version", block.nVersion);
1025
2.09k
    result.pushKV("rules", std::move(aRules));
1026
2.09k
    result.pushKV("vbavailable", std::move(vbavailable));
1027
2.09k
    result.pushKV("vbrequired", 0);
1028
1029
2.09k
    result.pushKV("previousblockhash", block.hashPrevBlock.GetHex());
1030
2.09k
    result.pushKV("transactions", std::move(transactions));
1031
2.09k
    result.pushKV("coinbaseaux", std::move(aux));
1032
2.09k
    result.pushKV("coinbasevalue", block.vtx[0]->vout[0].nValue);
1033
2.09k
    result.pushKV("longpollid", tip.GetHex() + ToString(nTransactionsUpdatedLast));
1034
2.09k
    result.pushKV("target", hashTarget.GetHex());
1035
2.09k
    result.pushKV("mintime", GetMinimumTime(pindexPrev, consensusParams.DifficultyAdjustmentInterval()));
1036
2.09k
    result.pushKV("mutable", std::move(aMutable));
1037
2.09k
    result.pushKV("noncerange", "00000000ffffffff");
1038
2.09k
    int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
1039
2.09k
    int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE;
1040
2.09k
    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
2.09k
    result.pushKV("sigoplimit", nSigOpLimit);
1047
2.09k
    result.pushKV("sizelimit", nSizeLimit);
1048
2.09k
    if (!fPreSegWit) {
1049
2.08k
        result.pushKV("weightlimit", MAX_BLOCK_WEIGHT);
1050
2.08k
    }
1051
2.09k
    result.pushKV("curtime", block.GetBlockTime());
1052
2.09k
    result.pushKV("bits", strprintf("%08x", block.nBits));
1053
2.09k
    result.pushKV("height", pindexPrev->nHeight + 1);
1054
1055
2.09k
    if (consensusParams.signet_blocks) {
1056
6
        result.pushKV("signet_challenge", HexStr(consensusParams.signet_challenge));
1057
6
    }
1058
1059
2.09k
    if (auto coinbase{block_template->getCoinbaseTx()}; coinbase.required_outputs.size() > 0) {
1060
2.09k
        CHECK_NONFATAL(coinbase.required_outputs.size() == 1); // Only one output is currently expected
1061
2.09k
        result.pushKV("default_witness_commitment", HexStr(coinbase.required_outputs[0].scriptPubKey));
1062
2.09k
    }
1063
1064
2.09k
    return result;
1065
2.09k
},
1066
4.78k
    };
1067
4.78k
}
1068
1069
class submitblock_StateCatcher final : public CValidationInterface
1070
{
1071
public:
1072
    uint256 hash;
1073
    bool found{false};
1074
    BlockValidationState state;
1075
1076
6.66k
    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
6.51k
    {
1081
6.51k
        if (block->GetHash() != hash) return;
1082
6.41k
        found = true;
1083
6.41k
        state = stateIn;
1084
6.41k
    }
1085
};
1086
1087
static RPCMethod submitblock()
1088
9.04k
{
1089
    // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored.
1090
9.04k
    return RPCMethod{
1091
9.04k
        "submitblock",
1092
9.04k
        "Attempts to submit new block to network.\n"
1093
9.04k
        "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n",
1094
9.04k
        {
1095
9.04k
            {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"},
1096
9.04k
            {"dummy", RPCArg::Type::STR, RPCArg::DefaultHint{"ignored"}, "dummy value, for compatibility with BIP22. This value is ignored.",
1097
9.04k
                RPCArgOptions{.placeholder = true}},
1098
9.04k
        },
1099
9.04k
        {
1100
9.04k
            RPCResult{"If the block was accepted", RPCResult::Type::NONE, "", ""},
1101
9.04k
            RPCResult{"Otherwise", RPCResult::Type::STR, "", "According to BIP22"},
1102
9.04k
        },
1103
9.04k
        RPCExamples{
1104
9.04k
                    HelpExampleCli("submitblock", "\"mydata\"")
1105
9.04k
            + HelpExampleRpc("submitblock", "\"mydata\"")
1106
9.04k
                },
1107
9.04k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1108
9.04k
{
1109
6.67k
    std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
1110
6.67k
    CBlock& block = *blockptr;
1111
6.67k
    if (!DecodeHexBlk(block, request.params[0].get_str())) {
1112
2
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
1113
2
    }
1114
1115
6.66k
    ChainstateManager& chainman = EnsureAnyChainman(request.context);
1116
6.66k
    {
1117
6.66k
        LOCK(cs_main);
1118
6.66k
        const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
1119
6.66k
        if (pindex) {
1120
6.66k
            chainman.UpdateUncommittedBlockStructures(block, pindex);
1121
6.66k
        }
1122
6.66k
    }
1123
1124
6.66k
    bool new_block;
1125
6.66k
    auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
1126
6.66k
    CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
1127
6.66k
    bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
1128
6.66k
    CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
1129
6.66k
    if (!new_block && accepted) {
1130
123
        return "duplicate";
1131
123
    }
1132
6.54k
    if (!sc->found) {
1133
126
        return "inconclusive";
1134
126
    }
1135
6.41k
    return BIP22ValidationResult(sc->state);
1136
6.54k
},
1137
9.04k
    };
1138
9.04k
}
1139
1140
static RPCMethod submitheader()
1141
4.21k
{
1142
4.21k
    return RPCMethod{
1143
4.21k
        "submitheader",
1144
4.21k
        "Decode the given hexdata as a header and submit it as a candidate chain tip if valid."
1145
4.21k
                "\nThrows when the header is invalid.\n",
1146
4.21k
                {
1147
4.21k
                    {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"},
1148
4.21k
                },
1149
4.21k
                RPCResult{
1150
4.21k
                    RPCResult::Type::NONE, "", "None"},
1151
4.21k
                RPCExamples{
1152
4.21k
                    HelpExampleCli("submitheader", "\"aabbcc\"") +
1153
4.21k
                    HelpExampleRpc("submitheader", "\"aabbcc\"")
1154
4.21k
                },
1155
4.21k
        [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
1156
4.21k
{
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.21k
    };
1178
4.21k
}
1179
1180
void RegisterMiningRPCCommands(CRPCTable& t)
1181
1.30k
{
1182
1.30k
    static const CRPCCommand commands[]{
1183
1.30k
        {"mining", &getnetworkhashps},
1184
1.30k
        {"mining", &getmininginfo},
1185
1.30k
        {"mining", &prioritisetransaction},
1186
1.30k
        {"mining", &getprioritisedtransactions},
1187
1.30k
        {"mining", &getblocktemplate},
1188
1.30k
        {"mining", &submitblock},
1189
1.30k
        {"mining", &submitheader},
1190
1191
1.30k
        {"hidden", &generatetoaddress},
1192
1.30k
        {"hidden", &generatetodescriptor},
1193
1.30k
        {"hidden", &generateblock},
1194
1.30k
        {"hidden", &generate},
1195
1.30k
    };
1196
14.3k
    for (const auto& c : commands) {
1197
14.3k
        t.appendCommand(c.name, &c);
1198
14.3k
    }
1199
1.30k
}