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 http://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"
30 #include <boost/assign/list_of.hpp>
36 extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_LWMAPOS;
37 extern uint64_t ASSETCHAINS_STAKED;
38 extern int32_t KOMODO_MININGTHREADS;
39 extern bool VERUS_MINTBLOCKS;
40 arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
43 * Return average network hashes per second based on the last 'lookup' blocks,
44 * or over the difficulty averaging window if 'lookup' is nonpositive.
45 * If 'height' is nonnegative, compute the estimate at the time when a given block was found.
47 int64_t GetNetworkHashPS(int lookup, int height) {
48 CBlockIndex *pb = chainActive.LastTip();
50 if (height >= 0 && height < chainActive.Height())
51 pb = chainActive[height];
53 if (pb == NULL || !pb->GetHeight())
56 // If lookup is nonpositive, then use difficulty averaging window.
58 lookup = Params().GetConsensus().nPowAveragingWindow;
60 // If lookup is larger than chain, then set it to chain length.
61 if (lookup > pb->GetHeight())
62 lookup = pb->GetHeight();
64 CBlockIndex *pb0 = pb;
65 int64_t minTime = pb0->GetBlockTime();
66 int64_t maxTime = minTime;
67 for (int i = 0; i < lookup; i++) {
69 int64_t time = pb0->GetBlockTime();
70 minTime = std::min(time, minTime);
71 maxTime = std::max(time, maxTime);
74 // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
75 if (minTime == maxTime)
78 arith_uint256 workDiff = pb->chainPower.chainWork - pb0->chainPower.chainWork;
79 int64_t timeDiff = maxTime - minTime;
81 return (int64_t)(workDiff.getdouble() / timeDiff);
84 UniValue getlocalsolps(const UniValue& params, bool fHelp)
89 "\nReturns the average local solutions per second since this node was started.\n"
90 "This is the same information shown on the metrics screen (if enabled).\n"
92 "xxx.xxxxx (numeric) Solutions per second average\n"
94 + HelpExampleCli("getlocalsolps", "")
95 + HelpExampleRpc("getlocalsolps", "")
99 return GetLocalSolPS();
102 UniValue getnetworksolps(const UniValue& params, bool fHelp)
104 if (fHelp || params.size() > 2)
106 "getnetworksolps ( blocks height )\n"
107 "\nReturns the estimated network solutions per second based on the last n blocks.\n"
108 "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n"
109 "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
111 "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n"
112 "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n"
114 "x (numeric) Solutions per second estimated\n"
116 + HelpExampleCli("getnetworksolps", "")
117 + HelpExampleRpc("getnetworksolps", "")
121 return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
124 UniValue getnetworkhashps(const UniValue& params, bool fHelp)
126 if (fHelp || params.size() > 2)
128 "getnetworkhashps ( blocks height )\n"
129 "\nDEPRECATED - left for backwards-compatibility. Use getnetworksolps instead.\n"
130 "\nReturns the estimated network solutions per second based on the last n blocks.\n"
131 "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n"
132 "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
134 "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n"
135 "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n"
137 "x (numeric) Solutions per second estimated\n"
139 + HelpExampleCli("getnetworkhashps", "")
140 + HelpExampleRpc("getnetworkhashps", "")
144 return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
148 extern bool VERUS_MINTBLOCKS;
149 UniValue getgenerate(const UniValue& params, bool fHelp)
151 if (fHelp || params.size() != 0)
154 "\nReturn if the server is set to mine and/or mint coins or not. The default is false.\n"
155 "It is set with the command line argument -gen (or komodo.conf setting gen) and -mint\n"
156 "It can also be set with the setgenerate call.\n"
159 " \"staking\": true|false (boolean) If staking is on or off (see setgenerate)\n"
160 " \"generate\": true|false (boolean) If mining is on or off (see setgenerate)\n"
161 " \"numthreads\": n (numeric) The processor limit for mining. (see setgenerate)\n"
164 + HelpExampleCli("getgenerate", "")
165 + HelpExampleRpc("getgenerate", "")
169 UniValue obj(UniValue::VOBJ);
170 obj.push_back(Pair("staking", VERUS_MINTBLOCKS));
171 obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
172 obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS));
176 extern uint8_t NOTARY_PUBKEY33[33];
178 //Value generate(const Array& params, bool fHelp)
179 UniValue generate(const UniValue& params, bool fHelp)
181 if (fHelp || params.size() < 1 || params.size() > 1)
183 "generate numblocks\n"
184 "\nMine blocks immediately (before the RPC call returns)\n"
185 "\nNote: this function can only be used on the regtest network\n"
187 "1. numblocks (numeric) How many blocks are generated immediately.\n"
189 "[ blockhashes ] (array) hashes of blocks generated\n"
191 "\nGenerate 11 blocks\n"
192 + HelpExampleCli("generate", "11")
195 if (GetArg("-mineraddress", "").empty()) {
198 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
201 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
204 if (!Params().MineBlocksOnDemand())
205 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
207 int nHeightStart = 0;
210 int nGenerate = params[0].get_int();
212 CReserveKey reservekey(pwalletMain);
215 { // Don't keep cs_main locked
217 nHeightStart = chainActive.Height();
218 nHeight = nHeightStart;
219 nHeightEnd = nHeightStart+nGenerate;
221 unsigned int nExtraNonce = 0;
222 UniValue blockHashes(UniValue::VARR);
223 unsigned int n = Params().EquihashN();
224 unsigned int k = Params().EquihashK();
225 uint64_t lastTime = 0;
226 while (nHeight < nHeightEnd)
228 // Validation may fail if block generation is too fast
229 if (GetTime() == lastTime) MilliSleep(1001);
230 lastTime = GetTime();
233 std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey,nHeight,KOMODO_MAXGPUCOUNT));
235 std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
237 if (!pblocktemplate.get())
238 throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
239 CBlock *pblock = &pblocktemplate->block;
242 IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce);
246 crypto_generichash_blake2b_state eh_state;
247 EhInitialiseState(n, k, eh_state);
249 // I = the block header minus nonce and solution.
250 CEquihashInput I{*pblock};
251 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
255 crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
258 // Yes, there is a chance every nonce could fail to satisfy the -regtest
259 // target -- 1 in 2^(2^256). That ain't gonna happen
260 pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
263 crypto_generichash_blake2b_state curr_state;
264 curr_state = eh_state;
265 crypto_generichash_blake2b_update(&curr_state,
266 pblock->nNonce.begin(),
267 pblock->nNonce.size());
269 // (x_1, x_2, ...) = A(I, V, n, k)
270 std::function<bool(std::vector<unsigned char>)> validBlock =
271 [&pblock](std::vector<unsigned char> soln)
274 pblock->nSolution = soln;
275 solutionTargetChecks.increment();
276 return CheckProofOfWork(*pblock,NOTARY_PUBKEY33,chainActive.Height(),Params().GetConsensus());
278 bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock);
279 ehSolverRuns.increment();
285 CValidationState state;
286 if (!ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, pblock, true, NULL))
287 throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
289 blockHashes.push_back(pblock->GetHash().GetHex());
295 UniValue setgenerate(const UniValue& params, bool fHelp)
297 if (fHelp || params.size() < 1 || params.size() > 2)
299 "setgenerate generate ( genproclimit )\n"
300 "\nSet 'generate' true to turn either mining/generation or minting/staking on and false to turn both off.\n"
301 "Mining is limited to 'genproclimit' processors, -1 is unlimited, setgenerate true with 0 genproclimit turns on staking\n"
302 "See the getgenerate call for the current setting.\n"
304 "1. generate (boolean, required) Set to true to turn on generation, off to turn off.\n"
305 "2. genproclimit (numeric, optional) Set processor limit when generation is on. Can be -1 for unlimited, 0 to turn on staking.\n"
307 "\nSet the generation on with a limit of one processor\n"
308 + HelpExampleCli("setgenerate", "true 1") +
309 "\nTurn minting/staking on\n"
310 + HelpExampleCli("setgenerate", "true 0") +
311 "\nCheck the setting\n"
312 + HelpExampleCli("getgenerate", "") +
313 "\nTurn off generation and minting\n"
314 + HelpExampleCli("setgenerate", "false") +
316 + HelpExampleRpc("setgenerate", "true, 1")
319 if (GetArg("-mineraddress", "").empty()) {
322 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
325 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
328 if (Params().MineBlocksOnDemand())
329 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
331 bool fGenerate = true;
332 if (params.size() > 0)
333 fGenerate = params[0].get_bool();
335 int nGenProcLimit = GetArg("-genproclimit", -1);
337 if (params.size() > 1)
339 gpl = params[1].get_int();
347 VERUS_MINTBLOCKS = 1;
348 KOMODO_MININGTHREADS = -1;
351 if (fGenerate && !gpl && params.size() > 1)
353 VERUS_MINTBLOCKS = 1;
357 VERUS_MINTBLOCKS = 0;
358 KOMODO_MININGTHREADS = 0;
362 KOMODO_MININGTHREADS = (int32_t)nGenProcLimit;
365 mapArgs["-gen"] = (fGenerate ? "1" : "0");
366 mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS);
369 GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
371 GenerateBitcoins(fGenerate, nGenProcLimit);
379 UniValue getmininginfo(const UniValue& params, bool fHelp)
381 if (fHelp || params.size() != 0)
384 "\nReturns a json object containing mining-related information."
387 " \"blocks\": nnn, (numeric) The current block\n"
388 " \"currentblocksize\": nnn, (numeric) The last block size\n"
389 " \"currentblocktx\": nnn, (numeric) The last block transaction\n"
390 " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
391 " \"errors\": \"...\" (string) Current errors\n"
392 " \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
393 " \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
394 " \"localsolps\": xxx.xxxxx (numeric) The average local solution rate in Sol/s since this node was started\n"
395 " \"networksolps\": x (numeric) The estimated network solution rate in Sol/s\n"
396 " \"pooledtx\": n (numeric) The size of the mem pool\n"
397 " \"testnet\": true|false (boolean) If using testnet or not\n"
398 " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
401 + HelpExampleCli("getmininginfo", "")
402 + HelpExampleRpc("getmininginfo", "")
408 UniValue obj(UniValue::VOBJ);
409 obj.push_back(Pair("blocks", (int)chainActive.Height()));
410 obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
411 obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
412 obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
413 obj.push_back(Pair("errors", GetWarnings("statusbar")));
414 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
415 if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
417 obj.push_back(Pair("localsolps" , getlocalsolps(params, false)));
418 obj.push_back(Pair("networksolps", getnetworksolps(params, false)));
422 obj.push_back(Pair("localhashps" , GetBoolArg("-gen", false) ? getlocalsolps(params, false) : (double)0.0));
424 obj.push_back(Pair("networkhashps", getnetworksolps(params, false)));
425 obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
426 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
427 obj.push_back(Pair("chain", Params().NetworkIDString()));
429 obj.push_back(Pair("staking", VERUS_MINTBLOCKS));
430 obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
431 obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS));
437 // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
438 UniValue prioritisetransaction(const UniValue& params, bool fHelp)
440 if (fHelp || params.size() != 3)
442 "prioritisetransaction <txid> <priority delta> <fee delta>\n"
443 "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
445 "1. \"txid\" (string, required) The transaction id.\n"
446 "2. priority delta (numeric, required) The priority to add or subtract.\n"
447 " The transaction selection algorithm considers the tx as it would have a higher priority.\n"
448 " (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
449 "3. fee delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
450 " The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
451 " considers the transaction as it would have paid a higher (or lower) fee.\n"
453 "true (boolean) Returns true\n"
455 + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
456 + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
461 uint256 hash = ParseHashStr(params[0].get_str(), "txid");
462 CAmount nAmount = params[2].get_int64();
464 mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
469 // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
470 static UniValue BIP22ValidationResult(const CValidationState& state)
475 std::string strRejectReason = state.GetRejectReason();
477 throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
478 if (state.IsInvalid())
480 if (strRejectReason.empty())
482 return strRejectReason;
484 // Should be impossible
488 UniValue getblocktemplate(const UniValue& params, bool fHelp)
490 if (fHelp || params.size() > 1)
492 "getblocktemplate ( \"jsonrequestobject\" )\n"
493 "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
494 "It returns data needed to construct a block to work on.\n"
495 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
498 "1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n"
500 " \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n"
501 " \"capabilities\":[ (array, optional) A list of strings\n"
502 " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
510 " \"version\" : n, (numeric) The block version\n"
511 " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n"
512 " \"finalsaplingroothash\" : \"xxxx\", (string) The hash of the final sapling root\n"
513 " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
515 " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
516 " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n"
517 " \"depends\" : [ (array) array of numbers \n"
518 " 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"
521 " \"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"
522 " \"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"
523 " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
527 // " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n"
528 // " \"flags\" : \"flags\" (string) \n"
530 // " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
531 " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n"
532 " \"target\" : \"xxxx\", (string) The hash target\n"
533 " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
534 " \"mutable\" : [ (array of string) list of ways the block template may be changed \n"
535 " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
538 " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n"
539 " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n"
540 " \"sizelimit\" : n, (numeric) limit of block size\n"
541 " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
542 " \"bits\" : \"xxx\", (string) compressed target of next block\n"
543 " \"height\" : n (numeric) The height of the next block\n"
547 + HelpExampleCli("getblocktemplate", "")
548 + HelpExampleRpc("getblocktemplate", "")
553 // Wallet or miner address is required because we support coinbasetxn
554 if (GetArg("-mineraddress", "").empty()) {
557 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
560 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
564 std::string strMode = "template";
565 UniValue lpval = NullUniValue;
566 // TODO: Re-enable coinbasevalue once a specification has been written
567 bool coinbasetxn = true;
568 if (params.size() > 0)
570 const UniValue& oparam = params[0].get_obj();
571 const UniValue& modeval = find_value(oparam, "mode");
573 strMode = modeval.get_str();
574 else if (modeval.isNull())
579 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
580 lpval = find_value(oparam, "longpollid");
582 if (strMode == "proposal")
584 const UniValue& dataval = find_value(oparam, "data");
585 if (!dataval.isStr())
586 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
589 if (!DecodeHexBlk(block, dataval.get_str()))
590 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
592 uint256 hash = block.GetHash();
593 BlockMap::iterator mi = mapBlockIndex.find(hash);
594 if (mi != mapBlockIndex.end()) {
595 CBlockIndex *pindex = mi->second;
598 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
600 if (pindex->nStatus & BLOCK_FAILED_MASK)
601 return "duplicate-invalid";
603 return "duplicate-inconclusive";
606 CBlockIndex* const pindexPrev = chainActive.LastTip();
607 // TestBlockValidity only supports blocks built on the current Tip
608 if (block.hashPrevBlock != pindexPrev->GetBlockHash())
609 return "inconclusive-not-best-prevblk";
610 CValidationState state;
611 TestBlockValidity(state, block, pindexPrev, false, true);
612 return BIP22ValidationResult(state);
616 if (strMode != "template")
617 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
622 fvNodesEmpty = vNodes.empty();
624 if (Params().MiningRequiresPeers() && (IsNotInSync() || fvNodesEmpty))
626 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
629 //if (IsInitialBlockDownload())
630 // throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
632 static unsigned int nTransactionsUpdatedLast;
636 // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
637 uint256 hashWatchedChain;
638 boost::system_time checktxtime;
639 unsigned int nTransactionsUpdatedLastLP;
643 // Format: <hashBestChain><nTransactionsUpdatedLast>
644 std::string lpstr = lpval.get_str();
646 hashWatchedChain.SetHex(lpstr.substr(0, 64));
647 nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
651 // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
652 hashWatchedChain = chainActive.LastTip()->GetBlockHash();
653 nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
656 // Release the wallet and main lock while waiting
657 LEAVE_CRITICAL_SECTION(cs_main);
659 checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
661 boost::unique_lock<boost::mutex> lock(csBestBlock);
662 while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
664 if (!cvBlockChange.timed_wait(lock, checktxtime))
666 // Timeout: Check transactions for update
667 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
669 checktxtime += boost::posix_time::seconds(10);
673 ENTER_CRITICAL_SECTION(cs_main);
676 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
677 // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
681 static CBlockIndex* pindexPrev;
682 static int64_t nStart;
683 static CBlockTemplate* pblocktemplate;
684 if (pindexPrev != chainActive.LastTip() ||
685 (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
687 // Clear pindexPrev so future calls make a new block, despite any failures from here on
690 // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
691 nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
692 CBlockIndex* pindexPrevNew = chainActive.LastTip();
698 delete pblocktemplate;
699 pblocktemplate = NULL;
702 CReserveKey reservekey(pwalletMain);
703 pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
705 pblocktemplate = CreateNewBlockWithKey();
708 throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");
710 // Need to update only after we know CreateNewBlockWithKey succeeded
711 pindexPrev = pindexPrevNew;
713 CBlock* pblock = &pblocktemplate->block; // pointer for convenience
716 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
717 pblock->nNonce = uint256();
719 UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
721 UniValue txCoinbase = NullUniValue;
722 UniValue transactions(UniValue::VARR);
723 map<uint256, int64_t> setTxIndex;
725 BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
726 uint256 txHash = tx.GetHash();
727 setTxIndex[txHash] = i++;
729 if (tx.IsCoinBase() && !coinbasetxn)
732 UniValue entry(UniValue::VOBJ);
734 entry.push_back(Pair("data", EncodeHexTx(tx)));
736 entry.push_back(Pair("hash", txHash.GetHex()));
738 UniValue deps(UniValue::VARR);
739 BOOST_FOREACH (const CTxIn &in, tx.vin)
741 if (setTxIndex.count(in.prevout.hash))
742 deps.push_back(setTxIndex[in.prevout.hash]);
744 entry.push_back(Pair("depends", deps));
746 int index_in_template = i - 1;
747 entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
748 entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
750 if (tx.IsCoinBase()) {
751 // Show founders' reward if it is required
752 //if (pblock->vtx[0].vout.size() > 1) {
753 // Correct this if GetBlockTemplate changes the order
754 // entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
756 CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus());
757 entry.push_back(Pair("coinbasevalue", nReward));
758 entry.push_back(Pair("required", true));
761 transactions.push_back(entry);
764 UniValue aux(UniValue::VOBJ);
765 aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
767 arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
769 static UniValue aMutable(UniValue::VARR);
770 if (aMutable.empty())
772 aMutable.push_back("time");
773 aMutable.push_back("transactions");
774 aMutable.push_back("prevblock");
777 UniValue result(UniValue::VOBJ);
778 result.push_back(Pair("capabilities", aCaps));
779 result.push_back(Pair("version", pblock->nVersion));
780 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
781 result.push_back(Pair("finalsaplingroothash", pblock->hashFinalSaplingRoot.GetHex()));
782 result.push_back(Pair("transactions", transactions));
784 assert(txCoinbase.isObject());
785 result.push_back(Pair("coinbasetxn", txCoinbase));
787 result.push_back(Pair("coinbaseaux", aux));
788 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
790 result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
791 if ( ASSETCHAINS_STAKED != 0 )
793 arith_uint256 POWtarget; int32_t PoSperc;
794 POWtarget = komodo_PoWtarget(&PoSperc,hashTarget,(int32_t)(pindexPrev->GetHeight()+1),ASSETCHAINS_STAKED);
795 result.push_back(Pair("target", POWtarget.GetHex()));
796 result.push_back(Pair("PoSperc", (int64_t)PoSperc));
797 result.push_back(Pair("ac_staked", (int64_t)ASSETCHAINS_STAKED));
798 result.push_back(Pair("origtarget", hashTarget.GetHex()));
799 } else result.push_back(Pair("target", hashTarget.GetHex()));
800 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
801 result.push_back(Pair("mutable", aMutable));
802 result.push_back(Pair("noncerange", "00000000ffffffff"));
803 result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
804 result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
805 result.push_back(Pair("curtime", pblock->GetBlockTime()));
806 result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
807 result.push_back(Pair("height", (int64_t)(pindexPrev->GetHeight()+1)));
809 //fprintf(stderr,"return complete template\n");
813 class submitblock_StateCatcher : public CValidationInterface
818 CValidationState state;
820 submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
823 virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
824 if (block.GetHash() != hash)
831 UniValue submitblock(const UniValue& params, bool fHelp)
833 if (fHelp || params.size() < 1 || params.size() > 2)
835 "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
836 "\nAttempts to submit new block to network.\n"
837 "The 'jsonparametersobject' parameter is currently ignored.\n"
838 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
841 "1. \"hexdata\" (string, required) the hex-encoded block data to submit\n"
842 "2. \"jsonparametersobject\" (string, optional) object of optional parameters\n"
844 " \"workid\" : \"id\" (string, optional) if the server provided a workid, it MUST be included with submissions\n"
847 "\"duplicate\" - node already has valid copy of block\n"
848 "\"duplicate-invalid\" - node already has block, but it is invalid\n"
849 "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
850 "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
851 "\"rejected\" - block was rejected as invalid\n"
852 "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
854 + HelpExampleCli("submitblock", "\"mydata\"")
855 + HelpExampleRpc("submitblock", "\"mydata\"")
859 //LogPrintStr("Hex block submission: " + params[0].get_str());
860 if (!DecodeHexBlk(block, params[0].get_str()))
861 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
863 uint256 hash = block.GetHash();
864 bool fBlockPresent = false;
867 BlockMap::iterator mi = mapBlockIndex.find(hash);
868 if (mi != mapBlockIndex.end()) {
869 CBlockIndex *pindex = mi->second;
872 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
874 if (pindex->nStatus & BLOCK_FAILED_MASK)
875 return "duplicate-invalid";
876 // Otherwise, we might only have the header - process the block before returning
877 fBlockPresent = true;
882 CValidationState state;
883 submitblock_StateCatcher sc(block.GetHash());
884 RegisterValidationInterface(&sc);
885 //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());
886 bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, &block, true, NULL);
887 UnregisterValidationInterface(&sc);
890 if (fAccepted && !sc.found)
891 return "duplicate-inconclusive";
897 return "inconclusive";
900 return BIP22ValidationResult(state);
903 UniValue estimatefee(const UniValue& params, bool fHelp)
905 if (fHelp || params.size() != 1)
907 "estimatefee nblocks\n"
908 "\nEstimates the approximate fee per kilobyte\n"
909 "needed for a transaction to begin confirmation\n"
910 "within nblocks blocks.\n"
912 "1. nblocks (numeric)\n"
914 "n : (numeric) estimated fee-per-kilobyte\n"
916 "-1.0 is returned if not enough transactions and\n"
917 "blocks have been observed to make an estimate.\n"
919 + HelpExampleCli("estimatefee", "6")
922 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
924 int nBlocks = params[0].get_int();
928 CFeeRate feeRate = mempool.estimateFee(nBlocks);
929 if (feeRate == CFeeRate(0))
932 return ValueFromAmount(feeRate.GetFeePerK());
935 UniValue estimatepriority(const UniValue& params, bool fHelp)
937 if (fHelp || params.size() != 1)
939 "estimatepriority nblocks\n"
940 "\nEstimates the approximate priority\n"
941 "a zero-fee transaction needs to begin confirmation\n"
942 "within nblocks blocks.\n"
944 "1. nblocks (numeric)\n"
946 "n : (numeric) estimated priority\n"
948 "-1.0 is returned if not enough transactions and\n"
949 "blocks have been observed to make an estimate.\n"
951 + HelpExampleCli("estimatepriority", "6")
954 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
956 int nBlocks = params[0].get_int();
960 return mempool.estimatePriority(nBlocks);
963 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
965 if (fHelp || params.size() > 1)
967 "getblocksubsidy height\n"
968 "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n"
970 "1. height (numeric, optional) The block height. If not provided, defaults to the current height of the chain.\n"
973 " \"miner\" : x.xxx (numeric) The mining reward amount in KMD.\n"
976 + HelpExampleCli("getblocksubsidy", "1000")
977 + HelpExampleRpc("getblockubsidy", "1000")
981 int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
983 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
985 CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
986 UniValue result(UniValue::VOBJ);
987 result.push_back(Pair("miner", ValueFromAmount(nReward)));
988 //result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
992 static const CRPCCommand commands[] =
993 { // category name actor (function) okSafeMode
994 // --------------------- ------------------------ ----------------------- ----------
995 { "mining", "getlocalsolps", &getlocalsolps, true },
996 { "mining", "getnetworksolps", &getnetworksolps, true },
997 { "mining", "getnetworkhashps", &getnetworkhashps, true },
998 { "mining", "getmininginfo", &getmininginfo, true },
999 { "mining", "prioritisetransaction", &prioritisetransaction, true },
1000 { "mining", "getblocktemplate", &getblocktemplate, true },
1001 { "mining", "submitblock", &submitblock, true },
1002 { "mining", "getblocksubsidy", &getblocksubsidy, true },
1004 #ifdef ENABLE_MINING
1005 { "generating", "getgenerate", &getgenerate, true },
1006 { "generating", "setgenerate", &setgenerate, true },
1007 { "generating", "generate", &generate, true },
1010 { "util", "estimatefee", &estimatefee, true },
1011 { "util", "estimatepriority", &estimatepriority, true },
1014 void RegisterMiningRPCCommands(CRPCTable &tableRPC)
1016 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1017 tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);