]> Git Repo - VerusCoin.git/blob - src/rpc/mining.cpp
Merge pull request #210 from miketout/dev
[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     int gpl = -1;
337     if (params.size() > 1)
338     {
339         gpl = params[1].get_int();
340         if (gpl != 0)
341         {
342             nGenProcLimit = gpl;
343         }
344     }
345     else
346     {
347         VERUS_MINTBLOCKS = 1;
348         KOMODO_MININGTHREADS = -1;
349     }
350
351     if (fGenerate && !gpl && params.size() > 1)
352     {
353         VERUS_MINTBLOCKS = 1;
354     }
355     else if (!fGenerate)
356     {
357         VERUS_MINTBLOCKS = 0;
358         KOMODO_MININGTHREADS = 0;
359     }
360     else
361     {
362         KOMODO_MININGTHREADS = (int32_t)nGenProcLimit;
363     }
364
365     mapArgs["-gen"] = (fGenerate ? "1" : "0");
366     mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS);
367
368 #ifdef ENABLE_WALLET
369     GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
370 #else
371     GenerateBitcoins(fGenerate, nGenProcLimit);
372 #endif
373
374     return NullUniValue;
375 }
376 #endif
377
378
379 UniValue getmininginfo(const UniValue& params, bool fHelp)
380 {
381     if (fHelp || params.size() != 0)
382         throw runtime_error(
383             "getmininginfo\n"
384             "\nReturns a json object containing mining-related information."
385             "\nResult:\n"
386             "{\n"
387             "  \"blocks\": nnn,             (numeric) The current block\n"
388             "  \"currentblocksize\": nnn,   (numeric) The last block size\n"
389             "  \"currentblocktx\": nnn,     (numeric) The last block transaction\n"
390             "  \"difficulty\": xxx.xxxxx    (numeric) The current difficulty\n"
391             "  \"errors\": \"...\"          (string) Current errors\n"
392             "  \"generate\": true|false     (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
393             "  \"genproclimit\": n          (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
394             "  \"localsolps\": xxx.xxxxx    (numeric) The average local solution rate in Sol/s since this node was started\n"
395             "  \"networksolps\": x          (numeric) The estimated network solution rate in Sol/s\n"
396             "  \"pooledtx\": n              (numeric) The size of the mem pool\n"
397             "  \"testnet\": true|false      (boolean) If using testnet or not\n"
398             "  \"chain\": \"xxxx\",         (string) current network name as defined in BIP70 (main, test, regtest)\n"
399             "}\n"
400             "\nExamples:\n"
401             + HelpExampleCli("getmininginfo", "")
402             + HelpExampleRpc("getmininginfo", "")
403         );
404
405
406     LOCK(cs_main);
407
408     UniValue obj(UniValue::VOBJ);
409     obj.push_back(Pair("blocks",           (int)chainActive.Height()));
410     obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
411     obj.push_back(Pair("currentblocktx",   (uint64_t)nLastBlockTx));
412     obj.push_back(Pair("difficulty",       (double)GetNetworkDifficulty()));
413     obj.push_back(Pair("errors",           GetWarnings("statusbar")));
414     obj.push_back(Pair("genproclimit",     (int)GetArg("-genproclimit", -1)));
415     if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
416     {
417         obj.push_back(Pair("localsolps"  , getlocalsolps(params, false)));
418         obj.push_back(Pair("networksolps", getnetworksolps(params, false)));
419     }
420     else
421     {
422         obj.push_back(Pair("localhashps"  , GetBoolArg("-gen", false) ? getlocalsolps(params, false) : (double)0.0));
423     }
424     obj.push_back(Pair("networkhashps",    getnetworksolps(params, false)));
425     obj.push_back(Pair("pooledtx",         (uint64_t)mempool.size()));
426     obj.push_back(Pair("testnet",          Params().TestnetToBeDeprecatedFieldRPC()));
427     obj.push_back(Pair("chain",            Params().NetworkIDString()));
428 #ifdef ENABLE_MINING
429     obj.push_back(Pair("staking",          VERUS_MINTBLOCKS));
430     obj.push_back(Pair("generate",         GetBoolArg("-gen", false)));
431     obj.push_back(Pair("numthreads",       (int64_t)KOMODO_MININGTHREADS));
432 #endif
433     return obj;
434 }
435
436
437 // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
438 UniValue prioritisetransaction(const UniValue& params, bool fHelp)
439 {
440     if (fHelp || params.size() != 3)
441         throw runtime_error(
442             "prioritisetransaction <txid> <priority delta> <fee delta>\n"
443             "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
444             "\nArguments:\n"
445             "1. \"txid\"       (string, required) The transaction id.\n"
446             "2. priority delta (numeric, required) The priority to add or subtract.\n"
447             "                  The transaction selection algorithm considers the tx as it would have a higher priority.\n"
448             "                  (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
449             "3. fee delta      (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
450             "                  The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
451             "                  considers the transaction as it would have paid a higher (or lower) fee.\n"
452             "\nResult\n"
453             "true              (boolean) Returns true\n"
454             "\nExamples:\n"
455             + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
456             + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
457         );
458
459     LOCK(cs_main);
460
461     uint256 hash = ParseHashStr(params[0].get_str(), "txid");
462     CAmount nAmount = params[2].get_int64();
463
464     mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
465     return true;
466 }
467
468
469 // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
470 static UniValue BIP22ValidationResult(const CValidationState& state)
471 {
472     if (state.IsValid())
473         return NullUniValue;
474
475     std::string strRejectReason = state.GetRejectReason();
476     if (state.IsError())
477         throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
478     if (state.IsInvalid())
479     {
480         if (strRejectReason.empty())
481             return "rejected";
482         return strRejectReason;
483     }
484     // Should be impossible
485     return "valid?";
486 }
487
488 UniValue getblocktemplate(const UniValue& params, bool fHelp)
489 {
490     if (fHelp || params.size() > 1)
491         throw runtime_error(
492             "getblocktemplate ( \"jsonrequestobject\" )\n"
493             "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
494             "It returns data needed to construct a block to work on.\n"
495             "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
496
497             "\nArguments:\n"
498             "1. \"jsonrequestobject\"       (string, optional) A json object in the following spec\n"
499             "     {\n"
500             "       \"mode\":\"template\"    (string, optional) This must be set to \"template\" or omitted\n"
501             "       \"capabilities\":[       (array, optional) A list of strings\n"
502             "           \"support\"           (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
503             "           ,...\n"
504             "         ]\n"
505             "     }\n"
506             "\n"
507
508             "\nResult:\n"
509             "{\n"
510             "  \"version\" : n,                     (numeric) The block version\n"
511             "  \"previousblockhash\" : \"xxxx\",    (string) The hash of current highest block\n"
512             "  \"finalsaplingroothash\" : \"xxxx\", (string) The hash of the final sapling root\n"
513             "  \"transactions\" : [                 (array) contents of non-coinbase transactions that should be included in the next block\n"
514             "      {\n"
515             "         \"data\" : \"xxxx\",          (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
516             "         \"hash\" : \"xxxx\",          (string) hash/id encoded in little-endian hexadecimal\n"
517             "         \"depends\" : [              (array) array of numbers \n"
518             "             n                        (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
519             "             ,...\n"
520             "         ],\n"
521             "         \"fee\": n,                   (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
522             "         \"sigops\" : n,               (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n"
523             "         \"required\" : true|false     (boolean) if provided and true, this transaction must be in the final block\n"
524             "      }\n"
525             "      ,...\n"
526             "  ],\n"
527 //            "  \"coinbaseaux\" : {                  (json object) data that should be included in the coinbase's scriptSig content\n"
528 //            "      \"flags\" : \"flags\"            (string) \n"
529 //            "  },\n"
530 //            "  \"coinbasevalue\" : n,               (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
531             "  \"coinbasetxn\" : { ... },           (json object) information for coinbase transaction\n"
532             "  \"target\" : \"xxxx\",               (string) The hash target\n"
533             "  \"mintime\" : xxx,                   (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
534             "  \"mutable\" : [                      (array of string) list of ways the block template may be changed \n"
535             "     \"value\"                         (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
536             "     ,...\n"
537             "  ],\n"
538             "  \"noncerange\" : \"00000000ffffffff\",   (string) A range of valid nonces\n"
539             "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
540             "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
541             "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
542             "  \"bits\" : \"xxx\",                 (string) compressed target of next block\n"
543             "  \"height\" : n                      (numeric) The height of the next block\n"
544             "}\n"
545
546             "\nExamples:\n"
547             + HelpExampleCli("getblocktemplate", "")
548             + HelpExampleRpc("getblocktemplate", "")
549          );
550
551     LOCK(cs_main);
552
553     // Wallet or miner address is required because we support coinbasetxn
554     if (GetArg("-mineraddress", "").empty()) {
555 #ifdef ENABLE_WALLET
556         if (!pwalletMain) {
557             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
558         }
559 #else
560         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
561 #endif
562     }
563
564     std::string strMode = "template";
565     UniValue lpval = NullUniValue;
566     // TODO: Re-enable coinbasevalue once a specification has been written
567     bool coinbasetxn = true;
568     if (params.size() > 0)
569     {
570         const UniValue& oparam = params[0].get_obj();
571         const UniValue& modeval = find_value(oparam, "mode");
572         if (modeval.isStr())
573             strMode = modeval.get_str();
574         else if (modeval.isNull())
575         {
576             /* Do nothing */
577         }
578         else
579             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
580         lpval = find_value(oparam, "longpollid");
581
582         if (strMode == "proposal")
583         {
584             const UniValue& dataval = find_value(oparam, "data");
585             if (!dataval.isStr())
586                 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
587
588             CBlock block;
589             if (!DecodeHexBlk(block, dataval.get_str()))
590                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
591
592             uint256 hash = block.GetHash();
593             BlockMap::iterator mi = mapBlockIndex.find(hash);
594             if (mi != mapBlockIndex.end()) {
595                 CBlockIndex *pindex = mi->second;
596                 if (pindex)
597                 {
598                     if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
599                         return "duplicate";
600                     if (pindex->nStatus & BLOCK_FAILED_MASK)
601                         return "duplicate-invalid";
602                 }
603                 return "duplicate-inconclusive";
604             }
605
606             CBlockIndex* const pindexPrev = chainActive.LastTip();
607             // TestBlockValidity only supports blocks built on the current Tip
608             if (block.hashPrevBlock != pindexPrev->GetBlockHash())
609                 return "inconclusive-not-best-prevblk";
610             CValidationState state;
611             TestBlockValidity(state, block, pindexPrev, false, true);
612             return BIP22ValidationResult(state);
613         }
614     }
615
616     if (strMode != "template")
617         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
618
619     bool fvNodesEmpty;
620     {
621         LOCK(cs_vNodes);
622         fvNodesEmpty = vNodes.empty();
623     }
624     if (Params().MiningRequiresPeers() && (IsNotInSync() || fvNodesEmpty))
625     {
626         throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
627     }
628
629     //if (IsInitialBlockDownload())
630      //   throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
631
632     static unsigned int nTransactionsUpdatedLast;
633
634     if (!lpval.isNull())
635     {
636         // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
637         uint256 hashWatchedChain;
638         boost::system_time checktxtime;
639         unsigned int nTransactionsUpdatedLastLP;
640
641         if (lpval.isStr())
642         {
643             // Format: <hashBestChain><nTransactionsUpdatedLast>
644             std::string lpstr = lpval.get_str();
645
646             hashWatchedChain.SetHex(lpstr.substr(0, 64));
647             nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
648         }
649         else
650         {
651             // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
652             hashWatchedChain = chainActive.LastTip()->GetBlockHash();
653             nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
654         }
655
656         // Release the wallet and main lock while waiting
657         LEAVE_CRITICAL_SECTION(cs_main);
658         {
659             checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
660
661             boost::unique_lock<boost::mutex> lock(csBestBlock);
662             while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
663             {
664                 if (!cvBlockChange.timed_wait(lock, checktxtime))
665                 {
666                     // Timeout: Check transactions for update
667                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
668                         break;
669                     checktxtime += boost::posix_time::seconds(10);
670                 }
671             }
672         }
673         ENTER_CRITICAL_SECTION(cs_main);
674
675         if (!IsRPCRunning())
676             throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
677         // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
678     }
679
680     // Update block
681     static CBlockIndex* pindexPrev;
682     static int64_t nStart;
683     static CBlockTemplate* pblocktemplate;
684     if (pindexPrev != chainActive.LastTip() ||
685         (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
686     {
687         // Clear pindexPrev so future calls make a new block, despite any failures from here on
688         pindexPrev = NULL;
689
690         // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
691         nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
692         CBlockIndex* pindexPrevNew = chainActive.LastTip();
693         nStart = GetTime();
694
695         // Create new block
696         if(pblocktemplate)
697         {
698             delete pblocktemplate;
699             pblocktemplate = NULL;
700         }
701 #ifdef ENABLE_WALLET
702         CReserveKey reservekey(pwalletMain);
703         pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
704 #else
705         pblocktemplate = CreateNewBlockWithKey();
706 #endif
707         if (!pblocktemplate)
708             throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");
709
710         // Need to update only after we know CreateNewBlockWithKey succeeded
711         pindexPrev = pindexPrevNew;
712     }
713     CBlock* pblock = &pblocktemplate->block; // pointer for convenience
714
715     // Update nTime
716     UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
717     pblock->nNonce = uint256();
718
719     UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
720
721     UniValue txCoinbase = NullUniValue;
722     UniValue transactions(UniValue::VARR);
723     map<uint256, int64_t> setTxIndex;
724     int i = 0;
725     BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
726         uint256 txHash = tx.GetHash();
727         setTxIndex[txHash] = i++;
728
729         if (tx.IsCoinBase() && !coinbasetxn)
730             continue;
731
732         UniValue entry(UniValue::VOBJ);
733
734         entry.push_back(Pair("data", EncodeHexTx(tx)));
735
736         entry.push_back(Pair("hash", txHash.GetHex()));
737
738         UniValue deps(UniValue::VARR);
739         BOOST_FOREACH (const CTxIn &in, tx.vin)
740         {
741             if (setTxIndex.count(in.prevout.hash))
742                 deps.push_back(setTxIndex[in.prevout.hash]);
743         }
744         entry.push_back(Pair("depends", deps));
745
746         int index_in_template = i - 1;
747         entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
748         entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
749
750         if (tx.IsCoinBase()) {
751             // Show founders' reward if it is required
752             //if (pblock->vtx[0].vout.size() > 1) {
753                 // Correct this if GetBlockTemplate changes the order
754             //    entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
755             //}
756             CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus());
757             entry.push_back(Pair("coinbasevalue", nReward));
758             entry.push_back(Pair("required", true));
759             txCoinbase = entry;
760         } else
761             transactions.push_back(entry);
762     }
763
764     UniValue aux(UniValue::VOBJ);
765     aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
766
767     arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
768
769     static UniValue aMutable(UniValue::VARR);
770     if (aMutable.empty())
771     {
772         aMutable.push_back("time");
773         aMutable.push_back("transactions");
774         aMutable.push_back("prevblock");
775     }
776
777     UniValue result(UniValue::VOBJ);
778     result.push_back(Pair("capabilities", aCaps));
779     result.push_back(Pair("version", pblock->nVersion));
780     result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
781     result.push_back(Pair("finalsaplingroothash", pblock->hashFinalSaplingRoot.GetHex()));
782     result.push_back(Pair("transactions", transactions));
783     if (coinbasetxn) {
784         assert(txCoinbase.isObject());
785         result.push_back(Pair("coinbasetxn", txCoinbase));
786     } else {
787         result.push_back(Pair("coinbaseaux", aux));
788         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
789     }
790     result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
791     if ( ASSETCHAINS_STAKED != 0 )
792     {
793         arith_uint256 POWtarget; int32_t PoSperc;
794         POWtarget = komodo_PoWtarget(&PoSperc,hashTarget,(int32_t)(pindexPrev->GetHeight()+1),ASSETCHAINS_STAKED);
795         result.push_back(Pair("target", POWtarget.GetHex()));
796         result.push_back(Pair("PoSperc", (int64_t)PoSperc));
797         result.push_back(Pair("ac_staked", (int64_t)ASSETCHAINS_STAKED));
798         result.push_back(Pair("origtarget", hashTarget.GetHex()));
799     } else result.push_back(Pair("target", hashTarget.GetHex()));
800     result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
801     result.push_back(Pair("mutable", aMutable));
802     result.push_back(Pair("noncerange", "00000000ffffffff"));
803     result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
804     result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
805     result.push_back(Pair("curtime", pblock->GetBlockTime()));
806     result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
807     result.push_back(Pair("height", (int64_t)(pindexPrev->GetHeight()+1)));
808
809     //fprintf(stderr,"return complete template\n");
810     return result;
811 }
812
813 class submitblock_StateCatcher : public CValidationInterface
814 {
815 public:
816     uint256 hash;
817     bool found;
818     CValidationState state;
819
820     submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
821
822 protected:
823     virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
824         if (block.GetHash() != hash)
825             return;
826         found = true;
827         state = stateIn;
828     };
829 };
830
831 UniValue submitblock(const UniValue& params, bool fHelp)
832 {
833     if (fHelp || params.size() < 1 || params.size() > 2)
834         throw runtime_error(
835             "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
836             "\nAttempts to submit new block to network.\n"
837             "The 'jsonparametersobject' parameter is currently ignored.\n"
838             "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
839
840             "\nArguments\n"
841             "1. \"hexdata\"    (string, required) the hex-encoded block data to submit\n"
842             "2. \"jsonparametersobject\"     (string, optional) object of optional parameters\n"
843             "    {\n"
844             "      \"workid\" : \"id\"    (string, optional) if the server provided a workid, it MUST be included with submissions\n"
845             "    }\n"
846             "\nResult:\n"
847             "\"duplicate\" - node already has valid copy of block\n"
848             "\"duplicate-invalid\" - node already has block, but it is invalid\n"
849             "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
850             "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
851             "\"rejected\" - block was rejected as invalid\n"
852             "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
853             "\nExamples:\n"
854             + HelpExampleCli("submitblock", "\"mydata\"")
855             + HelpExampleRpc("submitblock", "\"mydata\"")
856         );
857
858     CBlock block;
859     //LogPrintStr("Hex block submission: " + params[0].get_str());
860     if (!DecodeHexBlk(block, params[0].get_str()))
861         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
862
863     uint256 hash = block.GetHash();
864     bool fBlockPresent = false;
865     {
866         LOCK(cs_main);
867         BlockMap::iterator mi = mapBlockIndex.find(hash);
868         if (mi != mapBlockIndex.end()) {
869             CBlockIndex *pindex = mi->second;
870             if (pindex)
871             {
872                 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
873                     return "duplicate";
874                 if (pindex->nStatus & BLOCK_FAILED_MASK)
875                     return "duplicate-invalid";
876                 // Otherwise, we might only have the header - process the block before returning
877                 fBlockPresent = true;
878             }
879         }
880     }
881
882     CValidationState state;
883     submitblock_StateCatcher sc(block.GetHash());
884     RegisterValidationInterface(&sc);
885     //printf("submitblock, height=%d, coinbase sequence: %d, scriptSig: %s\n", chainActive.LastTip()->GetHeight()+1, block.vtx[0].vin[0].nSequence, block.vtx[0].vin[0].scriptSig.ToString().c_str());
886     bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, &block, true, NULL);
887     UnregisterValidationInterface(&sc);
888     if (fBlockPresent)
889     {
890         if (fAccepted && !sc.found)
891             return "duplicate-inconclusive";
892         return "duplicate";
893     }
894     if (fAccepted)
895     {
896         if (!sc.found)
897             return "inconclusive";
898         state = sc.state;
899     }
900     return BIP22ValidationResult(state);
901 }
902
903 UniValue estimatefee(const UniValue& params, bool fHelp)
904 {
905     if (fHelp || params.size() != 1)
906         throw runtime_error(
907             "estimatefee nblocks\n"
908             "\nEstimates the approximate fee per kilobyte\n"
909             "needed for a transaction to begin confirmation\n"
910             "within nblocks blocks.\n"
911             "\nArguments:\n"
912             "1. nblocks     (numeric)\n"
913             "\nResult:\n"
914             "n :    (numeric) estimated fee-per-kilobyte\n"
915             "\n"
916             "-1.0 is returned if not enough transactions and\n"
917             "blocks have been observed to make an estimate.\n"
918             "\nExample:\n"
919             + HelpExampleCli("estimatefee", "6")
920             );
921
922     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
923
924     int nBlocks = params[0].get_int();
925     if (nBlocks < 1)
926         nBlocks = 1;
927
928     CFeeRate feeRate = mempool.estimateFee(nBlocks);
929     if (feeRate == CFeeRate(0))
930         return -1.0;
931
932     return ValueFromAmount(feeRate.GetFeePerK());
933 }
934
935 UniValue estimatepriority(const UniValue& params, bool fHelp)
936 {
937     if (fHelp || params.size() != 1)
938         throw runtime_error(
939             "estimatepriority nblocks\n"
940             "\nEstimates the approximate priority\n"
941             "a zero-fee transaction needs to begin confirmation\n"
942             "within nblocks blocks.\n"
943             "\nArguments:\n"
944             "1. nblocks     (numeric)\n"
945             "\nResult:\n"
946             "n :    (numeric) estimated priority\n"
947             "\n"
948             "-1.0 is returned if not enough transactions and\n"
949             "blocks have been observed to make an estimate.\n"
950             "\nExample:\n"
951             + HelpExampleCli("estimatepriority", "6")
952             );
953
954     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
955
956     int nBlocks = params[0].get_int();
957     if (nBlocks < 1)
958         nBlocks = 1;
959
960     return mempool.estimatePriority(nBlocks);
961 }
962
963 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
964 {
965     if (fHelp || params.size() > 1)
966         throw runtime_error(
967             "getblocksubsidy height\n"
968             "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n"
969             "\nArguments:\n"
970             "1. height         (numeric, optional) The block height.  If not provided, defaults to the current height of the chain.\n"
971             "\nResult:\n"
972             "{\n"
973             "  \"miner\" : x.xxx           (numeric) The mining reward amount in KMD.\n"
974             "}\n"
975             "\nExamples:\n"
976             + HelpExampleCli("getblocksubsidy", "1000")
977             + HelpExampleRpc("getblockubsidy", "1000")
978         );
979
980     LOCK(cs_main);
981     int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
982     if (nHeight < 0)
983         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
984
985     CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
986     UniValue result(UniValue::VOBJ);
987     result.push_back(Pair("miner", ValueFromAmount(nReward)));
988     //result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
989     return result;
990 }
991
992 static const CRPCCommand commands[] =
993 { //  category              name                      actor (function)         okSafeMode
994   //  --------------------- ------------------------  -----------------------  ----------
995     { "mining",             "getlocalsolps",          &getlocalsolps,          true  },
996     { "mining",             "getnetworksolps",        &getnetworksolps,        true  },
997     { "mining",             "getnetworkhashps",       &getnetworkhashps,       true  },
998     { "mining",             "getmininginfo",          &getmininginfo,          true  },
999     { "mining",             "prioritisetransaction",  &prioritisetransaction,  true  },
1000     { "mining",             "getblocktemplate",       &getblocktemplate,       true  },
1001     { "mining",             "submitblock",            &submitblock,            true  },
1002     { "mining",             "getblocksubsidy",        &getblocksubsidy,        true  },
1003
1004 #ifdef ENABLE_MINING
1005     { "generating",         "getgenerate",            &getgenerate,            true  },
1006     { "generating",         "setgenerate",            &setgenerate,            true  },
1007     { "generating",         "generate",               &generate,               true  },
1008 #endif
1009
1010     { "util",               "estimatefee",            &estimatefee,            true  },
1011     { "util",               "estimatepriority",       &estimatepriority,       true  },
1012 };
1013
1014 void RegisterMiningRPCCommands(CRPCTable &tableRPC)
1015 {
1016     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1017         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
1018 }
This page took 0.091159 seconds and 4 git commands to generate.