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);;
336 if (params.size() > 1)
338 nGenProcLimit = params[1].get_int();
339 //if (nGenProcLimit == 0)
340 // fGenerate = false;
343 if (fGenerate && !nGenProcLimit)
345 VERUS_MINTBLOCKS = 1;
346 fGenerate = GetBoolArg("-gen", false);
347 nGenProcLimit = KOMODO_MININGTHREADS;
351 VERUS_MINTBLOCKS = 0;
352 KOMODO_MININGTHREADS = 0;
354 else KOMODO_MININGTHREADS = (int32_t)nGenProcLimit;
356 mapArgs["-gen"] = (fGenerate ? "1" : "0");
357 mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS);
360 GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
362 GenerateBitcoins(fGenerate, nGenProcLimit);
370 UniValue getmininginfo(const UniValue& params, bool fHelp)
372 if (fHelp || params.size() != 0)
375 "\nReturns a json object containing mining-related information."
378 " \"blocks\": nnn, (numeric) The current block\n"
379 " \"currentblocksize\": nnn, (numeric) The last block size\n"
380 " \"currentblocktx\": nnn, (numeric) The last block transaction\n"
381 " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
382 " \"errors\": \"...\" (string) Current errors\n"
383 " \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
384 " \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
385 " \"localsolps\": xxx.xxxxx (numeric) The average local solution rate in Sol/s since this node was started\n"
386 " \"networksolps\": x (numeric) The estimated network solution rate in Sol/s\n"
387 " \"pooledtx\": n (numeric) The size of the mem pool\n"
388 " \"testnet\": true|false (boolean) If using testnet or not\n"
389 " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
392 + HelpExampleCli("getmininginfo", "")
393 + HelpExampleRpc("getmininginfo", "")
399 UniValue obj(UniValue::VOBJ);
400 obj.push_back(Pair("blocks", (int)chainActive.Height()));
401 obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
402 obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
403 obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
404 obj.push_back(Pair("errors", GetWarnings("statusbar")));
405 obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
406 if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
408 obj.push_back(Pair("localsolps" , getlocalsolps(params, false)));
409 obj.push_back(Pair("networksolps", getnetworksolps(params, false)));
413 obj.push_back(Pair("localhashps" , GetBoolArg("-gen", false) ? getlocalsolps(params, false) : (double)0.0));
415 obj.push_back(Pair("networkhashps", getnetworksolps(params, false)));
416 obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
417 obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
418 obj.push_back(Pair("chain", Params().NetworkIDString()));
420 obj.push_back(Pair("staking", VERUS_MINTBLOCKS));
421 obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
422 obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS));
428 // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
429 UniValue prioritisetransaction(const UniValue& params, bool fHelp)
431 if (fHelp || params.size() != 3)
433 "prioritisetransaction <txid> <priority delta> <fee delta>\n"
434 "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
436 "1. \"txid\" (string, required) The transaction id.\n"
437 "2. priority delta (numeric, required) The priority to add or subtract.\n"
438 " The transaction selection algorithm considers the tx as it would have a higher priority.\n"
439 " (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
440 "3. fee delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
441 " The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
442 " considers the transaction as it would have paid a higher (or lower) fee.\n"
444 "true (boolean) Returns true\n"
446 + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
447 + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
452 uint256 hash = ParseHashStr(params[0].get_str(), "txid");
453 CAmount nAmount = params[2].get_int64();
455 mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
460 // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
461 static UniValue BIP22ValidationResult(const CValidationState& state)
466 std::string strRejectReason = state.GetRejectReason();
468 throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
469 if (state.IsInvalid())
471 if (strRejectReason.empty())
473 return strRejectReason;
475 // Should be impossible
479 UniValue getblocktemplate(const UniValue& params, bool fHelp)
481 if (fHelp || params.size() > 1)
483 "getblocktemplate ( \"jsonrequestobject\" )\n"
484 "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
485 "It returns data needed to construct a block to work on.\n"
486 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
489 "1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n"
491 " \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n"
492 " \"capabilities\":[ (array, optional) A list of strings\n"
493 " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
501 " \"version\" : n, (numeric) The block version\n"
502 " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n"
503 " \"finalsaplingroothash\" : \"xxxx\", (string) The hash of the final sapling root\n"
504 " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
506 " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
507 " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n"
508 " \"depends\" : [ (array) array of numbers \n"
509 " 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"
512 " \"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"
513 " \"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"
514 " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
518 // " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n"
519 // " \"flags\" : \"flags\" (string) \n"
521 // " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
522 " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n"
523 " \"target\" : \"xxxx\", (string) The hash target\n"
524 " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
525 " \"mutable\" : [ (array of string) list of ways the block template may be changed \n"
526 " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
529 " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n"
530 " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n"
531 " \"sizelimit\" : n, (numeric) limit of block size\n"
532 " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
533 " \"bits\" : \"xxx\", (string) compressed target of next block\n"
534 " \"height\" : n (numeric) The height of the next block\n"
538 + HelpExampleCli("getblocktemplate", "")
539 + HelpExampleRpc("getblocktemplate", "")
544 // Wallet or miner address is required because we support coinbasetxn
545 if (GetArg("-mineraddress", "").empty()) {
548 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
551 throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
555 std::string strMode = "template";
556 UniValue lpval = NullUniValue;
557 // TODO: Re-enable coinbasevalue once a specification has been written
558 bool coinbasetxn = true;
559 if (params.size() > 0)
561 const UniValue& oparam = params[0].get_obj();
562 const UniValue& modeval = find_value(oparam, "mode");
564 strMode = modeval.get_str();
565 else if (modeval.isNull())
570 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
571 lpval = find_value(oparam, "longpollid");
573 if (strMode == "proposal")
575 const UniValue& dataval = find_value(oparam, "data");
576 if (!dataval.isStr())
577 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
580 if (!DecodeHexBlk(block, dataval.get_str()))
581 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
583 uint256 hash = block.GetHash();
584 BlockMap::iterator mi = mapBlockIndex.find(hash);
585 if (mi != mapBlockIndex.end()) {
586 CBlockIndex *pindex = mi->second;
589 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
591 if (pindex->nStatus & BLOCK_FAILED_MASK)
592 return "duplicate-invalid";
594 return "duplicate-inconclusive";
597 CBlockIndex* const pindexPrev = chainActive.LastTip();
598 // TestBlockValidity only supports blocks built on the current Tip
599 if (block.hashPrevBlock != pindexPrev->GetBlockHash())
600 return "inconclusive-not-best-prevblk";
601 CValidationState state;
602 TestBlockValidity(state, block, pindexPrev, false, true);
603 return BIP22ValidationResult(state);
607 if (strMode != "template")
608 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
613 fvNodesEmpty = vNodes.empty();
615 if (Params().MiningRequiresPeers() && (IsNotInSync() || fvNodesEmpty))
618 int loops = 0, blockDiff = 0, newDiff = 0;
619 const int delay = 15;
623 MilliSleep(1000 + rand() % 4000);
625 fvNodesEmpty = vNodes.empty();
629 if ((newDiff = IsNotInSync()) > 1)
631 if (blockDiff != newDiff)
637 if (++loops <= delay)
644 } while (fvNodesEmpty || IsNotInSync());
646 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
648 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
651 //if (IsInitialBlockDownload())
652 // throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
654 static unsigned int nTransactionsUpdatedLast;
658 // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
659 uint256 hashWatchedChain;
660 boost::system_time checktxtime;
661 unsigned int nTransactionsUpdatedLastLP;
665 // Format: <hashBestChain><nTransactionsUpdatedLast>
666 std::string lpstr = lpval.get_str();
668 hashWatchedChain.SetHex(lpstr.substr(0, 64));
669 nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
673 // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
674 hashWatchedChain = chainActive.LastTip()->GetBlockHash();
675 nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
678 // Release the wallet and main lock while waiting
679 LEAVE_CRITICAL_SECTION(cs_main);
681 checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
683 boost::unique_lock<boost::mutex> lock(csBestBlock);
684 while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
686 if (!cvBlockChange.timed_wait(lock, checktxtime))
688 // Timeout: Check transactions for update
689 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
691 checktxtime += boost::posix_time::seconds(10);
695 ENTER_CRITICAL_SECTION(cs_main);
698 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
699 // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
703 static CBlockIndex* pindexPrev;
704 static int64_t nStart;
705 static CBlockTemplate* pblocktemplate;
706 if (pindexPrev != chainActive.LastTip() ||
707 (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
709 // Clear pindexPrev so future calls make a new block, despite any failures from here on
712 // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
713 nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
714 CBlockIndex* pindexPrevNew = chainActive.LastTip();
720 delete pblocktemplate;
721 pblocktemplate = NULL;
724 CReserveKey reservekey(pwalletMain);
725 pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
727 pblocktemplate = CreateNewBlockWithKey();
730 throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");
732 // Need to update only after we know CreateNewBlockWithKey succeeded
733 pindexPrev = pindexPrevNew;
735 CBlock* pblock = &pblocktemplate->block; // pointer for convenience
738 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
739 pblock->nNonce = uint256();
741 UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
743 UniValue txCoinbase = NullUniValue;
744 UniValue transactions(UniValue::VARR);
745 map<uint256, int64_t> setTxIndex;
747 BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
748 uint256 txHash = tx.GetHash();
749 setTxIndex[txHash] = i++;
751 if (tx.IsCoinBase() && !coinbasetxn)
754 UniValue entry(UniValue::VOBJ);
756 entry.push_back(Pair("data", EncodeHexTx(tx)));
758 entry.push_back(Pair("hash", txHash.GetHex()));
760 UniValue deps(UniValue::VARR);
761 BOOST_FOREACH (const CTxIn &in, tx.vin)
763 if (setTxIndex.count(in.prevout.hash))
764 deps.push_back(setTxIndex[in.prevout.hash]);
766 entry.push_back(Pair("depends", deps));
768 int index_in_template = i - 1;
769 entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
770 entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
772 if (tx.IsCoinBase()) {
773 // Show founders' reward if it is required
774 //if (pblock->vtx[0].vout.size() > 1) {
775 // Correct this if GetBlockTemplate changes the order
776 // entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
778 CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus());
779 entry.push_back(Pair("coinbasevalue", nReward));
780 entry.push_back(Pair("required", true));
783 transactions.push_back(entry);
786 UniValue aux(UniValue::VOBJ);
787 aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
789 arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
791 static UniValue aMutable(UniValue::VARR);
792 if (aMutable.empty())
794 aMutable.push_back("time");
795 aMutable.push_back("transactions");
796 aMutable.push_back("prevblock");
799 UniValue result(UniValue::VOBJ);
800 result.push_back(Pair("capabilities", aCaps));
801 result.push_back(Pair("version", pblock->nVersion));
802 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
803 result.push_back(Pair("finalsaplingroothash", pblock->hashFinalSaplingRoot.GetHex()));
804 result.push_back(Pair("transactions", transactions));
806 assert(txCoinbase.isObject());
807 result.push_back(Pair("coinbasetxn", txCoinbase));
809 result.push_back(Pair("coinbaseaux", aux));
810 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
812 result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
813 if ( ASSETCHAINS_STAKED != 0 )
815 arith_uint256 POWtarget; int32_t PoSperc;
816 POWtarget = komodo_PoWtarget(&PoSperc,hashTarget,(int32_t)(pindexPrev->GetHeight()+1),ASSETCHAINS_STAKED);
817 result.push_back(Pair("target", POWtarget.GetHex()));
818 result.push_back(Pair("PoSperc", (int64_t)PoSperc));
819 result.push_back(Pair("ac_staked", (int64_t)ASSETCHAINS_STAKED));
820 result.push_back(Pair("origtarget", hashTarget.GetHex()));
821 } else result.push_back(Pair("target", hashTarget.GetHex()));
822 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
823 result.push_back(Pair("mutable", aMutable));
824 result.push_back(Pair("noncerange", "00000000ffffffff"));
825 result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
826 result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
827 result.push_back(Pair("curtime", pblock->GetBlockTime()));
828 result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
829 result.push_back(Pair("height", (int64_t)(pindexPrev->GetHeight()+1)));
831 //fprintf(stderr,"return complete template\n");
835 class submitblock_StateCatcher : public CValidationInterface
840 CValidationState state;
842 submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
845 virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
846 if (block.GetHash() != hash)
853 UniValue submitblock(const UniValue& params, bool fHelp)
855 if (fHelp || params.size() < 1 || params.size() > 2)
857 "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
858 "\nAttempts to submit new block to network.\n"
859 "The 'jsonparametersobject' parameter is currently ignored.\n"
860 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
863 "1. \"hexdata\" (string, required) the hex-encoded block data to submit\n"
864 "2. \"jsonparametersobject\" (string, optional) object of optional parameters\n"
866 " \"workid\" : \"id\" (string, optional) if the server provided a workid, it MUST be included with submissions\n"
869 "\"duplicate\" - node already has valid copy of block\n"
870 "\"duplicate-invalid\" - node already has block, but it is invalid\n"
871 "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
872 "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
873 "\"rejected\" - block was rejected as invalid\n"
874 "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
876 + HelpExampleCli("submitblock", "\"mydata\"")
877 + HelpExampleRpc("submitblock", "\"mydata\"")
881 if (!DecodeHexBlk(block, params[0].get_str()))
882 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
884 uint256 hash = block.GetHash();
885 bool fBlockPresent = false;
888 BlockMap::iterator mi = mapBlockIndex.find(hash);
889 if (mi != mapBlockIndex.end()) {
890 CBlockIndex *pindex = mi->second;
893 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
895 if (pindex->nStatus & BLOCK_FAILED_MASK)
896 return "duplicate-invalid";
897 // Otherwise, we might only have the header - process the block before returning
898 fBlockPresent = true;
903 CValidationState state;
904 submitblock_StateCatcher sc(block.GetHash());
905 RegisterValidationInterface(&sc);
906 bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, &block, true, NULL);
907 UnregisterValidationInterface(&sc);
910 if (fAccepted && !sc.found)
911 return "duplicate-inconclusive";
917 return "inconclusive";
920 return BIP22ValidationResult(state);
923 UniValue estimatefee(const UniValue& params, bool fHelp)
925 if (fHelp || params.size() != 1)
927 "estimatefee nblocks\n"
928 "\nEstimates the approximate fee per kilobyte\n"
929 "needed for a transaction to begin confirmation\n"
930 "within nblocks blocks.\n"
932 "1. nblocks (numeric)\n"
934 "n : (numeric) estimated fee-per-kilobyte\n"
936 "-1.0 is returned if not enough transactions and\n"
937 "blocks have been observed to make an estimate.\n"
939 + HelpExampleCli("estimatefee", "6")
942 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
944 int nBlocks = params[0].get_int();
948 CFeeRate feeRate = mempool.estimateFee(nBlocks);
949 if (feeRate == CFeeRate(0))
952 return ValueFromAmount(feeRate.GetFeePerK());
955 UniValue estimatepriority(const UniValue& params, bool fHelp)
957 if (fHelp || params.size() != 1)
959 "estimatepriority nblocks\n"
960 "\nEstimates the approximate priority\n"
961 "a zero-fee transaction needs to begin confirmation\n"
962 "within nblocks blocks.\n"
964 "1. nblocks (numeric)\n"
966 "n : (numeric) estimated priority\n"
968 "-1.0 is returned if not enough transactions and\n"
969 "blocks have been observed to make an estimate.\n"
971 + HelpExampleCli("estimatepriority", "6")
974 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
976 int nBlocks = params[0].get_int();
980 return mempool.estimatePriority(nBlocks);
983 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
985 if (fHelp || params.size() > 1)
987 "getblocksubsidy height\n"
988 "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n"
990 "1. height (numeric, optional) The block height. If not provided, defaults to the current height of the chain.\n"
993 " \"miner\" : x.xxx (numeric) The mining reward amount in KMD.\n"
996 + HelpExampleCli("getblocksubsidy", "1000")
997 + HelpExampleRpc("getblockubsidy", "1000")
1001 int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
1003 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
1005 CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
1006 UniValue result(UniValue::VOBJ);
1007 result.push_back(Pair("miner", ValueFromAmount(nReward)));
1008 //result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
1012 static const CRPCCommand commands[] =
1013 { // category name actor (function) okSafeMode
1014 // --------------------- ------------------------ ----------------------- ----------
1015 { "mining", "getlocalsolps", &getlocalsolps, true },
1016 { "mining", "getnetworksolps", &getnetworksolps, true },
1017 { "mining", "getnetworkhashps", &getnetworkhashps, true },
1018 { "mining", "getmininginfo", &getmininginfo, true },
1019 { "mining", "prioritisetransaction", &prioritisetransaction, true },
1020 { "mining", "getblocktemplate", &getblocktemplate, true },
1021 { "mining", "submitblock", &submitblock, true },
1022 { "mining", "getblocksubsidy", &getblocksubsidy, true },
1024 #ifdef ENABLE_MINING
1025 { "generating", "getgenerate", &getgenerate, true },
1026 { "generating", "setgenerate", &setgenerate, true },
1027 { "generating", "generate", &generate, true },
1030 { "util", "estimatefee", &estimatefee, true },
1031 { "util", "estimatepriority", &estimatepriority, true },
1034 void RegisterMiningRPCCommands(CRPCTable &tableRPC)
1036 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1037 tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);