1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php .
7 #include "chainparams.h"
8 #include "consensus/consensus.h"
9 #include "consensus/validation.h"
12 #include "crypto/equihash.h"
20 #include "rpc/server.h"
21 #include "txmempool.h"
23 #include "validationinterface.h"
25 #include "wallet/wallet.h"
27 #include "pbaas/pbaas.h"
28 #include "pbaas/notarization.h"
32 #include <boost/assign/list_of.hpp>
33 #include <boost/shared_ptr.hpp>
39 extern uint32_t ASSETCHAINS_ALGO;
40 extern int32_t ASSETCHAINS_EQUIHASH, ASSETCHAINS_LWMAPOS;
41 extern int32_t VERUS_MIN_STAKEAGE;
42 extern uint64_t ASSETCHAINS_STAKED;
43 extern int32_t KOMODO_MININGTHREADS;
44 extern bool VERUS_MINTBLOCKS;
45 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
46 arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
47 int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex);
50 * Return average network hashes per second based on the last 'lookup' blocks,
51 * or over the difficulty averaging window if 'lookup' is nonpositive.
52 * If 'height' is nonnegative, compute the estimate at the time when a given block was found.
54 int64_t GetNetworkHashPS(int lookup, int height) {
55 CBlockIndex *pb = chainActive.LastTip();
57 if (height >= 0 && height < chainActive.Height())
58 pb = chainActive[height];
60 if (pb == NULL || !pb->GetHeight())
63 // If lookup is nonpositive, then use difficulty averaging window.
65 lookup = Params().GetConsensus().nPowAveragingWindow;
67 // If lookup is larger than chain, then set it to chain length.
68 if (lookup > pb->GetHeight())
69 lookup = pb->GetHeight();
71 CBlockIndex *pb0 = pb;
72 int64_t minTime = pb0->GetBlockTime();
73 int64_t maxTime = minTime;
74 for (int i = 0; i < lookup; i++) {
76 int64_t time = pb0->GetBlockTime();
77 minTime = std::min(time, minTime);
78 maxTime = std::max(time, maxTime);
81 // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
82 if (minTime == maxTime)
85 arith_uint256 workDiff = pb->chainPower.chainWork - pb0->chainPower.chainWork;
86 int64_t timeDiff = maxTime - minTime;
88 return (int64_t)(workDiff.getdouble() / timeDiff);
91 UniValue getlocalsolps(const UniValue& params, bool fHelp)
96 "\nReturns the average local solutions per second since this node was started.\n"
97 "This is the same information shown on the metrics screen (if enabled).\n"
99 "xxx.xxxxx (numeric) Solutions per second average\n"
101 + HelpExampleCli("getlocalsolps", "")
102 + HelpExampleRpc("getlocalsolps", "")
106 return GetLocalSolPS();
109 UniValue getnetworksolps(const UniValue& params, bool fHelp)
111 if (fHelp || params.size() > 2)
113 "getnetworksolps ( blocks height )\n"
114 "\nReturns the estimated network solutions per second based on the last n blocks.\n"
115 "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n"
116 "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
118 "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n"
119 "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n"
121 "x (numeric) Solutions per second estimated\n"
123 + HelpExampleCli("getnetworksolps", "")
124 + HelpExampleRpc("getnetworksolps", "")
128 return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
131 UniValue getnetworkhashps(const UniValue& params, bool fHelp)
133 if (fHelp || params.size() > 2)
135 "getnetworkhashps ( blocks height )\n"
136 "\nDEPRECATED - left for backwards-compatibility. Use getnetworksolps instead.\n"
137 "\nReturns the estimated network solutions per second based on the last n blocks.\n"
138 "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n"
139 "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
141 "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n"
142 "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n"
144 "x (numeric) Solutions per second estimated\n"
146 + HelpExampleCli("getnetworkhashps", "")
147 + HelpExampleRpc("getnetworkhashps", "")
151 return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
155 extern bool VERUS_MINTBLOCKS;
156 UniValue getgenerate(const UniValue& params, bool fHelp)
158 if (fHelp || params.size() != 0)
161 "\nReturn if the server is set to mine and/or mint coins or not. The default is false.\n"
162 "It is set with the command line argument -gen (or komodo.conf setting gen) and -mint\n"
163 "It can also be set with the setgenerate call.\n"
166 " \"staking\": true|false (boolean) If staking is on or off (see setgenerate)\n"
167 " \"generate\": true|false (boolean) If mining is on or off (see setgenerate)\n"
168 " \"numthreads\": n (numeric) The processor limit for mining. (see setgenerate)\n"
171 + HelpExampleCli("getgenerate", "")
172 + HelpExampleRpc("getgenerate", "")
176 UniValue obj(UniValue::VOBJ);
177 obj.push_back(Pair("staking", VERUS_MINTBLOCKS));
178 obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
179 obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS));
183 extern uint8_t NOTARY_PUBKEY33[33];
185 //Value generate(const Array& params, bool fHelp)
186 UniValue generate(const UniValue& params, bool fHelp)
188 if (fHelp || params.size() < 1 || params.size() > 1)
190 "generate numblocks\n"
191 "\nMine blocks immediately (before the RPC call returns)\n"
192 "\nNote: this function can only be used on the regtest network\n"
194 "1. numblocks (numeric) How many blocks are generated immediately.\n"
196 "[ blockhashes ] (array) hashes of blocks generated\n"
198 "\nGenerate 11 blocks\n"
199 + HelpExampleCli("generate", "11")
202 if (GetArg("-mineraddress", "").empty()) {
205 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
208 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "verusd compiled without wallet and -mineraddress not set");
211 if (!Params().MineBlocksOnDemand())
212 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
214 int nHeightStart = 0;
217 int nGenerate = params[0].get_int();
219 CReserveKey reservekey(pwalletMain);
222 //throw an error if no script was provided
223 if (!reservekey.GetReservedKey(pubKey))
224 throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet or -mineraddress)");
226 { // Don't keep cs_main locked
228 nHeightStart = chainActive.Height();
229 nHeight = nHeightStart;
230 nHeightEnd = nHeightStart+nGenerate;
232 unsigned int nExtraNonce = 0;
233 UniValue blockHashes(UniValue::VARR);
234 unsigned int n = Params().GetConsensus().EquihashN();
235 unsigned int k = Params().GetConsensus().EquihashK();
236 uint64_t lastTime = 0;
237 while (nHeight < nHeightEnd)
239 // Validation may fail if block generation is too fast
240 if (GetTime() == lastTime) MilliSleep(1001);
241 lastTime = GetTime();
244 std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey, nHeight, KOMODO_MAXGPUCOUNT));
246 std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
248 if (!pblocktemplate.get())
249 throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
250 CBlock *pblock = &pblocktemplate->block;
253 IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce);
257 crypto_generichash_blake2b_state eh_state;
258 EhInitialiseState(n, k, eh_state);
260 // I = the block header minus nonce and solution.
261 CEquihashInput I{*pblock};
262 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
266 crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
269 // Yes, there is a chance every nonce could fail to satisfy the -regtest
270 // target -- 1 in 2^(2^256). That ain't gonna happen
271 pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
274 crypto_generichash_blake2b_state curr_state;
275 curr_state = eh_state;
276 crypto_generichash_blake2b_update(&curr_state,
277 pblock->nNonce.begin(),
278 pblock->nNonce.size());
280 // (x_1, x_2, ...) = A(I, V, n, k)
281 std::function<bool(std::vector<unsigned char>)> validBlock =
282 [&pblock](std::vector<unsigned char> soln)
285 pblock->nSolution = soln;
286 solutionTargetChecks.increment();
287 return CheckProofOfWork(*pblock,NOTARY_PUBKEY33,chainActive.Height(),Params().GetConsensus());
289 bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock);
290 ehSolverRuns.increment();
296 CValidationState state;
297 if (!ProcessNewBlock(1, chainActive.LastTip()->GetHeight()+1, state, Params(), NULL, pblock, true, NULL))
298 throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
300 blockHashes.push_back(pblock->GetHash().GetHex());
302 //mark script as important because it was used at least for one coinbase output
303 reservekey.KeepKey();
308 UniValue setgenerate(const UniValue& params, bool fHelp)
310 if (fHelp || params.size() < 1 || params.size() > 2)
312 "setgenerate generate ( genproclimit )\n"
313 "\nSet 'generate' true to turn either mining/generation or minting/staking on and false to turn both off.\n"
314 "Mining is limited to 'genproclimit' processors, -1 is unlimited, setgenerate true with 0 genproclimit turns on staking\n"
315 "See the getgenerate call for the current setting.\n"
317 "1. generate (boolean, required) Set to true to turn on generation, off to turn off.\n"
318 "2. genproclimit (numeric, optional) Set processor limit when generation is on. Can be -1 for unlimited, 0 to turn on staking.\n"
320 "\nSet the generation on with a limit of one processor\n"
321 + HelpExampleCli("setgenerate", "true 1") +
322 "\nTurn minting/staking on\n"
323 + HelpExampleCli("setgenerate", "true 0") +
324 "\nCheck the setting\n"
325 + HelpExampleCli("getgenerate", "") +
326 "\nTurn off generation and minting\n"
327 + HelpExampleCli("setgenerate", "false") +
329 + HelpExampleRpc("setgenerate", "true, 1")
332 if (GetArg("-mineraddress", "").empty()) {
335 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
338 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "verusd compiled without wallet and -mineraddress not set");
341 if (Params().MineBlocksOnDemand())
342 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
344 bool fGenerate = true;
345 if (params.size() > 0)
346 fGenerate = params[0].get_bool();
348 int nGenProcLimit = GetArg("-genproclimit", -1);
350 if (params.size() > 1)
352 gpl = params[1].get_int();
360 VERUS_MINTBLOCKS = 1;
361 KOMODO_MININGTHREADS = -1;
364 if (fGenerate && !gpl && params.size() > 1)
366 VERUS_MINTBLOCKS = 1;
370 VERUS_MINTBLOCKS = 0;
371 KOMODO_MININGTHREADS = 0;
375 KOMODO_MININGTHREADS = (int32_t)nGenProcLimit;
378 mapArgs["-gen"] = (fGenerate ? "1" : "0");
379 mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS);
382 GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
384 GenerateBitcoins(fGenerate, nGenProcLimit);
391 UniValue getmininginfo(const UniValue& params, bool fHelp)
393 if (fHelp || params.size() != 0)
396 "\nReturns a json object containing mining-related information."
399 " \"blocks\": nnn, (numeric) The current block\n"
400 " \"currentblocksize\": nnn, (numeric) The last block size\n"
401 " \"currentblocktx\": nnn, (numeric) The last block transaction\n"
402 " \"averageblockfees\": xxx.xxxxx (numeric) The average block fees, in addition to block reward, over the past 100 blocks\n"
403 " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
404 " \"stakingsupply\": xxx.xxxxx (numeric) The current estimated total staking supply\n"
405 " \"errors\": \"...\" (string) Current errors\n"
406 " \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
407 " \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
408 " \"localsolps\": xxx.xxxxx (numeric) The average local solution rate in Sol/s since this node was started\n"
409 " \"networksolps\": x (numeric) The estimated network solution rate in Sol/s\n"
410 " \"pooledtx\": n (numeric) The size of the mem pool\n"
411 " \"testnet\": true|false (boolean) If using testnet or not\n"
412 " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
414 " \"generate\": true|false (boolean) If this instance is mining or staking\n"
415 " \"staking\": true|false (boolean) If staking\n"
416 " \"numthreads\": n (numeric) Number of CPU threads mining\n"
417 " \"mergemining\": n (numeric) Number of blockchains we are merge mining with\n"
418 " \"mergeminedchains\": [] (optional, list of names) Blockchain names that are being merge mined with this blockchain\n"
422 + HelpExampleCli("getmininginfo", "")
423 + HelpExampleRpc("getmininginfo", "")
429 auto consensus = Params().GetConsensus();
430 uint32_t height = chainActive.Height();
431 CAmount estimatedStakingSupply = 0;
432 CAmount avgBlockFees = 0;
433 bool avgBlockFeesValid = true;
437 int first = height - 100;
439 arith_uint256 bigTotalFees(0);
440 arith_uint256 totalChainStake(0);
441 arith_uint256 bnStakeTarget;
444 for (int i = first; i < height; i++)
446 CBlockIndex &index = *chainActive[i];
449 if (avgBlockFeesValid && komodo_blockload(block, &index))
451 avgBlockFeesValid = false;
452 LogPrintf("%s: failed to estimate average block fees\n", __func__);
456 // subtract block reward from total output of coinbase and add the rest for an average
457 bigTotalFees = bigTotalFees + arith_uint256(block.vtx[0].GetValueOut() - GetBlockSubsidy(index.GetHeight(), consensus));
460 // if POS block, add stake
462 if (i > 100 && index.IsVerusPOSBlock())
464 bnStakeTarget.SetCompact(index.GetVerusPOSTarget());
466 if (bnStakeTarget == 0)
469 avgBlockFees = false;
470 LogPrintf("%s: failed to estimate staking supply\n", __func__);
474 // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
475 // as it's too large for a arith_uint256. However, as 2**256 is at least as large
476 // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
477 // or ~bnTarget / (nTarget+1) + 1.
478 totalChainStake = totalChainStake + (~bnStakeTarget / (bnStakeTarget + 1)) + 1;
483 avgBlockFees = avgBlockFeesValid ? (bigTotalFees / arith_uint256(height - first)).GetLow64() : 0;
487 totalChainStake = totalChainStake / arith_uint256(height - first);
490 if (totalChainStake > arith_uint256(INT64_MAX))
492 LogPrintf("%s: overflow estimating staking supply\n", __func__);
496 estimatedStakingSupply = totalChainStake.GetLow64();
500 UniValue obj(UniValue::VOBJ);
501 obj.push_back(Pair("blocks", (int)height));
502 obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
503 obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
504 obj.push_back(Pair("averageblockfees", ValueFromAmount(avgBlockFees)));
505 obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
506 obj.push_back(Pair("stakingsupply", ValueFromAmount(estimatedStakingSupply)));
507 obj.push_back(Pair("errors", GetWarnings("statusbar")));
508 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
509 if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
511 obj.push_back(Pair("localsolps" , getlocalsolps(params, false)));
512 obj.push_back(Pair("networksolps", getnetworksolps(params, false)));
516 obj.push_back(Pair("localhashps" , GetBoolArg("-gen", false) ? getlocalsolps(params, false) : (double)0.0));
518 obj.push_back(Pair("networkhashps", getnetworksolps(params, false)));
519 obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
520 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
521 obj.push_back(Pair("chain", Params().NetworkIDString()));
523 bool mining = GetBoolArg("-gen", false);
524 obj.push_back(Pair("generate", mining));
525 obj.push_back(Pair("staking", VERUS_MINTBLOCKS));
527 auto chains = ConnectedChains.GetMergeMinedChains();
528 bool mergeMining = mining && ((!IsVerusActive() && ConnectedChains.IsVerusPBaaSAvailable()) || (IsVerusActive() && chains.size()));
529 int numChains = mergeMining ? (IsVerusActive() ? chains.size() + 1 : 1) : 0;
530 obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS));
531 obj.push_back(Pair("mergemining", numChains));
532 if (chains.size() || numChains)
534 UniValue chainNames(UniValue::VARR);
535 for (auto chain : chains)
537 chainNames.push_back(chain.name);
539 obj.push_back(Pair("mergeminedchains", chainNames));
546 // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
547 UniValue prioritisetransaction(const UniValue& params, bool fHelp)
549 if (fHelp || params.size() != 3)
551 "prioritisetransaction <txid> <priority delta> <fee delta>\n"
552 "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
554 "1. \"txid\" (string, required) The transaction id.\n"
555 "2. priority delta (numeric, required) The priority to add or subtract.\n"
556 " The transaction selection algorithm considers the tx as it would have a higher priority.\n"
557 " (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
558 "3. fee delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
559 " The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
560 " considers the transaction as it would have paid a higher (or lower) fee.\n"
562 "true (boolean) Returns true\n"
564 + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
565 + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
570 uint256 hash = ParseHashStr(params[0].get_str(), "txid");
571 CAmount nAmount = params[2].get_int64();
573 mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
578 // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
579 static UniValue BIP22ValidationResult(const CValidationState& state)
584 std::string strRejectReason = state.GetRejectReason();
586 throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
587 if (state.IsInvalid())
589 if (strRejectReason.empty())
591 return strRejectReason;
593 // Should be impossible
597 UniValue getblocktemplate(const UniValue& params, bool fHelp)
599 if (fHelp || params.size() > 1)
601 "getblocktemplate ( \"jsonrequestobject\" )\n"
602 "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
603 "It returns data needed to construct a block to work on.\n"
604 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
607 "1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n"
609 " \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n"
610 " \"capabilities\":[ (array, optional) A list of strings\n"
611 " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
619 " \"version\" : n, (numeric) The block version\n"
620 " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n"
621 " \"finalsaplingroothash\" : \"xxxx\", (string) The hash of the final sapling root\n"
622 " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
624 " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
625 " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n"
626 " \"depends\" : [ (array) array of numbers \n"
627 " 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"
630 " \"fee\": n, (numeric) 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\n"
631 " \"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"
632 " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
636 // " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n"
637 // " \"flags\" : \"flags\" (string) \n"
639 // " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
640 " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n"
641 " \"target\" : \"xxxx\", (string) The hash target\n"
642 " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
643 " \"mutable\" : [ (array of string) list of ways the block template may be changed \n"
644 " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
647 " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n"
648 " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n"
649 " \"sizelimit\" : n, (numeric) limit of block size\n"
650 " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
651 " \"bits\" : \"xxx\", (string) compressed target of next block\n"
652 " \"height\" : n (numeric) The height of the next block\n"
656 + HelpExampleCli("getblocktemplate", "")
657 + HelpExampleRpc("getblocktemplate", "")
662 // Wallet or miner address is required because we support coinbasetxn
663 if (GetArg("-mineraddress", "").empty()) {
666 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
669 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "verusd compiled without wallet and -mineraddress not set");
673 std::string strMode = "template";
674 UniValue lpval = NullUniValue;
676 // TODO: Re-enable coinbasevalue once a specification has been written
677 bool coinbasetxn = true;
679 if (params.size() > 0)
681 const UniValue& oparam = params[0].get_obj();
682 const UniValue& modeval = find_value(oparam, "mode");
684 strMode = modeval.get_str();
685 else if (modeval.isNull())
690 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
691 lpval = find_value(oparam, "longpollid");
693 if (strMode == "proposal")
695 const UniValue& dataval = find_value(oparam, "data");
696 if (!dataval.isStr())
697 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
700 if (!DecodeHexBlk(block, dataval.get_str()))
701 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
703 uint256 hash = block.GetHash();
704 BlockMap::iterator mi = mapBlockIndex.find(hash);
705 if (mi != mapBlockIndex.end()) {
706 CBlockIndex *pindex = mi->second;
709 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
711 if (pindex->nStatus & BLOCK_FAILED_MASK)
712 return "duplicate-invalid";
714 return "duplicate-inconclusive";
717 CBlockIndex* const pindexPrev = chainActive.LastTip();
718 // TestBlockValidity only supports blocks built on the current Tip
719 if (block.hashPrevBlock != pindexPrev->GetBlockHash())
720 return "inconclusive-not-best-prevblk";
721 CValidationState state;
722 TestBlockValidity(state, Params(), block, pindexPrev, false, true);
723 return BIP22ValidationResult(state);
727 if (strMode != "template")
728 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
733 fvNodesEmpty = vNodes.empty();
735 if (Params().MiningRequiresPeers() && (IsNotInSync() || fvNodesEmpty))
737 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
740 //if (IsInitialBlockDownload())
741 // throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
743 static unsigned int nTransactionsUpdatedLast;
747 // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
748 uint256 hashWatchedChain;
749 boost::system_time checktxtime;
750 unsigned int nTransactionsUpdatedLastLP;
754 // Format: <hashBestChain><nTransactionsUpdatedLast>
755 std::string lpstr = lpval.get_str();
757 hashWatchedChain.SetHex(lpstr.substr(0, 64));
758 nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
762 // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
763 hashWatchedChain = chainActive.LastTip()->GetBlockHash();
764 nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
767 // Release the wallet and main lock while waiting
768 LEAVE_CRITICAL_SECTION(cs_main);
770 checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
772 boost::unique_lock<boost::mutex> lock(csBestBlock);
773 while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
775 if (!cvBlockChange.timed_wait(lock, checktxtime))
777 // Timeout: Check transactions for update
778 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
780 checktxtime += boost::posix_time::seconds(10);
784 ENTER_CRITICAL_SECTION(cs_main);
787 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
788 // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
792 static CBlockIndex* pindexPrev;
793 static int64_t nStart;
794 static CBlockTemplate* pblocktemplate;
795 if (pindexPrev != chainActive.LastTip() ||
796 (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
798 // Clear pindexPrev so future calls make a new block, despite any failures from here on
801 // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
802 nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
803 CBlockIndex* pindexPrevNew = chainActive.LastTip();
809 delete pblocktemplate;
810 pblocktemplate = NULL;
813 CReserveKey reservekey(pwalletMain);
814 pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
816 pblocktemplate = CreateNewBlockWithKey();
819 /* keep Zcash script-based approach for reference
820 boost::shared_ptr<CReserveScript> coinbaseScript;
821 GetMainSignals().ScriptForMining(coinbaseScript);
823 // Throw an error if no script was provided
824 if (!coinbaseScript->reserveScript.size())
825 throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet or -mineraddress)");
827 pblocktemplate = CreateNewBlock(Params(), coinbaseScript->reserveScript);
831 throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");
833 // Mark script as important because it was used at least for one coinbase output
834 //coinbaseScript->KeepScript();
836 // Need to update only after we know CreateNewBlock succeeded
837 pindexPrev = pindexPrevNew;
839 CBlock* pblock = &pblocktemplate->block; // pointer for convenience
842 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
843 pblock->nNonce = uint256();
845 UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
847 UniValue txCoinbase = NullUniValue;
848 UniValue transactions(UniValue::VARR);
849 map<uint256, int64_t> setTxIndex;
851 BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
852 uint256 txHash = tx.GetHash();
853 setTxIndex[txHash] = i++;
855 if (tx.IsCoinBase() && !coinbasetxn)
858 UniValue entry(UniValue::VOBJ);
860 entry.push_back(Pair("data", EncodeHexTx(tx)));
862 entry.push_back(Pair("hash", txHash.GetHex()));
864 UniValue deps(UniValue::VARR);
865 BOOST_FOREACH (const CTxIn &in, tx.vin)
867 if (setTxIndex.count(in.prevout.hash))
868 deps.push_back(setTxIndex[in.prevout.hash]);
870 entry.push_back(Pair("depends", deps));
872 int index_in_template = i - 1;
873 entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
874 entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
876 if (tx.IsCoinBase()) {
877 // Show founders' reward if it is required
878 //if (pblock->vtx[0].vout.size() > 1) {
879 // Correct this if GetBlockTemplate changes the order
880 // entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
882 CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus());
883 entry.push_back(Pair("coinbasevalue", nReward));
884 entry.push_back(Pair("required", true));
887 transactions.push_back(entry);
890 UniValue aux(UniValue::VOBJ);
891 aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
893 arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
895 static UniValue aMutable(UniValue::VARR);
896 if (aMutable.empty())
898 aMutable.push_back("time");
899 aMutable.push_back("transactions");
900 aMutable.push_back("prevblock");
903 UniValue result(UniValue::VOBJ);
904 result.push_back(Pair("capabilities", aCaps));
905 result.push_back(Pair("version", pblock->nVersion));
906 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
907 result.push_back(Pair("finalsaplingroothash", pblock->hashFinalSaplingRoot.GetHex()));
909 if (CConstVerusSolutionVector::Version(pblock->nSolution) >= CActivationHeight::ACTIVATE_VERUSHASH2_1)
911 result.push_back(Pair("solution", HexBytes(pblock->nSolution.data(), pblock->nSolution.size())));
913 result.push_back(Pair("transactions", transactions));
915 assert(txCoinbase.isObject());
916 result.push_back(Pair("coinbasetxn", txCoinbase));
918 result.push_back(Pair("coinbaseaux", aux));
919 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
921 result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
922 if ( ASSETCHAINS_STAKED != 0 )
924 arith_uint256 POWtarget; int32_t PoSperc;
925 POWtarget = komodo_PoWtarget(&PoSperc,hashTarget,(int32_t)(pindexPrev->GetHeight()+1),ASSETCHAINS_STAKED);
926 result.push_back(Pair("target", POWtarget.GetHex()));
927 result.push_back(Pair("PoSperc", (int64_t)PoSperc));
928 result.push_back(Pair("ac_staked", (int64_t)ASSETCHAINS_STAKED));
929 result.push_back(Pair("origtarget", hashTarget.GetHex()));
930 } else result.push_back(Pair("target", hashTarget.GetHex()));
931 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
932 result.push_back(Pair("mutable", aMutable));
933 result.push_back(Pair("noncerange", "00000000ffffffff"));
934 result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
935 result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
936 result.push_back(Pair("curtime", pblock->GetBlockTime()));
937 result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
938 result.push_back(Pair("height", (int64_t)(pindexPrev->GetHeight()+1)));
940 //fprintf(stderr,"return complete template\n");
944 class submitblock_StateCatcher : public CValidationInterface
949 CValidationState state;
951 submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
954 virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
955 if (block.GetHash() != hash)
962 UniValue submitblock(const UniValue& params, bool fHelp)
964 if (fHelp || params.size() < 1 || params.size() > 2)
966 "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
967 "\nAttempts to submit new block to network.\n"
968 "The 'jsonparametersobject' parameter is currently ignored.\n"
969 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
972 "1. \"hexdata\" (string, required) the hex-encoded block data to submit\n"
973 "2. \"jsonparametersobject\" (string, optional) object of optional parameters\n"
975 " \"workid\" : \"id\" (string, optional) if the server provided a workid, it MUST be included with submissions\n"
978 "\"duplicate\" - node already has valid copy of block\n"
979 "\"duplicate-invalid\" - node already has block, but it is invalid\n"
980 "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
981 "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
982 "\"rejected\" - block was rejected as invalid\n"
983 "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
985 + HelpExampleCli("submitblock", "\"mydata\"")
986 + HelpExampleRpc("submitblock", "\"mydata\"")
992 //LogPrintStr("Hex block submission: " + params[0].get_str());
993 if (!DecodeHexBlk(block, params[0].get_str()))
994 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
998 printf("Exception: %s\n", e.what());
999 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
1002 printf("Received block submission for %s\nhash: %s\n", ASSETCHAINS_SYMBOL, block.GetHash().GetHex().c_str());
1004 uint256 hash = block.GetHash();
1005 bool fBlockPresent = false;
1008 BlockMap::iterator mi = mapBlockIndex.find(hash);
1009 if (mi != mapBlockIndex.end()) {
1010 CBlockIndex *pindex = mi->second;
1013 printf("Already have block %s\n", block.GetHash().GetHex().c_str());
1015 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
1017 if (pindex->nStatus & BLOCK_FAILED_MASK)
1018 return "duplicate-invalid";
1019 // Otherwise, we might only have the header - process the block before returning
1020 fBlockPresent = true;
1025 CValidationState state;
1026 submitblock_StateCatcher sc(block.GetHash());
1028 CCriticalSection cs_blocksubmission;
1030 LOCK(cs_blocksubmission);
1031 RegisterValidationInterface(&sc);
1032 //printf("submitblock, height=%d, coinbase sequence: %d, scriptSig: %s\n", chainActive.LastTip()->GetHeight()+1, block.vtx[0].vin[0].nSequence, block.vtx[0].vin[0].scriptSig.ToString().c_str());
1033 fAccepted = ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1, state, Params(), NULL, &block, true, NULL);
1034 UnregisterValidationInterface(&sc);
1036 if (fBlockPresent || !fAccepted || !sc.found)
1038 //printf("Block was not accepted %s\n", state.GetRejectReason().c_str());
1039 ConnectedChains.lastSubmissionFailed = true;
1043 if (fAccepted && !sc.found)
1044 return "duplicate-inconclusive";
1050 return "inconclusive";
1053 return BIP22ValidationResult(state);
1056 UniValue estimatefee(const UniValue& params, bool fHelp)
1058 if (fHelp || params.size() != 1)
1059 throw runtime_error(
1060 "estimatefee nblocks\n"
1061 "\nEstimates the approximate fee per kilobyte\n"
1062 "needed for a transaction to begin confirmation\n"
1063 "within nblocks blocks.\n"
1065 "1. nblocks (numeric)\n"
1067 "n : (numeric) estimated fee-per-kilobyte\n"
1069 "minimum fee is returned if not enough transactions and\n"
1070 "blocks have been observed to make an estimate.\n"
1072 + HelpExampleCli("estimatefee", "6")
1075 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
1077 int nBlocks = params[0].get_int();
1081 CFeeRate feeRate = mempool.estimateFee(nBlocks);
1082 if (feeRate == CFeeRate(0))
1084 feeRate = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
1086 return ValueFromAmount(feeRate.GetFeePerK());
1089 UniValue estimatepriority(const UniValue& params, bool fHelp)
1091 if (fHelp || params.size() != 1)
1092 throw runtime_error(
1093 "estimatepriority nblocks\n"
1094 "\nEstimates the approximate priority\n"
1095 "a zero-fee transaction needs to begin confirmation\n"
1096 "within nblocks blocks.\n"
1098 "1. nblocks (numeric)\n"
1100 "n : (numeric) estimated priority\n"
1102 "-1.0 is returned if not enough transactions and\n"
1103 "blocks have been observed to make an estimate.\n"
1105 + HelpExampleCli("estimatepriority", "6")
1108 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
1110 int nBlocks = params[0].get_int();
1114 return mempool.estimatePriority(nBlocks);
1117 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
1119 if (fHelp || params.size() > 1)
1120 throw runtime_error(
1121 "getblocksubsidy height\n"
1122 "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n"
1124 "1. height (numeric, optional) The block height. If not provided, defaults to the current height of the chain.\n"
1127 " \"miner\" : x.xxx (numeric) The mining reward amount in KMD.\n"
1130 + HelpExampleCli("getblocksubsidy", "1000")
1131 + HelpExampleRpc("getblockubsidy", "1000")
1135 int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
1137 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
1139 CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
1140 UniValue result(UniValue::VOBJ);
1141 result.push_back(Pair("miner", ValueFromAmount(nReward)));
1142 //result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
1146 static const CRPCCommand commands[] =
1147 { // category name actor (function) okSafeMode
1148 // --------------------- ------------------------ ----------------------- ----------
1149 { "mining", "getlocalsolps", &getlocalsolps, true },
1150 { "mining", "getnetworksolps", &getnetworksolps, true },
1151 { "mining", "getnetworkhashps", &getnetworkhashps, true },
1152 { "mining", "getmininginfo", &getmininginfo, true },
1153 { "mining", "prioritisetransaction", &prioritisetransaction, true },
1154 { "mining", "getblocktemplate", &getblocktemplate, true },
1155 { "mining", "submitblock", &submitblock, true },
1156 { "mining", "getblocksubsidy", &getblocksubsidy, true },
1158 #ifdef ENABLE_MINING
1159 { "generating", "getgenerate", &getgenerate, true },
1160 { "generating", "setgenerate", &setgenerate, true },
1161 { "generating", "generate", &generate, true },
1164 { "util", "estimatefee", &estimatefee, true },
1165 { "util", "estimatepriority", &estimatepriority, true },
1168 void RegisterMiningRPCCommands(CRPCTable &tableRPC)
1170 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1171 tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);