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