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