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