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;
587 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
589 if (pindex->nStatus & BLOCK_FAILED_MASK)
590 return "duplicate-invalid";
591 return "duplicate-inconclusive";
594 CBlockIndex* const pindexPrev = chainActive.LastTip();
595 // TestBlockValidity only supports blocks built on the current Tip
596 if (block.hashPrevBlock != pindexPrev->GetBlockHash())
597 return "inconclusive-not-best-prevblk";
598 CValidationState state;
599 TestBlockValidity(state, block, pindexPrev, false, true);
600 return BIP22ValidationResult(state);
604 if (strMode != "template")
605 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
610 fvNodesEmpty = vNodes.empty();
612 if (Params().MiningRequiresPeers() && (IsNotInSync() || fvNodesEmpty))
614 int loops = 0, blockDiff = 0, newDiff = 0;
615 const int delay = 15;
619 MilliSleep(1000 + rand() % 4000);
621 fvNodesEmpty = vNodes.empty();
625 if ((newDiff = IsNotInSync()) > 1)
627 if (blockDiff != newDiff)
633 if (++loops <= delay)
640 } while (fvNodesEmpty || IsNotInSync());
642 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
645 //if (IsInitialBlockDownload())
646 // throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
648 static unsigned int nTransactionsUpdatedLast;
652 // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
653 uint256 hashWatchedChain;
654 boost::system_time checktxtime;
655 unsigned int nTransactionsUpdatedLastLP;
659 // Format: <hashBestChain><nTransactionsUpdatedLast>
660 std::string lpstr = lpval.get_str();
662 hashWatchedChain.SetHex(lpstr.substr(0, 64));
663 nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
667 // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
668 hashWatchedChain = chainActive.LastTip()->GetBlockHash();
669 nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
672 // Release the wallet and main lock while waiting
673 LEAVE_CRITICAL_SECTION(cs_main);
675 checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
677 boost::unique_lock<boost::mutex> lock(csBestBlock);
678 while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
680 if (!cvBlockChange.timed_wait(lock, checktxtime))
682 // Timeout: Check transactions for update
683 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
685 checktxtime += boost::posix_time::seconds(10);
689 ENTER_CRITICAL_SECTION(cs_main);
692 throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
693 // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
697 static CBlockIndex* pindexPrev;
698 static int64_t nStart;
699 static CBlockTemplate* pblocktemplate;
700 if (pindexPrev != chainActive.LastTip() ||
701 (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
703 // Clear pindexPrev so future calls make a new block, despite any failures from here on
706 // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
707 nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
708 CBlockIndex* pindexPrevNew = chainActive.LastTip();
714 delete pblocktemplate;
715 pblocktemplate = NULL;
718 CReserveKey reservekey(pwalletMain);
719 pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
721 pblocktemplate = CreateNewBlockWithKey();
724 throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");
726 // Need to update only after we know CreateNewBlockWithKey succeeded
727 pindexPrev = pindexPrevNew;
729 CBlock* pblock = &pblocktemplate->block; // pointer for convenience
732 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
733 pblock->nNonce = uint256();
735 UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
737 UniValue txCoinbase = NullUniValue;
738 UniValue transactions(UniValue::VARR);
739 map<uint256, int64_t> setTxIndex;
741 BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
742 uint256 txHash = tx.GetHash();
743 setTxIndex[txHash] = i++;
745 if (tx.IsCoinBase() && !coinbasetxn)
748 UniValue entry(UniValue::VOBJ);
750 entry.push_back(Pair("data", EncodeHexTx(tx)));
752 entry.push_back(Pair("hash", txHash.GetHex()));
754 UniValue deps(UniValue::VARR);
755 BOOST_FOREACH (const CTxIn &in, tx.vin)
757 if (setTxIndex.count(in.prevout.hash))
758 deps.push_back(setTxIndex[in.prevout.hash]);
760 entry.push_back(Pair("depends", deps));
762 int index_in_template = i - 1;
763 entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
764 entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
766 if (tx.IsCoinBase()) {
767 // Show founders' reward if it is required
768 //if (pblock->vtx[0].vout.size() > 1) {
769 // Correct this if GetBlockTemplate changes the order
770 // entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
772 CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus());
773 entry.push_back(Pair("coinbasevalue", nReward));
774 entry.push_back(Pair("required", true));
777 transactions.push_back(entry);
780 UniValue aux(UniValue::VOBJ);
781 aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
783 arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
785 static UniValue aMutable(UniValue::VARR);
786 if (aMutable.empty())
788 aMutable.push_back("time");
789 aMutable.push_back("transactions");
790 aMutable.push_back("prevblock");
793 UniValue result(UniValue::VOBJ);
794 result.push_back(Pair("capabilities", aCaps));
795 result.push_back(Pair("version", pblock->nVersion));
796 result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
797 result.push_back(Pair("finalsaplingroothash", pblock->hashFinalSaplingRoot.GetHex()));
798 result.push_back(Pair("transactions", transactions));
800 assert(txCoinbase.isObject());
801 result.push_back(Pair("coinbasetxn", txCoinbase));
803 result.push_back(Pair("coinbaseaux", aux));
804 result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
806 result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
807 if ( ASSETCHAINS_STAKED != 0 )
809 arith_uint256 POWtarget; int32_t PoSperc;
810 POWtarget = komodo_PoWtarget(&PoSperc,hashTarget,(int32_t)(pindexPrev->GetHeight()+1),ASSETCHAINS_STAKED);
811 result.push_back(Pair("target", POWtarget.GetHex()));
812 result.push_back(Pair("PoSperc", (int64_t)PoSperc));
813 result.push_back(Pair("ac_staked", (int64_t)ASSETCHAINS_STAKED));
814 result.push_back(Pair("origtarget", hashTarget.GetHex()));
815 } else result.push_back(Pair("target", hashTarget.GetHex()));
816 result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
817 result.push_back(Pair("mutable", aMutable));
818 result.push_back(Pair("noncerange", "00000000ffffffff"));
819 result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
820 result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
821 result.push_back(Pair("curtime", pblock->GetBlockTime()));
822 result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
823 result.push_back(Pair("height", (int64_t)(pindexPrev->GetHeight()+1)));
825 //fprintf(stderr,"return complete template\n");
829 class submitblock_StateCatcher : public CValidationInterface
834 CValidationState state;
836 submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
839 virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
840 if (block.GetHash() != hash)
847 UniValue submitblock(const UniValue& params, bool fHelp)
849 if (fHelp || params.size() < 1 || params.size() > 2)
851 "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
852 "\nAttempts to submit new block to network.\n"
853 "The 'jsonparametersobject' parameter is currently ignored.\n"
854 "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
857 "1. \"hexdata\" (string, required) the hex-encoded block data to submit\n"
858 "2. \"jsonparametersobject\" (string, optional) object of optional parameters\n"
860 " \"workid\" : \"id\" (string, optional) if the server provided a workid, it MUST be included with submissions\n"
863 "\"duplicate\" - node already has valid copy of block\n"
864 "\"duplicate-invalid\" - node already has block, but it is invalid\n"
865 "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
866 "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
867 "\"rejected\" - block was rejected as invalid\n"
868 "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
870 + HelpExampleCli("submitblock", "\"mydata\"")
871 + HelpExampleRpc("submitblock", "\"mydata\"")
875 if (!DecodeHexBlk(block, params[0].get_str()))
876 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
878 uint256 hash = block.GetHash();
879 bool fBlockPresent = false;
882 BlockMap::iterator mi = mapBlockIndex.find(hash);
883 if (mi != mapBlockIndex.end()) {
884 CBlockIndex *pindex = mi->second;
885 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
887 if (pindex->nStatus & BLOCK_FAILED_MASK)
888 return "duplicate-invalid";
889 // Otherwise, we might only have the header - process the block before returning
890 fBlockPresent = true;
894 CValidationState state;
895 submitblock_StateCatcher sc(block.GetHash());
896 RegisterValidationInterface(&sc);
897 bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, &block, true, NULL);
898 UnregisterValidationInterface(&sc);
901 if (fAccepted && !sc.found)
902 return "duplicate-inconclusive";
908 return "inconclusive";
911 return BIP22ValidationResult(state);
914 UniValue estimatefee(const UniValue& params, bool fHelp)
916 if (fHelp || params.size() != 1)
918 "estimatefee nblocks\n"
919 "\nEstimates the approximate fee per kilobyte\n"
920 "needed for a transaction to begin confirmation\n"
921 "within nblocks blocks.\n"
923 "1. nblocks (numeric)\n"
925 "n : (numeric) estimated fee-per-kilobyte\n"
927 "-1.0 is returned if not enough transactions and\n"
928 "blocks have been observed to make an estimate.\n"
930 + HelpExampleCli("estimatefee", "6")
933 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
935 int nBlocks = params[0].get_int();
939 CFeeRate feeRate = mempool.estimateFee(nBlocks);
940 if (feeRate == CFeeRate(0))
943 return ValueFromAmount(feeRate.GetFeePerK());
946 UniValue estimatepriority(const UniValue& params, bool fHelp)
948 if (fHelp || params.size() != 1)
950 "estimatepriority nblocks\n"
951 "\nEstimates the approximate priority\n"
952 "a zero-fee transaction needs to begin confirmation\n"
953 "within nblocks blocks.\n"
955 "1. nblocks (numeric)\n"
957 "n : (numeric) estimated priority\n"
959 "-1.0 is returned if not enough transactions and\n"
960 "blocks have been observed to make an estimate.\n"
962 + HelpExampleCli("estimatepriority", "6")
965 RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
967 int nBlocks = params[0].get_int();
971 return mempool.estimatePriority(nBlocks);
974 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
976 if (fHelp || params.size() > 1)
978 "getblocksubsidy height\n"
979 "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n"
981 "1. height (numeric, optional) The block height. If not provided, defaults to the current height of the chain.\n"
984 " \"miner\" : x.xxx (numeric) The mining reward amount in KMD.\n"
987 + HelpExampleCli("getblocksubsidy", "1000")
988 + HelpExampleRpc("getblockubsidy", "1000")
992 int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
994 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
996 CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
997 UniValue result(UniValue::VOBJ);
998 result.push_back(Pair("miner", ValueFromAmount(nReward)));
999 //result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
1003 static const CRPCCommand commands[] =
1004 { // category name actor (function) okSafeMode
1005 // --------------------- ------------------------ ----------------------- ----------
1006 { "mining", "getlocalsolps", &getlocalsolps, true },
1007 { "mining", "getnetworksolps", &getnetworksolps, true },
1008 { "mining", "getnetworkhashps", &getnetworkhashps, true },
1009 { "mining", "getmininginfo", &getmininginfo, true },
1010 { "mining", "prioritisetransaction", &prioritisetransaction, true },
1011 { "mining", "getblocktemplate", &getblocktemplate, true },
1012 { "mining", "submitblock", &submitblock, true },
1013 { "mining", "getblocksubsidy", &getblocksubsidy, true },
1015 #ifdef ENABLE_MINING
1016 { "generating", "getgenerate", &getgenerate, true },
1017 { "generating", "setgenerate", &setgenerate, true },
1018 { "generating", "generate", &generate, true },
1021 { "util", "estimatefee", &estimatefee, true },
1022 { "util", "estimatepriority", &estimatepriority, true },
1025 void RegisterMiningRPCCommands(CRPCTable &tableRPC)
1027 for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1028 tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);