Line data Source code
1 : // Copyright (c) 2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2014-2015 The Dash developers
4 : // Copyright (c) 2015-2022 The PIVX Core developers
5 : // Distributed under the MIT software license, see the accompanying
6 : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
7 :
8 : #include "amount.h"
9 : #include "blockassembler.h"
10 : #include "chainparams.h"
11 : #include "core_io.h"
12 : #include "key_io.h"
13 : #include "miner.h"
14 : #include "net.h"
15 : #include "rpc/server.h"
16 : #include "shutdown.h"
17 : #include "util/blockstatecatcher.h"
18 : #include "validationinterface.h"
19 : #ifdef ENABLE_WALLET
20 : #include "wallet/rpcwallet.h"
21 : #include "wallet/db.h"
22 : #include "wallet/wallet.h"
23 : #endif
24 : #include "warnings.h"
25 :
26 : #include <univalue.h>
27 :
28 : #ifdef ENABLE_WALLET
29 3271 : UniValue generateBlocks(const Consensus::Params& consensus,
30 : CWallet* const pwallet,
31 : bool fPoS,
32 : const int nGenerate,
33 : int nHeight,
34 : int nHeightEnd,
35 : CScript* coinbaseScript)
36 : {
37 3271 : UniValue blockHashes(UniValue::VARR);
38 :
39 3277 : BlockStateCatcherWrapper sc(UINT256_ZERO);
40 3271 : sc.registerEvent();
41 15746 : while (nHeight < nHeightEnd && !ShutdownRequested()) {
42 :
43 : // Get available coins
44 24956 : std::vector<CStakeableOutput> availableCoins;
45 12481 : if (fPoS && !pwallet->StakeableCoins(&availableCoins)) {
46 0 : throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "No available coins to stake");
47 : }
48 :
49 12481 : std::unique_ptr<CBlockTemplate> pblocktemplate(fPoS ?
50 14356 : BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(CScript(), pwallet, true, &availableCoins) :
51 26831 : CreateNewBlockWithScript(*coinbaseScript, pwallet));
52 12481 : if (!pblocktemplate.get()) break;
53 24950 : std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
54 :
55 12475 : if(!fPoS) {
56 10606 : if (ShutdownRequested()) break;
57 10606 : if (!SolveBlock(pblock, nHeight + 1)) continue;
58 : }
59 :
60 12475 : sc.get().setBlockHash(pblock->GetHash());
61 12475 : bool res = ProcessNewBlock(pblock, nullptr);
62 12475 : if (!res || sc.get().stateErrorFound())
63 0 : throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
64 :
65 12475 : ++nHeight;
66 12475 : blockHashes.push_back(pblock->GetHash().GetHex());
67 :
68 : // Check PoS if needed.
69 12475 : if (!fPoS)
70 10606 : fPoS = consensus.NetworkUpgradeActive(nHeight + 1, Consensus::UPGRADE_POS);
71 : }
72 :
73 3271 : const int nGenerated = blockHashes.size();
74 3271 : if (nGenerated == 0 || (!fPoS && nGenerated < nGenerate))
75 12 : throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new blocks");
76 :
77 3265 : return blockHashes;
78 : }
79 :
80 3271 : UniValue generate(const JSONRPCRequest& request)
81 : {
82 3271 : CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
83 :
84 3271 : if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
85 0 : return NullUniValue;
86 :
87 3271 : if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
88 0 : throw std::runtime_error(
89 : "generate nblocks\n"
90 : "\nMine blocks immediately (before the RPC call returns)\n"
91 : "\nNote: this function can only be used on the regtest network\n"
92 :
93 : "\nArguments:\n"
94 : "1. nblocks (numeric, required) How many blocks to generate.\n"
95 :
96 : "\nResult\n"
97 : "[ blockhashes ] (array) hashes of blocks generated\n"
98 :
99 : "\nExamples:\n"
100 : "\nGenerate 11 blocks\n"
101 0 : + HelpExampleCli("generate", "11")
102 0 : );
103 :
104 3271 : if (!Params().IsRegTestNet())
105 0 : throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
106 :
107 3271 : const int nGenerate = request.params[0].get_int();
108 3271 : int nHeightEnd = 0;
109 3271 : int nHeight = 0;
110 :
111 3271 : { // Don't keep cs_main locked
112 3271 : LOCK(cs_main);
113 3271 : nHeight = chainActive.Height();
114 3271 : nHeightEnd = nHeight + nGenerate;
115 : }
116 :
117 3271 : const Consensus::Params& consensus = Params().GetConsensus();
118 3271 : bool fPoS = consensus.NetworkUpgradeActive(nHeight + 1, Consensus::UPGRADE_POS);
119 6 : std::unique_ptr<CReserveKey> reservekey;
120 6542 : CScript coinbaseScript;
121 :
122 3271 : if (fPoS) {
123 : // If we are in PoS, wallet must be unlocked.
124 626 : EnsureWalletIsUnlocked(pwallet);
125 : } else {
126 : // Coinbase key
127 2645 : reservekey = std::make_unique<CReserveKey>(pwallet);
128 2645 : CPubKey pubkey;
129 2645 : if (!reservekey->GetReservedKey(pubkey)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Error: Cannot get key from keypool");
130 2651 : coinbaseScript = GetScriptForDestination(pubkey.GetID());
131 : }
132 :
133 : // Create the blocks
134 3271 : UniValue blockHashes = generateBlocks(consensus,
135 : pwallet,
136 : fPoS,
137 : nGenerate,
138 : nHeight,
139 : nHeightEnd,
140 6536 : &coinbaseScript);
141 :
142 : // mark key as used, only for PoW coinbases
143 3265 : if (reservekey) {
144 : // Remove key from key pool
145 2645 : reservekey->KeepKey();
146 : }
147 :
148 3265 : return blockHashes;
149 : }
150 :
151 0 : UniValue generatetoaddress(const JSONRPCRequest& request)
152 : {
153 0 : CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
154 :
155 0 : if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
156 0 : return NullUniValue;
157 :
158 0 : if (request.fHelp || request.params.size() != 2)
159 0 : throw std::runtime_error(
160 : "generatetoaddress nblocks \"address\"\n"
161 : "\nMine blocks immediately to a specified address (before the RPC call returns)\n"
162 : "\nArguments:\n"
163 : "1. nblocks (numeric, required) How many blocks are generated immediately.\n"
164 : "2. \"address\" (string, required) The address to send the newly generated bitcoin to.\n"
165 : "\nResult\n"
166 : "[ blockhashes ] (array) hashes of blocks generated\n"
167 : "\nExamples:\n"
168 : "\nGenerate 11 blocks to myaddress\n"
169 0 : + HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
170 0 : );
171 :
172 0 : int nGenerate = request.params[0].get_int();
173 0 : CTxDestination dest(DecodeDestination(request.params[1].get_str()));
174 0 : if (!IsValidDestination(dest)) {
175 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
176 : }
177 0 : CScript coinbaseScript = GetScriptForDestination(dest);
178 :
179 0 : const Consensus::Params& consensus = Params().GetConsensus();
180 0 : int nHeightEnd = 0;
181 0 : int nHeight = 0;
182 :
183 0 : { // Don't keep cs_main locked
184 0 : LOCK(cs_main);
185 0 : nHeight = chainActive.Height();
186 0 : nHeightEnd = nHeight + nGenerate;
187 : }
188 :
189 0 : bool fPoS = consensus.NetworkUpgradeActive(nHeight + 1, Consensus::UPGRADE_POS);
190 0 : return generateBlocks(consensus,
191 : pwallet,
192 : fPoS,
193 : nGenerate,
194 : nHeight,
195 : nHeightEnd,
196 0 : &coinbaseScript);
197 : }
198 :
199 : #endif // ENABLE_WALLET
200 :
201 : #ifdef ENABLE_MINING_RPC
202 : /**
203 : * Return average network hashes per second based on the last 'lookup' blocks,
204 : * or from the last difficulty change if 'lookup' is nonpositive.
205 : * If 'height' is nonnegative, compute the estimate at the time when a given block was found.
206 : */
207 : UniValue GetNetworkHashPS(int lookup, int height)
208 : {
209 : CBlockIndex *pb = chainActive.Tip();
210 :
211 : if (height >= 0 && height < chainActive.Height())
212 : pb = chainActive[height];
213 :
214 : if (pb == nullptr || !pb->nHeight)
215 : return 0;
216 :
217 : // If lookup is -1, then use blocks since last difficulty change.
218 : if (lookup <= 0)
219 : lookup = pb->nHeight % 2016 + 1;
220 :
221 : // If lookup is larger than chain, then set it to chain length.
222 : if (lookup > pb->nHeight)
223 : lookup = pb->nHeight;
224 :
225 : CBlockIndex* pb0 = pb;
226 : int64_t minTime = pb0->GetBlockTime();
227 : int64_t maxTime = minTime;
228 : for (int i = 0; i < lookup; i++) {
229 : pb0 = pb0->pprev;
230 : int64_t time = pb0->GetBlockTime();
231 : minTime = std::min(time, minTime);
232 : maxTime = std::max(time, maxTime);
233 : }
234 :
235 : // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
236 : if (minTime == maxTime)
237 : return 0;
238 :
239 : arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork;
240 : int64_t timeDiff = maxTime - minTime;
241 :
242 : return (int64_t)(workDiff.getdouble() / timeDiff);
243 : }
244 :
245 : UniValue getnetworkhashps(const JSONRPCRequest& request)
246 : {
247 : if (request.fHelp || request.params.size() > 2)
248 : throw std::runtime_error(
249 : "getnetworkhashps ( nblocks height )\n"
250 : "\nReturns the estimated network hashes per second based on the last n blocks.\n"
251 : "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
252 : "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
253 :
254 : "\nArguments:\n"
255 : "1. nblocks (numeric, optional, default=120) The number of blocks, or -1 for blocks since last difficulty change.\n"
256 : "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n"
257 :
258 : "\nResult:\n"
259 : "x (numeric) Hashes per second estimated\n"
260 : "\nExamples:\n" +
261 : HelpExampleCli("getnetworkhashps", "") + HelpExampleRpc("getnetworkhashps", ""));
262 :
263 : LOCK(cs_main);
264 : return GetNetworkHashPS(request.params.size() > 0 ? request.params[0].get_int() : 120, request.params.size() > 1 ? request.params[1].get_int() : -1);
265 : }
266 :
267 : #ifdef ENABLE_WALLET
268 : UniValue getgenerate(const JSONRPCRequest& request)
269 : {
270 : if (request.fHelp || request.params.size() != 0)
271 : throw std::runtime_error(
272 : "getgenerate\n"
273 : "\nReturn if the server is set to generate coins or not. The default is false.\n"
274 : "It is set with the command line argument -gen (or pivx.conf setting gen)\n"
275 : "It can also be set with the setgenerate call.\n"
276 :
277 : "\nResult\n"
278 : "true|false (boolean) If the server is set to generate coins or not\n"
279 :
280 : "\nExamples:\n" +
281 : HelpExampleCli("getgenerate", "") + HelpExampleRpc("getgenerate", ""));
282 :
283 : LOCK(cs_main);
284 : return gArgs.GetBoolArg("-gen", false);
285 : }
286 :
287 : UniValue setgenerate(const JSONRPCRequest& request)
288 : {
289 : CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
290 :
291 : if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
292 : return NullUniValue;
293 :
294 : if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
295 : throw std::runtime_error(
296 : "setgenerate generate ( genproclimit )\n"
297 : "\nSet 'generate' true or false to turn generation on or off.\n"
298 : "Generation is limited to 'genproclimit' processors, -1 is unlimited.\n"
299 : "See the getgenerate call for the current setting.\n"
300 :
301 : "\nArguments:\n"
302 : "1. generate (boolean, required) Set to true to turn on generation, false to turn off.\n"
303 : "2. genproclimit (numeric, optional) Set the processor limit for when generation is on. Can be -1 for unlimited.\n"
304 :
305 : "\nExamples:\n"
306 : "\nSet the generation on with a limit of one processor\n" +
307 : HelpExampleCli("setgenerate", "true 1") +
308 : "\nCheck the setting\n" + HelpExampleCli("getgenerate", "") +
309 : "\nTurn off generation\n" + HelpExampleCli("setgenerate", "false") +
310 : "\nUsing json rpc\n" + HelpExampleRpc("setgenerate", "true, 1"));
311 :
312 : if (Params().IsRegTestNet())
313 : throw JSONRPCError(RPC_INVALID_REQUEST, "Use the generate method instead of setgenerate on regtest");
314 :
315 : bool fGenerate = true;
316 : if (request.params.size() > 0)
317 : fGenerate = request.params[0].get_bool();
318 :
319 : const int nHeight = WITH_LOCK(cs_main, return chainActive.Height() + 1);
320 : if (fGenerate && Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_POS))
321 : throw JSONRPCError(RPC_INVALID_REQUEST, "Proof of Work phase has already ended");
322 :
323 : int nGenProcLimit = -1;
324 : if (request.params.size() > 1) {
325 : nGenProcLimit = request.params[1].get_int();
326 : if (nGenProcLimit == 0)
327 : fGenerate = false;
328 : }
329 :
330 : gArgs.GetArg("-gen", "") = (fGenerate ? "1" : "0");
331 : gArgs.GetArg("-genproclimit", "") = itostr(nGenProcLimit);
332 : GenerateBitcoins(fGenerate, pwallet, nGenProcLimit);
333 :
334 : return NullUniValue;
335 : }
336 :
337 : UniValue gethashespersec(const JSONRPCRequest& request)
338 : {
339 : if (request.fHelp || request.params.size() != 0)
340 : throw std::runtime_error(
341 : "gethashespersec\n"
342 : "\nReturns a recent hashes per second performance measurement while generating.\n"
343 : "See the getgenerate and setgenerate calls to turn generation on and off.\n"
344 :
345 : "\nResult:\n"
346 : "n (numeric) The recent hashes per second when generation is on (will return 0 if generation is off)\n"
347 :
348 : "\nExamples:\n" +
349 : HelpExampleCli("gethashespersec", "") + HelpExampleRpc("gethashespersec", ""));
350 :
351 : if (GetTimeMillis() - nHPSTimerStart > 8000)
352 : return (int64_t)0;
353 : return (int64_t)dHashesPerSec;
354 : }
355 : #endif
356 :
357 :
358 : UniValue getmininginfo(const JSONRPCRequest& request)
359 : {
360 : if (request.fHelp || request.params.size() != 0)
361 : throw std::runtime_error(
362 : "getmininginfo\n"
363 : "\nReturns a json object containing mining-related information."
364 :
365 : "\nResult:\n"
366 : "{\n"
367 : " \"blocks\": nnn, (numeric) The current block\n"
368 : " \"currentblocksize\": nnn, (numeric) The last block size\n"
369 : " \"currentblocktx\": nnn, (numeric) The last block transaction\n"
370 : " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
371 : " \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
372 : " \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
373 : " \"hashespersec\": n (numeric) The hashes per second of the generation, or 0 if no generation.\n"
374 : " \"pooledtx\": n (numeric) The size of the mem pool\n"
375 : " \"testnet\": true|false (boolean) If using testnet or not\n"
376 : " \"chain\": \"xxxx\", (string) current network name (main, test, regtest)\n"
377 : " \"warnings\": \"...\" (string) any network and blockchain warnings\n"
378 : " \"errors\": \"...\" (string) DEPRECATED. Same as warnings. Only shown when bitcoind is started with -deprecatedrpc=getmininginfo\n"
379 : "}\n"
380 :
381 : "\nExamples:\n" +
382 : HelpExampleCli("getmininginfo", "") + HelpExampleRpc("getmininginfo", ""));
383 :
384 : LOCK(cs_main);
385 :
386 : UniValue obj(UniValue::VOBJ);
387 : obj.pushKV("blocks", (int)chainActive.Height());
388 : obj.pushKV("currentblocksize", (uint64_t)nLastBlockSize);
389 : obj.pushKV("currentblocktx", (uint64_t)nLastBlockTx);
390 : obj.pushKV("difficulty", (double)GetDifficulty());
391 : obj.pushKV("genproclimit", (int)gArgs.GetArg("-genproclimit", -1));
392 : obj.pushKV("networkhashps", getnetworkhashps(request));
393 : obj.pushKV("pooledtx", (uint64_t)mempool.size());
394 : obj.pushKV("testnet", Params().IsTestnet());
395 : obj.pushKV("chain", Params().NetworkIDString());
396 : obj.pushKV("errors", GetWarnings("statusbar"));
397 : if (IsDeprecatedRPCEnabled("getmininginfo")) {
398 : obj.pushKV("errors", GetWarnings("statusbar"));
399 : } else {
400 : obj.pushKV("warnings", GetWarnings("statusbar"));
401 : }
402 : #ifdef ENABLE_WALLET
403 : obj.pushKV("generate", getgenerate(request));
404 : obj.pushKV("hashespersec", gethashespersec(request));
405 : #endif
406 : return obj;
407 : }
408 : #endif // ENABLE_MINING_RPC
409 :
410 : // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
411 2 : UniValue prioritisetransaction(const JSONRPCRequest& request)
412 : {
413 2 : if (request.fHelp || request.params.size() != 2)
414 0 : throw std::runtime_error(
415 : "prioritisetransaction \"txid\" priority_delta fee_delta\n"
416 : "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
417 :
418 : "\nArguments:\n"
419 : "1. \"txid\" (string, required) The transaction id.\n"
420 : "2. fee_delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
421 : " The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
422 : " considers the transaction as it would have paid a higher (or lower) fee.\n"
423 :
424 : "\nResult\n"
425 : "true (boolean) Returns true\n"
426 :
427 0 : "\nExamples:\n" +
428 0 : HelpExampleCli("prioritisetransaction", "\"txid\" 10000") + HelpExampleRpc("prioritisetransaction", "\"txid\", 10000"));
429 :
430 2 : LOCK(cs_main);
431 :
432 2 : uint256 hash = ParseHashStr(request.params[0].get_str(), "txid");
433 2 : CAmount nAmount = request.params[1].get_int64();
434 :
435 2 : mempool.PrioritiseTransaction(hash, nAmount);
436 4 : return true;
437 : }
438 :
439 : // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
440 24 : static UniValue BIP22ValidationResult(const CValidationState& state)
441 : {
442 24 : if (state.IsValid())
443 16 : return NullUniValue;
444 :
445 32 : std::string strRejectReason = state.GetRejectReason();
446 8 : if (state.IsError())
447 0 : throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
448 8 : if (state.IsInvalid()) {
449 8 : if (strRejectReason.empty())
450 4 : return "rejected";
451 4 : return strRejectReason;
452 : }
453 : // Should be impossible
454 0 : return "valid?";
455 : }
456 :
457 : #ifdef ENABLE_MINING_RPC
458 : UniValue getblocktemplate(const JSONRPCRequest& request)
459 : {
460 : CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
461 :
462 : if (request.fHelp || request.params.size() > 1)
463 : throw std::runtime_error(
464 : "getblocktemplate ( \"template_request\" )\n"
465 : "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
466 : "It returns data needed to construct a block to work on.\n"
467 : "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
468 :
469 : "\nArguments:\n"
470 : "1. template_request (json object, optional) A json object in the following spec\n"
471 : " {\n"
472 : " \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n"
473 : " \"capabilities\":[ (array, optional) A list of strings\n"
474 : " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
475 : " ,...\n"
476 : " ]\n"
477 : " }\n"
478 : "\n"
479 :
480 : "\nResult:\n"
481 : "{\n"
482 : " \"version\" : n, (numeric) The block version\n"
483 : " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n"
484 : " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
485 : " {\n"
486 : " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
487 : " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n"
488 : " \"depends\" : [ (array) array of numbers \n"
489 : " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
490 : " ,...\n"
491 : " ],\n"
492 : " \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in upiv); 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\n"
493 : " \"sigops\" : n, (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n"
494 : " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
495 : " }\n"
496 : " ,...\n"
497 : " ],\n"
498 : " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n"
499 : " \"flags\" : \"flags\" (string) \n"
500 : " },\n"
501 : " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in upiv)\n"
502 : " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n"
503 : " \"target\" : \"xxxx\", (string) The hash target\n"
504 : " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
505 : " \"mutable\" : [ (array of string) list of ways the block template may be changed \n"
506 : " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
507 : " ,...\n"
508 : " ],\n"
509 : " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n"
510 : " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n"
511 : " \"sizelimit\" : n, (numeric) limit of block size\n"
512 : " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
513 : " \"bits\" : \"xxx\", (string) compressed target of next block\n"
514 : " \"height\" : n (numeric) The height of the next block\n"
515 : " \"payee\" : \"xxx\", (string) required payee for the next block\n"
516 : " \"payee_amount\" : n, (numeric) required amount to pay\n"
517 : " \"votes\" : [\n (array) show vote candidates\n"
518 : " { ... } (json object) vote candidate\n"
519 : " ,...\n"
520 : " ],\n"
521 : " \"enforce_masternode_payments\" : true|false (boolean) true, if masternode payments are enforced\n"
522 : "}\n"
523 :
524 : "\nExamples:\n" +
525 : HelpExampleCli("getblocktemplate", "") + HelpExampleRpc("getblocktemplate", ""));
526 :
527 : LOCK(cs_main);
528 :
529 : std::string strMode = "template";
530 : UniValue lpval = NullUniValue;
531 : if (request.params.size() > 0) {
532 : const UniValue& oparam = request.params[0].get_obj();
533 : const UniValue& modeval = find_value(oparam, "mode");
534 : if (modeval.isStr())
535 : strMode = modeval.get_str();
536 : else if (modeval.isNull()) {
537 : /* Do nothing */
538 : } else
539 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
540 : lpval = find_value(oparam, "longpollid");
541 :
542 : if (strMode == "proposal") {
543 : const UniValue& dataval = find_value(oparam, "data");
544 : if (!dataval.isStr())
545 : throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
546 :
547 : CBlock block;
548 : if (!DecodeHexBlk(block, dataval.get_str()))
549 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
550 :
551 : uint256 hash = block.GetHash();
552 : CBlockIndex* pindex = LookupBlockIndex(hash);
553 : if (pindex) {
554 : if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
555 : return "duplicate";
556 : if (pindex->nStatus & BLOCK_FAILED_MASK)
557 : return "duplicate-invalid";
558 : return "duplicate-inconclusive";
559 : }
560 :
561 : CBlockIndex* const pindexPrev = chainActive.Tip();
562 : // TestBlockValidity only supports blocks built on the current Tip
563 : if (block.hashPrevBlock != pindexPrev->GetBlockHash())
564 : return "inconclusive-not-best-prevblk";
565 : CValidationState state;
566 : TestBlockValidity(state, block, pindexPrev, false, true);
567 : return BIP22ValidationResult(state);
568 : }
569 : }
570 :
571 : if (strMode != "template")
572 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
573 :
574 : if(!g_connman)
575 : throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
576 :
577 : if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
578 : throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "PIVX is not connected!");
579 :
580 : if (IsInitialBlockDownload())
581 : throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "PIVX is downloading blocks...");
582 :
583 : static unsigned int nTransactionsUpdatedLast;
584 :
585 : if (!lpval.isNull()) {
586 : // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
587 : uint256 hashWatchedChain;
588 : std::chrono::steady_clock::time_point checktxtime;
589 : unsigned int nTransactionsUpdatedLastLP;
590 :
591 : if (lpval.isStr()) {
592 : // Format: <hashBestChain><nTransactionsUpdatedLast>
593 : std::string lpstr = lpval.get_str();
594 :
595 : hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
596 : nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
597 : } else {
598 : // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
599 : hashWatchedChain = chainActive.Tip()->GetBlockHash();
600 : nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
601 : }
602 :
603 : // Release the wallet and main lock while waiting
604 : LEAVE_CRITICAL_SECTION(cs_main);
605 : {
606 : checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
607 :
608 : WAIT_LOCK(g_best_block_mutex, lock);
609 : while (g_best_block == hashWatchedChain && IsRPCRunning()) {
610 : if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout)
611 : {
612 : // Timeout: Check transactions for update
613 : if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
614 : break;
615 : checktxtime += std::chrono::seconds(10);
616 : }
617 : }
618 : }
619 : ENTER_CRITICAL_SECTION(cs_main);
620 :
621 : if (!IsRPCRunning())
622 : throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
623 : // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
624 : }
625 :
626 : // Update block
627 : static CBlockIndex* pindexPrev;
628 : static int64_t nStart;
629 : static std::unique_ptr<CBlockTemplate> pblocktemplate;
630 : if (pindexPrev != chainActive.Tip() ||
631 : (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) {
632 : // Clear pindexPrev so future calls make a new block, despite any failures from here on
633 : pindexPrev = nullptr;
634 :
635 : // Store the chainActive.Tip() used before CreateNewBlock, to avoid races
636 : nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
637 : CBlockIndex* pindexPrevNew = chainActive.Tip();
638 : nStart = GetTime();
639 :
640 : // Create new block
641 : if (pblocktemplate) {
642 : pblocktemplate.release();
643 : pblocktemplate = nullptr;
644 : }
645 : CScript scriptDummy = CScript() << OP_TRUE;
646 : pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptDummy, pwallet, false);
647 : if (!pblocktemplate)
648 : throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
649 :
650 : // Need to update only after we know CreateNewBlock succeeded
651 : pindexPrev = pindexPrevNew;
652 : }
653 : CBlock* pblock = &pblocktemplate->block; // pointer for convenience
654 :
655 : // Update nTime
656 : UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
657 : pblock->nNonce = 0;
658 :
659 : UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
660 :
661 : UniValue transactions(UniValue::VARR);
662 : std::map<uint256, int64_t> setTxIndex;
663 : int i = 0;
664 : for (const auto& txIn : pblock->vtx) {
665 : const CTransaction& tx = *txIn;
666 : const uint256& txHash = tx.GetHash();
667 : setTxIndex[txHash] = i++;
668 :
669 : if (tx.IsCoinBase())
670 : continue;
671 :
672 : UniValue entry(UniValue::VOBJ);
673 :
674 : entry.pushKV("data", EncodeHexTx(tx));
675 :
676 : entry.pushKV("hash", txHash.GetHex());
677 :
678 : UniValue deps(UniValue::VARR);
679 : for (const CTxIn& in : tx.vin) {
680 : if (setTxIndex.count(in.prevout.hash))
681 : deps.push_back(setTxIndex[in.prevout.hash]);
682 : }
683 : entry.pushKV("depends", deps);
684 :
685 : int index_in_template = i - 1;
686 : entry.pushKV("fee", pblocktemplate->vTxFees[index_in_template]);
687 : entry.pushKV("sigops", pblocktemplate->vTxSigOps[index_in_template]);
688 :
689 : transactions.push_back(entry);
690 : }
691 :
692 : UniValue aux(UniValue::VOBJ);
693 : aux.pushKV("flags", HexStr(COINBASE_FLAGS));
694 :
695 : arith_uint256& hashTarget = arith_uint256().SetCompact(pblock->nBits);
696 :
697 : static UniValue aMutable(UniValue::VARR);
698 : if (aMutable.empty()) {
699 : aMutable.push_back("time");
700 : aMutable.push_back("transactions");
701 : aMutable.push_back("prevblock");
702 : }
703 :
704 : UniValue aVotes(UniValue::VARR);
705 :
706 : UniValue result(UniValue::VOBJ);
707 : result.pushKV("capabilities", aCaps);
708 : result.pushKV("version", pblock->nVersion);
709 : result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
710 : result.pushKV("transactions", transactions);
711 : result.pushKV("coinbaseaux", aux);
712 : result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->GetValueOut());
713 : result.pushKV("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast));
714 : result.pushKV("target", hashTarget.GetHex());
715 : result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast() + 1);
716 : result.pushKV("mutable", aMutable);
717 : result.pushKV("noncerange", "00000000ffffffff");
718 : // result.pushKV("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS);
719 : // result.pushKV("sizelimit", (int64_t)MAX_BLOCK_SIZE);
720 : result.pushKV("curtime", pblock->GetBlockTime());
721 : result.pushKV("bits", strprintf("%08x", pblock->nBits));
722 : result.pushKV("height", (int64_t)(pindexPrev->nHeight + 1));
723 : result.pushKV("votes", aVotes);
724 : result.pushKV("enforce_masternode_payments", true);
725 :
726 : return result;
727 : }
728 : #endif // ENABLE_MINING_RPC
729 :
730 50 : UniValue submitblock(const JSONRPCRequest& request)
731 : {
732 50 : if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
733 0 : throw std::runtime_error(
734 : "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
735 : "\nAttempts to submit new block to network.\n"
736 : "The 'jsonparametersobject' parameter is currently ignored.\n"
737 : "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
738 :
739 : "\nArguments\n"
740 : "1. \"hexdata\" (string, required) the hex-encoded block data to submit\n"
741 : "2. \"parameters\" (string, optional) object of optional parameters\n"
742 : " {\n"
743 : " \"workid\" : \"id\" (string, optional) if the server provided a workid, it MUST be included with submissions\n"
744 : " }\n"
745 :
746 : "\nResult:\n"
747 :
748 0 : "\nExamples:\n" +
749 0 : HelpExampleCli("submitblock", "\"mydata\"") + HelpExampleRpc("submitblock", "\"mydata\""));
750 :
751 100 : std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
752 50 : CBlock& block = *blockptr;
753 50 : if (!DecodeHexBlk(block, request.params[0].get_str()))
754 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
755 :
756 50 : if (block.vtx.empty() || !block.vtx[0]->IsCoinBase()) {
757 0 : throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block does not start with a coinbase");
758 : }
759 :
760 50 : uint256 hash = block.GetHash();
761 50 : bool fBlockPresent = false;
762 50 : {
763 50 : LOCK(cs_main);
764 50 : CBlockIndex* pindex = LookupBlockIndex(hash);
765 50 : if (pindex) {
766 0 : if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
767 0 : return "duplicate";
768 0 : if (pindex->nStatus & BLOCK_FAILED_MASK)
769 0 : return "duplicate-invalid";
770 : // Otherwise, we might only have the header - process the block before returning
771 : fBlockPresent = true;
772 : }
773 : }
774 :
775 100 : BlockStateCatcherWrapper sc(block.GetHash());
776 50 : sc.registerEvent();
777 50 : bool fAccepted = ProcessNewBlock(blockptr, nullptr);
778 50 : if (fBlockPresent) {
779 0 : if (fAccepted && !sc.get().found)
780 0 : return "duplicate-inconclusive";
781 0 : return "duplicate";
782 : }
783 50 : if (fAccepted) {
784 40 : if (!sc.get().found)
785 26 : return "inconclusive";
786 : }
787 24 : return BIP22ValidationResult(sc.get().state);
788 : }
789 :
790 125 : UniValue estimatefee(const JSONRPCRequest& request)
791 : {
792 125 : if (request.fHelp || request.params.size() != 1)
793 0 : throw std::runtime_error(
794 : "estimatefee nblocks\n"
795 : "\nEstimates the approximate fee per kilobyte\n"
796 : "needed for a transaction to begin confirmation\n"
797 : "within nblocks blocks.\n"
798 :
799 : "\nArguments:\n"
800 : "1. nblocks (numeric)\n"
801 :
802 : "\nResult:\n"
803 : "n : (numeric) estimated fee-per-kilobyte\n"
804 : "\n"
805 : "-1.0 is returned if not enough transactions and\n"
806 : "blocks have been observed to make an estimate.\n"
807 :
808 0 : "\nExample:\n" +
809 0 : HelpExampleCli("estimatefee", "6"));
810 :
811 125 : RPCTypeCheck(request.params, {UniValue::VNUM});
812 :
813 125 : int nBlocks = request.params[0].get_int();
814 125 : if (nBlocks < 1)
815 0 : nBlocks = 1;
816 :
817 125 : CFeeRate feeRate = mempool.estimateFee(nBlocks);
818 125 : if (feeRate == CFeeRate(0))
819 1 : return -1.0;
820 :
821 124 : return ValueFromAmount(feeRate.GetFeePerK());
822 : }
823 :
824 62 : UniValue estimatesmartfee(const JSONRPCRequest& request)
825 : {
826 62 : if (request.fHelp || request.params.size() != 1)
827 0 : throw std::runtime_error(
828 : "estimatesmartfee nblocks\n"
829 : "\nDEPRECATED. WARNING: This interface is unstable and may disappear or change!\n"
830 : "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
831 : "confirmation within nblocks blocks if possible and return the number of blocks\n"
832 : "for which the estimate is valid.\n"
833 : "\nArguments:\n"
834 : "1. nblocks (numeric)\n"
835 : "\nResult:\n"
836 : "{\n"
837 : " \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n"
838 : " \"blocks\" : n (numeric) block number where estimate was found\n"
839 : "}\n"
840 : "\n"
841 : "A negative value is returned if not enough transactions and blocks\n"
842 : "have been observed to make an estimate for any number of blocks.\n"
843 : "However it will not return a value below the mempool reject fee.\n"
844 : "\nExample:\n"
845 0 : + HelpExampleCli("estimatesmartfee", "6")
846 0 : );
847 :
848 62 : RPCTypeCheck(request.params, {UniValue::VNUM});
849 :
850 62 : int nBlocks = request.params[0].get_int();
851 :
852 62 : UniValue result(UniValue::VOBJ);
853 62 : int answerFound;
854 62 : CFeeRate feeRate = mempool.estimateSmartFee(nBlocks, &answerFound);
855 186 : result.pushKV("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()));
856 62 : result.pushKV("blocks", answerFound);
857 62 : return result;
858 : }
859 :
860 : // clang-format off
861 : static const CRPCCommand commands[] =
862 : { // category name actor (function) okSafe argNames
863 : // --------------------- ------------------------ ----------------------- ------ --------
864 : { "util", "estimatefee", &estimatefee, true, {"nblocks"} },
865 : { "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks"} },
866 : { "mining", "prioritisetransaction", &prioritisetransaction, true, {"txid","priority_delta","fee_delta"} },
867 :
868 : /** Not shown in help */
869 : #ifdef ENABLE_WALLET
870 : { "hidden", "generate", &generate, true, {"nblocks"} },
871 : { "hidden", "generatetoaddress", &generatetoaddress, true, {"nblocks","address"} },
872 : #endif
873 : { "hidden", "submitblock", &submitblock, true, {"hexdata","parameters"} },
874 : #ifdef ENABLE_MINING_RPC
875 : { "hidden", "getblocktemplate", &getblocktemplate, true, {"template_request"} },
876 : { "hidden", "getnetworkhashps", &getnetworkhashps, true, {"nblocks","height"} },
877 : { "hidden", "getmininginfo", &getmininginfo, true, {} },
878 : #ifdef ENABLE_WALLET
879 : { "hidden", "getgenerate", &getgenerate, true, {} },
880 : { "hidden", "gethashespersec", &gethashespersec, true, {} },
881 : { "hidden", "setgenerate", &setgenerate, true, {"generate","genproclimit"} },
882 : #endif // ENABLE_WALLET
883 : #endif // ENABLE_MINING_RPC
884 :
885 : };
886 : // clang-format on
887 :
888 494 : void RegisterMiningRPCCommands(CRPCTable &tableRPC)
889 : {
890 3458 : for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
891 2964 : tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
892 494 : }
|