]> Git Repo - VerusCoin.git/blob - src/rpc/mining.cpp
Timeout adjustment
[VerusCoin.git] / src / rpc / mining.cpp
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.
5
6 #include "amount.h"
7 #include "chainparams.h"
8 #include "consensus/consensus.h"
9 #include "consensus/validation.h"
10 #include "core_io.h"
11 #ifdef ENABLE_MINING
12 #include "crypto/equihash.h"
13 #endif
14 #include "init.h"
15 #include "main.h"
16 #include "metrics.h"
17 #include "miner.h"
18 #include "net.h"
19 #include "pow.h"
20 #include "rpc/server.h"
21 #include "txmempool.h"
22 #include "util.h"
23 #include "validationinterface.h"
24 #ifdef ENABLE_WALLET
25 #include "wallet/wallet.h"
26 #endif
27
28 #include <stdint.h>
29
30 #include <boost/assign/list_of.hpp>
31
32 #include <univalue.h>
33
34 using namespace std;
35
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);
41
42 /**
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.
46  */
47 int64_t GetNetworkHashPS(int lookup, int height) {
48     CBlockIndex *pb = chainActive.LastTip();
49
50     if (height >= 0 && height < chainActive.Height())
51         pb = chainActive[height];
52
53     if (pb == NULL || !pb->GetHeight())
54         return 0;
55
56     // If lookup is nonpositive, then use difficulty averaging window.
57     if (lookup <= 0)
58         lookup = Params().GetConsensus().nPowAveragingWindow;
59
60     // If lookup is larger than chain, then set it to chain length.
61     if (lookup > pb->GetHeight())
62         lookup = pb->GetHeight();
63
64     CBlockIndex *pb0 = pb;
65     int64_t minTime = pb0->GetBlockTime();
66     int64_t maxTime = minTime;
67     for (int i = 0; i < lookup; i++) {
68         pb0 = pb0->pprev;
69         int64_t time = pb0->GetBlockTime();
70         minTime = std::min(time, minTime);
71         maxTime = std::max(time, maxTime);
72     }
73
74     // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
75     if (minTime == maxTime)
76         return 0;
77
78     arith_uint256 workDiff = pb->chainPower.chainWork - pb0->chainPower.chainWork;
79     int64_t timeDiff = maxTime - minTime;
80
81     return (int64_t)(workDiff.getdouble() / timeDiff);
82 }
83
84 UniValue getlocalsolps(const UniValue& params, bool fHelp)
85 {
86     if (fHelp)
87         throw runtime_error(
88             "getlocalsolps\n"
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"
91             "\nResult:\n"
92             "xxx.xxxxx     (numeric) Solutions per second average\n"
93             "\nExamples:\n"
94             + HelpExampleCli("getlocalsolps", "")
95             + HelpExampleRpc("getlocalsolps", "")
96        );
97
98     LOCK(cs_main);
99     return GetLocalSolPS();
100 }
101
102 UniValue getnetworksolps(const UniValue& params, bool fHelp)
103 {
104     if (fHelp || params.size() > 2)
105         throw runtime_error(
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"
110             "\nArguments:\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"
113             "\nResult:\n"
114             "x             (numeric) Solutions per second estimated\n"
115             "\nExamples:\n"
116             + HelpExampleCli("getnetworksolps", "")
117             + HelpExampleRpc("getnetworksolps", "")
118        );
119
120     LOCK(cs_main);
121     return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
122 }
123
124 UniValue getnetworkhashps(const UniValue& params, bool fHelp)
125 {
126     if (fHelp || params.size() > 2)
127         throw runtime_error(
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"
133             "\nArguments:\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"
136             "\nResult:\n"
137             "x             (numeric) Solutions per second estimated\n"
138             "\nExamples:\n"
139             + HelpExampleCli("getnetworkhashps", "")
140             + HelpExampleRpc("getnetworkhashps", "")
141        );
142
143     LOCK(cs_main);
144     return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
145 }
146
147 #ifdef ENABLE_MINING
148 extern bool VERUS_MINTBLOCKS;
149 UniValue getgenerate(const UniValue& params, bool fHelp)
150 {
151     if (fHelp || params.size() != 0)
152         throw runtime_error(
153             "getgenerate\n"
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"
157             "\nResult\n"
158             "{\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"
162             "}\n"
163             "\nExamples:\n"
164             + HelpExampleCli("getgenerate", "")
165             + HelpExampleRpc("getgenerate", "")
166         );
167
168     LOCK(cs_main);
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));
173     return obj;
174 }
175
176 extern uint8_t NOTARY_PUBKEY33[33];
177
178 //Value generate(const Array& params, bool fHelp)
179 UniValue generate(const UniValue& params, bool fHelp)
180 {
181     if (fHelp || params.size() < 1 || params.size() > 1)
182         throw runtime_error(
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"
186             "\nArguments:\n"
187             "1. numblocks    (numeric) How many blocks are generated immediately.\n"
188             "\nResult\n"
189             "[ blockhashes ]     (array) hashes of blocks generated\n"
190             "\nExamples:\n"
191             "\nGenerate 11 blocks\n"
192             + HelpExampleCli("generate", "11")
193         );
194
195     if (GetArg("-mineraddress", "").empty()) {
196 #ifdef ENABLE_WALLET
197         if (!pwalletMain) {
198             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
199         }
200 #else
201         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
202 #endif
203     }
204     if (!Params().MineBlocksOnDemand())
205         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
206
207     int nHeightStart = 0;
208     int nHeightEnd = 0;
209     int nHeight = 0;
210     int nGenerate = params[0].get_int();
211 #ifdef ENABLE_WALLET
212     CReserveKey reservekey(pwalletMain);
213 #endif
214
215     {   // Don't keep cs_main locked
216         LOCK(cs_main);
217         nHeightStart = chainActive.Height();
218         nHeight = nHeightStart;
219         nHeightEnd = nHeightStart+nGenerate;
220     }
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)
227     {
228         // Validation may fail if block generation is too fast
229         if (GetTime() == lastTime) MilliSleep(1001);
230         lastTime = GetTime();
231
232 #ifdef ENABLE_WALLET
233         std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey,nHeight,KOMODO_MAXGPUCOUNT));
234 #else
235         std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
236 #endif
237         if (!pblocktemplate.get())
238             throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
239         CBlock *pblock = &pblocktemplate->block;
240         {
241             LOCK(cs_main);
242             IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce);
243         }
244
245         // Hash state
246         crypto_generichash_blake2b_state eh_state;
247         EhInitialiseState(n, k, eh_state);
248
249         // I = the block header minus nonce and solution.
250         CEquihashInput I{*pblock};
251         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
252         ss << I;
253
254         // H(I||...
255         crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
256
257         while (true) {
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);
261
262             // H(I||V||...
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());
268
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)
272             {
273                 LOCK(cs_main);
274                 pblock->nSolution = soln;
275                 solutionTargetChecks.increment();
276                 return CheckProofOfWork(*pblock,NOTARY_PUBKEY33,chainActive.Height(),Params().GetConsensus());
277             };
278             bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock);
279             ehSolverRuns.increment();
280             if (found) {
281                 goto endloop;
282             }
283         }
284 endloop:
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");
288         ++nHeight;
289         blockHashes.push_back(pblock->GetHash().GetHex());
290     }
291     return blockHashes;
292 }
293
294
295 UniValue setgenerate(const UniValue& params, bool fHelp)
296 {
297     if (fHelp || params.size() < 1 || params.size() > 2)
298         throw runtime_error(
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"
303             "\nArguments:\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"
306             "\nExamples:\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") +
315             "\nUsing json rpc\n"
316             + HelpExampleRpc("setgenerate", "true, 1")
317         );
318
319     if (GetArg("-mineraddress", "").empty()) {
320 #ifdef ENABLE_WALLET
321         if (!pwalletMain) {
322             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
323         }
324 #else
325         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
326 #endif
327     }
328     if (Params().MineBlocksOnDemand())
329         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
330
331     bool fGenerate = true;
332     if (params.size() > 0)
333         fGenerate = params[0].get_bool();
334
335     int nGenProcLimit = GetArg("-genproclimit", -1);;
336     if (params.size() > 1)
337     {
338         nGenProcLimit = params[1].get_int();
339         //if (nGenProcLimit == 0)
340         //    fGenerate = false;
341     }
342
343     if (fGenerate && !nGenProcLimit)
344     {
345         VERUS_MINTBLOCKS = 1;
346         fGenerate = GetBoolArg("-gen", false);
347         nGenProcLimit = KOMODO_MININGTHREADS;
348     }
349     else if (!fGenerate)
350     {
351         VERUS_MINTBLOCKS = 0;
352         KOMODO_MININGTHREADS = 0;
353     }
354     else KOMODO_MININGTHREADS = (int32_t)nGenProcLimit;
355
356     mapArgs["-gen"] = (fGenerate ? "1" : "0");
357     mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS);
358
359 #ifdef ENABLE_WALLET
360     GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
361 #else
362     GenerateBitcoins(fGenerate, nGenProcLimit);
363 #endif
364
365     return NullUniValue;
366 }
367 #endif
368
369
370 UniValue getmininginfo(const UniValue& params, bool fHelp)
371 {
372     if (fHelp || params.size() != 0)
373         throw runtime_error(
374             "getmininginfo\n"
375             "\nReturns a json object containing mining-related information."
376             "\nResult:\n"
377             "{\n"
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"
390             "}\n"
391             "\nExamples:\n"
392             + HelpExampleCli("getmininginfo", "")
393             + HelpExampleRpc("getmininginfo", "")
394         );
395
396
397     LOCK(cs_main);
398
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)
407     {
408         obj.push_back(Pair("localsolps"  , getlocalsolps(params, false)));
409         obj.push_back(Pair("networksolps", getnetworksolps(params, false)));
410     }
411     else
412     {
413         obj.push_back(Pair("localhashps"  , GetBoolArg("-gen", false) ? getlocalsolps(params, false) : (double)0.0));
414     }
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()));
419 #ifdef ENABLE_MINING
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));
423 #endif
424     return obj;
425 }
426
427
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)
430 {
431     if (fHelp || params.size() != 3)
432         throw runtime_error(
433             "prioritisetransaction <txid> <priority delta> <fee delta>\n"
434             "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
435             "\nArguments:\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"
443             "\nResult\n"
444             "true              (boolean) Returns true\n"
445             "\nExamples:\n"
446             + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
447             + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
448         );
449
450     LOCK(cs_main);
451
452     uint256 hash = ParseHashStr(params[0].get_str(), "txid");
453     CAmount nAmount = params[2].get_int64();
454
455     mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
456     return true;
457 }
458
459
460 // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
461 static UniValue BIP22ValidationResult(const CValidationState& state)
462 {
463     if (state.IsValid())
464         return NullUniValue;
465
466     std::string strRejectReason = state.GetRejectReason();
467     if (state.IsError())
468         throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
469     if (state.IsInvalid())
470     {
471         if (strRejectReason.empty())
472             return "rejected";
473         return strRejectReason;
474     }
475     // Should be impossible
476     return "valid?";
477 }
478
479 UniValue getblocktemplate(const UniValue& params, bool fHelp)
480 {
481     if (fHelp || params.size() > 1)
482         throw runtime_error(
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"
487
488             "\nArguments:\n"
489             "1. \"jsonrequestobject\"       (string, optional) A json object in the following spec\n"
490             "     {\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"
494             "           ,...\n"
495             "         ]\n"
496             "     }\n"
497             "\n"
498
499             "\nResult:\n"
500             "{\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"
505             "      {\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"
510             "             ,...\n"
511             "         ],\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"
515             "      }\n"
516             "      ,...\n"
517             "  ],\n"
518 //            "  \"coinbaseaux\" : {                  (json object) data that should be included in the coinbase's scriptSig content\n"
519 //            "      \"flags\" : \"flags\"            (string) \n"
520 //            "  },\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"
527             "     ,...\n"
528             "  ],\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"
535             "}\n"
536
537             "\nExamples:\n"
538             + HelpExampleCli("getblocktemplate", "")
539             + HelpExampleRpc("getblocktemplate", "")
540          );
541
542     LOCK(cs_main);
543
544     // Wallet or miner address is required because we support coinbasetxn
545     if (GetArg("-mineraddress", "").empty()) {
546 #ifdef ENABLE_WALLET
547         if (!pwalletMain) {
548             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
549         }
550 #else
551         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
552 #endif
553     }
554
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)
560     {
561         const UniValue& oparam = params[0].get_obj();
562         const UniValue& modeval = find_value(oparam, "mode");
563         if (modeval.isStr())
564             strMode = modeval.get_str();
565         else if (modeval.isNull())
566         {
567             /* Do nothing */
568         }
569         else
570             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
571         lpval = find_value(oparam, "longpollid");
572
573         if (strMode == "proposal")
574         {
575             const UniValue& dataval = find_value(oparam, "data");
576             if (!dataval.isStr())
577                 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
578
579             CBlock block;
580             if (!DecodeHexBlk(block, dataval.get_str()))
581                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
582
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))
588                     return "duplicate";
589                 if (pindex->nStatus & BLOCK_FAILED_MASK)
590                     return "duplicate-invalid";
591                 return "duplicate-inconclusive";
592             }
593
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);
601         }
602     }
603
604     if (strMode != "template")
605         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
606
607     bool fvNodesEmpty;
608     {
609         LOCK(cs_vNodes);
610         fvNodesEmpty = vNodes.empty();
611     }
612     if (Params().MiningRequiresPeers() && (IsNotInSync() || fvNodesEmpty))
613     {
614         int loops = 0, blockDiff = 0, newDiff = 0;
615         const int delay = 15;
616         do {
617             if (fvNodesEmpty)
618             {
619                 MilliSleep(1000 + rand() % 4000);
620                 LOCK(cs_vNodes);
621                 fvNodesEmpty = vNodes.empty();
622                 loops = 0;
623                 blockDiff = 0;
624             }
625             if ((newDiff = IsNotInSync()) > 1)
626             {
627                 if (blockDiff != newDiff)
628                 {
629                     blockDiff = newDiff;
630                 }
631                 else
632                 {
633                     if (++loops <= delay)
634                     {
635                         MilliSleep(1000);
636                     }
637                     else break;
638                 }
639             }
640         } while (fvNodesEmpty || IsNotInSync());
641         if (loops > delay)
642             throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
643     }
644
645     //if (IsInitialBlockDownload())
646      //   throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
647
648     static unsigned int nTransactionsUpdatedLast;
649
650     if (!lpval.isNull())
651     {
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;
656
657         if (lpval.isStr())
658         {
659             // Format: <hashBestChain><nTransactionsUpdatedLast>
660             std::string lpstr = lpval.get_str();
661
662             hashWatchedChain.SetHex(lpstr.substr(0, 64));
663             nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
664         }
665         else
666         {
667             // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
668             hashWatchedChain = chainActive.LastTip()->GetBlockHash();
669             nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
670         }
671
672         // Release the wallet and main lock while waiting
673         LEAVE_CRITICAL_SECTION(cs_main);
674         {
675             checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
676
677             boost::unique_lock<boost::mutex> lock(csBestBlock);
678             while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
679             {
680                 if (!cvBlockChange.timed_wait(lock, checktxtime))
681                 {
682                     // Timeout: Check transactions for update
683                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
684                         break;
685                     checktxtime += boost::posix_time::seconds(10);
686                 }
687             }
688         }
689         ENTER_CRITICAL_SECTION(cs_main);
690
691         if (!IsRPCRunning())
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?
694     }
695
696     // Update block
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))
702     {
703         // Clear pindexPrev so future calls make a new block, despite any failures from here on
704         pindexPrev = NULL;
705
706         // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
707         nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
708         CBlockIndex* pindexPrevNew = chainActive.LastTip();
709         nStart = GetTime();
710
711         // Create new block
712         if(pblocktemplate)
713         {
714             delete pblocktemplate;
715             pblocktemplate = NULL;
716         }
717 #ifdef ENABLE_WALLET
718         CReserveKey reservekey(pwalletMain);
719         pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
720 #else
721         pblocktemplate = CreateNewBlockWithKey();
722 #endif
723         if (!pblocktemplate)
724             throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");
725
726         // Need to update only after we know CreateNewBlockWithKey succeeded
727         pindexPrev = pindexPrevNew;
728     }
729     CBlock* pblock = &pblocktemplate->block; // pointer for convenience
730
731     // Update nTime
732     UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
733     pblock->nNonce = uint256();
734
735     UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
736
737     UniValue txCoinbase = NullUniValue;
738     UniValue transactions(UniValue::VARR);
739     map<uint256, int64_t> setTxIndex;
740     int i = 0;
741     BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
742         uint256 txHash = tx.GetHash();
743         setTxIndex[txHash] = i++;
744
745         if (tx.IsCoinBase() && !coinbasetxn)
746             continue;
747
748         UniValue entry(UniValue::VOBJ);
749
750         entry.push_back(Pair("data", EncodeHexTx(tx)));
751
752         entry.push_back(Pair("hash", txHash.GetHex()));
753
754         UniValue deps(UniValue::VARR);
755         BOOST_FOREACH (const CTxIn &in, tx.vin)
756         {
757             if (setTxIndex.count(in.prevout.hash))
758                 deps.push_back(setTxIndex[in.prevout.hash]);
759         }
760         entry.push_back(Pair("depends", deps));
761
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]));
765
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));
771             //}
772             CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus());
773             entry.push_back(Pair("coinbasevalue", nReward));
774             entry.push_back(Pair("required", true));
775             txCoinbase = entry;
776         } else
777             transactions.push_back(entry);
778     }
779
780     UniValue aux(UniValue::VOBJ);
781     aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
782
783     arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
784
785     static UniValue aMutable(UniValue::VARR);
786     if (aMutable.empty())
787     {
788         aMutable.push_back("time");
789         aMutable.push_back("transactions");
790         aMutable.push_back("prevblock");
791     }
792
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));
799     if (coinbasetxn) {
800         assert(txCoinbase.isObject());
801         result.push_back(Pair("coinbasetxn", txCoinbase));
802     } else {
803         result.push_back(Pair("coinbaseaux", aux));
804         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
805     }
806     result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
807     if ( ASSETCHAINS_STAKED != 0 )
808     {
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)));
824
825     //fprintf(stderr,"return complete template\n");
826     return result;
827 }
828
829 class submitblock_StateCatcher : public CValidationInterface
830 {
831 public:
832     uint256 hash;
833     bool found;
834     CValidationState state;
835
836     submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
837
838 protected:
839     virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
840         if (block.GetHash() != hash)
841             return;
842         found = true;
843         state = stateIn;
844     };
845 };
846
847 UniValue submitblock(const UniValue& params, bool fHelp)
848 {
849     if (fHelp || params.size() < 1 || params.size() > 2)
850         throw runtime_error(
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"
855
856             "\nArguments\n"
857             "1. \"hexdata\"    (string, required) the hex-encoded block data to submit\n"
858             "2. \"jsonparametersobject\"     (string, optional) object of optional parameters\n"
859             "    {\n"
860             "      \"workid\" : \"id\"    (string, optional) if the server provided a workid, it MUST be included with submissions\n"
861             "    }\n"
862             "\nResult:\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"
869             "\nExamples:\n"
870             + HelpExampleCli("submitblock", "\"mydata\"")
871             + HelpExampleRpc("submitblock", "\"mydata\"")
872         );
873
874     CBlock block;
875     if (!DecodeHexBlk(block, params[0].get_str()))
876         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
877
878     uint256 hash = block.GetHash();
879     bool fBlockPresent = false;
880     {
881         LOCK(cs_main);
882         BlockMap::iterator mi = mapBlockIndex.find(hash);
883         if (mi != mapBlockIndex.end()) {
884             CBlockIndex *pindex = mi->second;
885             if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
886                 return "duplicate";
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;
891         }
892     }
893
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);
899     if (fBlockPresent)
900     {
901         if (fAccepted && !sc.found)
902             return "duplicate-inconclusive";
903         return "duplicate";
904     }
905     if (fAccepted)
906     {
907         if (!sc.found)
908             return "inconclusive";
909         state = sc.state;
910     }
911     return BIP22ValidationResult(state);
912 }
913
914 UniValue estimatefee(const UniValue& params, bool fHelp)
915 {
916     if (fHelp || params.size() != 1)
917         throw runtime_error(
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"
922             "\nArguments:\n"
923             "1. nblocks     (numeric)\n"
924             "\nResult:\n"
925             "n :    (numeric) estimated fee-per-kilobyte\n"
926             "\n"
927             "-1.0 is returned if not enough transactions and\n"
928             "blocks have been observed to make an estimate.\n"
929             "\nExample:\n"
930             + HelpExampleCli("estimatefee", "6")
931             );
932
933     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
934
935     int nBlocks = params[0].get_int();
936     if (nBlocks < 1)
937         nBlocks = 1;
938
939     CFeeRate feeRate = mempool.estimateFee(nBlocks);
940     if (feeRate == CFeeRate(0))
941         return -1.0;
942
943     return ValueFromAmount(feeRate.GetFeePerK());
944 }
945
946 UniValue estimatepriority(const UniValue& params, bool fHelp)
947 {
948     if (fHelp || params.size() != 1)
949         throw runtime_error(
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"
954             "\nArguments:\n"
955             "1. nblocks     (numeric)\n"
956             "\nResult:\n"
957             "n :    (numeric) estimated priority\n"
958             "\n"
959             "-1.0 is returned if not enough transactions and\n"
960             "blocks have been observed to make an estimate.\n"
961             "\nExample:\n"
962             + HelpExampleCli("estimatepriority", "6")
963             );
964
965     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
966
967     int nBlocks = params[0].get_int();
968     if (nBlocks < 1)
969         nBlocks = 1;
970
971     return mempool.estimatePriority(nBlocks);
972 }
973
974 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
975 {
976     if (fHelp || params.size() > 1)
977         throw runtime_error(
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"
980             "\nArguments:\n"
981             "1. height         (numeric, optional) The block height.  If not provided, defaults to the current height of the chain.\n"
982             "\nResult:\n"
983             "{\n"
984             "  \"miner\" : x.xxx           (numeric) The mining reward amount in KMD.\n"
985             "}\n"
986             "\nExamples:\n"
987             + HelpExampleCli("getblocksubsidy", "1000")
988             + HelpExampleRpc("getblockubsidy", "1000")
989         );
990
991     LOCK(cs_main);
992     int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
993     if (nHeight < 0)
994         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
995
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)));
1000     return result;
1001 }
1002
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  },
1014
1015 #ifdef ENABLE_MINING
1016     { "generating",         "getgenerate",            &getgenerate,            true  },
1017     { "generating",         "setgenerate",            &setgenerate,            true  },
1018     { "generating",         "generate",               &generate,               true  },
1019 #endif
1020
1021     { "util",               "estimatefee",            &estimatefee,            true  },
1022     { "util",               "estimatepriority",       &estimatepriority,       true  },
1023 };
1024
1025 void RegisterMiningRPCCommands(CRPCTable &tableRPC)
1026 {
1027     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1028         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
1029 }
This page took 0.083016 seconds and 4 git commands to generate.