]> Git Repo - VerusCoin.git/blob - src/rpc/mining.cpp
Merge pull request #140 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     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)
588                 {
589                     if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
590                         return "duplicate";
591                     if (pindex->nStatus & BLOCK_FAILED_MASK)
592                         return "duplicate-invalid";
593                 }
594                 return "duplicate-inconclusive";
595             }
596
597             CBlockIndex* const pindexPrev = chainActive.LastTip();
598             // TestBlockValidity only supports blocks built on the current Tip
599             if (block.hashPrevBlock != pindexPrev->GetBlockHash())
600                 return "inconclusive-not-best-prevblk";
601             CValidationState state;
602             TestBlockValidity(state, block, pindexPrev, false, true);
603             return BIP22ValidationResult(state);
604         }
605     }
606
607     if (strMode != "template")
608         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
609
610     bool fvNodesEmpty;
611     {
612         LOCK(cs_vNodes);
613         fvNodesEmpty = vNodes.empty();
614     }
615     if (Params().MiningRequiresPeers() && (IsNotInSync() || fvNodesEmpty))
616     {
617         /*
618         int loops = 0, blockDiff = 0, newDiff = 0;
619         const int delay = 15;
620         do {
621             if (fvNodesEmpty)
622             {
623                 MilliSleep(1000 + rand() % 4000);
624                 LOCK(cs_vNodes);
625                 fvNodesEmpty = vNodes.empty();
626                 loops = 0;
627                 blockDiff = 0;
628             }
629             if ((newDiff = IsNotInSync()) > 1)
630             {
631                 if (blockDiff != newDiff)
632                 {
633                     blockDiff = newDiff;
634                 }
635                 else
636                 {
637                     if (++loops <= delay)
638                     {
639                         MilliSleep(1000);
640                     }
641                     else break;
642                 }
643             }
644         } while (fvNodesEmpty || IsNotInSync());
645         if (loops > delay)
646             throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
647         */
648         throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Cannot get a block template while no peers are connected or chain not in sync!");
649     }
650
651     //if (IsInitialBlockDownload())
652      //   throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
653
654     static unsigned int nTransactionsUpdatedLast;
655
656     if (!lpval.isNull())
657     {
658         // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
659         uint256 hashWatchedChain;
660         boost::system_time checktxtime;
661         unsigned int nTransactionsUpdatedLastLP;
662
663         if (lpval.isStr())
664         {
665             // Format: <hashBestChain><nTransactionsUpdatedLast>
666             std::string lpstr = lpval.get_str();
667
668             hashWatchedChain.SetHex(lpstr.substr(0, 64));
669             nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
670         }
671         else
672         {
673             // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
674             hashWatchedChain = chainActive.LastTip()->GetBlockHash();
675             nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
676         }
677
678         // Release the wallet and main lock while waiting
679         LEAVE_CRITICAL_SECTION(cs_main);
680         {
681             checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
682
683             boost::unique_lock<boost::mutex> lock(csBestBlock);
684             while (chainActive.LastTip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
685             {
686                 if (!cvBlockChange.timed_wait(lock, checktxtime))
687                 {
688                     // Timeout: Check transactions for update
689                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
690                         break;
691                     checktxtime += boost::posix_time::seconds(10);
692                 }
693             }
694         }
695         ENTER_CRITICAL_SECTION(cs_main);
696
697         if (!IsRPCRunning())
698             throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
699         // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
700     }
701
702     // Update block
703     static CBlockIndex* pindexPrev;
704     static int64_t nStart;
705     static CBlockTemplate* pblocktemplate;
706     if (pindexPrev != chainActive.LastTip() ||
707         (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
708     {
709         // Clear pindexPrev so future calls make a new block, despite any failures from here on
710         pindexPrev = NULL;
711
712         // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
713         nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
714         CBlockIndex* pindexPrevNew = chainActive.LastTip();
715         nStart = GetTime();
716
717         // Create new block
718         if(pblocktemplate)
719         {
720             delete pblocktemplate;
721             pblocktemplate = NULL;
722         }
723 #ifdef ENABLE_WALLET
724         CReserveKey reservekey(pwalletMain);
725         pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
726 #else
727         pblocktemplate = CreateNewBlockWithKey();
728 #endif
729         if (!pblocktemplate)
730             throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");
731
732         // Need to update only after we know CreateNewBlockWithKey succeeded
733         pindexPrev = pindexPrevNew;
734     }
735     CBlock* pblock = &pblocktemplate->block; // pointer for convenience
736
737     // Update nTime
738     UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
739     pblock->nNonce = uint256();
740
741     UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
742
743     UniValue txCoinbase = NullUniValue;
744     UniValue transactions(UniValue::VARR);
745     map<uint256, int64_t> setTxIndex;
746     int i = 0;
747     BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
748         uint256 txHash = tx.GetHash();
749         setTxIndex[txHash] = i++;
750
751         if (tx.IsCoinBase() && !coinbasetxn)
752             continue;
753
754         UniValue entry(UniValue::VOBJ);
755
756         entry.push_back(Pair("data", EncodeHexTx(tx)));
757
758         entry.push_back(Pair("hash", txHash.GetHex()));
759
760         UniValue deps(UniValue::VARR);
761         BOOST_FOREACH (const CTxIn &in, tx.vin)
762         {
763             if (setTxIndex.count(in.prevout.hash))
764                 deps.push_back(setTxIndex[in.prevout.hash]);
765         }
766         entry.push_back(Pair("depends", deps));
767
768         int index_in_template = i - 1;
769         entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
770         entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
771
772         if (tx.IsCoinBase()) {
773             // Show founders' reward if it is required
774             //if (pblock->vtx[0].vout.size() > 1) {
775                 // Correct this if GetBlockTemplate changes the order
776             //    entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
777             //}
778             CAmount nReward = GetBlockSubsidy(chainActive.LastTip()->GetHeight()+1, Params().GetConsensus());
779             entry.push_back(Pair("coinbasevalue", nReward));
780             entry.push_back(Pair("required", true));
781             txCoinbase = entry;
782         } else
783             transactions.push_back(entry);
784     }
785
786     UniValue aux(UniValue::VOBJ);
787     aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
788
789     arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
790
791     static UniValue aMutable(UniValue::VARR);
792     if (aMutable.empty())
793     {
794         aMutable.push_back("time");
795         aMutable.push_back("transactions");
796         aMutable.push_back("prevblock");
797     }
798
799     UniValue result(UniValue::VOBJ);
800     result.push_back(Pair("capabilities", aCaps));
801     result.push_back(Pair("version", pblock->nVersion));
802     result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
803     result.push_back(Pair("finalsaplingroothash", pblock->hashFinalSaplingRoot.GetHex()));
804     result.push_back(Pair("transactions", transactions));
805     if (coinbasetxn) {
806         assert(txCoinbase.isObject());
807         result.push_back(Pair("coinbasetxn", txCoinbase));
808     } else {
809         result.push_back(Pair("coinbaseaux", aux));
810         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
811     }
812     result.push_back(Pair("longpollid", chainActive.LastTip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
813     if ( ASSETCHAINS_STAKED != 0 )
814     {
815         arith_uint256 POWtarget; int32_t PoSperc;
816         POWtarget = komodo_PoWtarget(&PoSperc,hashTarget,(int32_t)(pindexPrev->GetHeight()+1),ASSETCHAINS_STAKED);
817         result.push_back(Pair("target", POWtarget.GetHex()));
818         result.push_back(Pair("PoSperc", (int64_t)PoSperc));
819         result.push_back(Pair("ac_staked", (int64_t)ASSETCHAINS_STAKED));
820         result.push_back(Pair("origtarget", hashTarget.GetHex()));
821     } else result.push_back(Pair("target", hashTarget.GetHex()));
822     result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
823     result.push_back(Pair("mutable", aMutable));
824     result.push_back(Pair("noncerange", "00000000ffffffff"));
825     result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
826     result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
827     result.push_back(Pair("curtime", pblock->GetBlockTime()));
828     result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
829     result.push_back(Pair("height", (int64_t)(pindexPrev->GetHeight()+1)));
830
831     //fprintf(stderr,"return complete template\n");
832     return result;
833 }
834
835 class submitblock_StateCatcher : public CValidationInterface
836 {
837 public:
838     uint256 hash;
839     bool found;
840     CValidationState state;
841
842     submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
843
844 protected:
845     virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
846         if (block.GetHash() != hash)
847             return;
848         found = true;
849         state = stateIn;
850     };
851 };
852
853 UniValue submitblock(const UniValue& params, bool fHelp)
854 {
855     if (fHelp || params.size() < 1 || params.size() > 2)
856         throw runtime_error(
857             "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
858             "\nAttempts to submit new block to network.\n"
859             "The 'jsonparametersobject' parameter is currently ignored.\n"
860             "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
861
862             "\nArguments\n"
863             "1. \"hexdata\"    (string, required) the hex-encoded block data to submit\n"
864             "2. \"jsonparametersobject\"     (string, optional) object of optional parameters\n"
865             "    {\n"
866             "      \"workid\" : \"id\"    (string, optional) if the server provided a workid, it MUST be included with submissions\n"
867             "    }\n"
868             "\nResult:\n"
869             "\"duplicate\" - node already has valid copy of block\n"
870             "\"duplicate-invalid\" - node already has block, but it is invalid\n"
871             "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
872             "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
873             "\"rejected\" - block was rejected as invalid\n"
874             "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
875             "\nExamples:\n"
876             + HelpExampleCli("submitblock", "\"mydata\"")
877             + HelpExampleRpc("submitblock", "\"mydata\"")
878         );
879
880     CBlock block;
881     if (!DecodeHexBlk(block, params[0].get_str()))
882         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
883
884     uint256 hash = block.GetHash();
885     bool fBlockPresent = false;
886     {
887         LOCK(cs_main);
888         BlockMap::iterator mi = mapBlockIndex.find(hash);
889         if (mi != mapBlockIndex.end()) {
890             CBlockIndex *pindex = mi->second;
891             if (pindex)
892             {
893                 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
894                     return "duplicate";
895                 if (pindex->nStatus & BLOCK_FAILED_MASK)
896                     return "duplicate-invalid";
897                 // Otherwise, we might only have the header - process the block before returning
898                 fBlockPresent = true;
899             }
900         }
901     }
902
903     CValidationState state;
904     submitblock_StateCatcher sc(block.GetHash());
905     RegisterValidationInterface(&sc);
906     bool fAccepted = ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, &block, true, NULL);
907     UnregisterValidationInterface(&sc);
908     if (fBlockPresent)
909     {
910         if (fAccepted && !sc.found)
911             return "duplicate-inconclusive";
912         return "duplicate";
913     }
914     if (fAccepted)
915     {
916         if (!sc.found)
917             return "inconclusive";
918         state = sc.state;
919     }
920     return BIP22ValidationResult(state);
921 }
922
923 UniValue estimatefee(const UniValue& params, bool fHelp)
924 {
925     if (fHelp || params.size() != 1)
926         throw runtime_error(
927             "estimatefee nblocks\n"
928             "\nEstimates the approximate fee per kilobyte\n"
929             "needed for a transaction to begin confirmation\n"
930             "within nblocks blocks.\n"
931             "\nArguments:\n"
932             "1. nblocks     (numeric)\n"
933             "\nResult:\n"
934             "n :    (numeric) estimated fee-per-kilobyte\n"
935             "\n"
936             "-1.0 is returned if not enough transactions and\n"
937             "blocks have been observed to make an estimate.\n"
938             "\nExample:\n"
939             + HelpExampleCli("estimatefee", "6")
940             );
941
942     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
943
944     int nBlocks = params[0].get_int();
945     if (nBlocks < 1)
946         nBlocks = 1;
947
948     CFeeRate feeRate = mempool.estimateFee(nBlocks);
949     if (feeRate == CFeeRate(0))
950         return -1.0;
951
952     return ValueFromAmount(feeRate.GetFeePerK());
953 }
954
955 UniValue estimatepriority(const UniValue& params, bool fHelp)
956 {
957     if (fHelp || params.size() != 1)
958         throw runtime_error(
959             "estimatepriority nblocks\n"
960             "\nEstimates the approximate priority\n"
961             "a zero-fee transaction needs to begin confirmation\n"
962             "within nblocks blocks.\n"
963             "\nArguments:\n"
964             "1. nblocks     (numeric)\n"
965             "\nResult:\n"
966             "n :    (numeric) estimated priority\n"
967             "\n"
968             "-1.0 is returned if not enough transactions and\n"
969             "blocks have been observed to make an estimate.\n"
970             "\nExample:\n"
971             + HelpExampleCli("estimatepriority", "6")
972             );
973
974     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
975
976     int nBlocks = params[0].get_int();
977     if (nBlocks < 1)
978         nBlocks = 1;
979
980     return mempool.estimatePriority(nBlocks);
981 }
982
983 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
984 {
985     if (fHelp || params.size() > 1)
986         throw runtime_error(
987             "getblocksubsidy height\n"
988             "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n"
989             "\nArguments:\n"
990             "1. height         (numeric, optional) The block height.  If not provided, defaults to the current height of the chain.\n"
991             "\nResult:\n"
992             "{\n"
993             "  \"miner\" : x.xxx           (numeric) The mining reward amount in KMD.\n"
994             "}\n"
995             "\nExamples:\n"
996             + HelpExampleCli("getblocksubsidy", "1000")
997             + HelpExampleRpc("getblockubsidy", "1000")
998         );
999
1000     LOCK(cs_main);
1001     int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
1002     if (nHeight < 0)
1003         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
1004
1005     CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
1006     UniValue result(UniValue::VOBJ);
1007     result.push_back(Pair("miner", ValueFromAmount(nReward)));
1008     //result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
1009     return result;
1010 }
1011
1012 static const CRPCCommand commands[] =
1013 { //  category              name                      actor (function)         okSafeMode
1014   //  --------------------- ------------------------  -----------------------  ----------
1015     { "mining",             "getlocalsolps",          &getlocalsolps,          true  },
1016     { "mining",             "getnetworksolps",        &getnetworksolps,        true  },
1017     { "mining",             "getnetworkhashps",       &getnetworkhashps,       true  },
1018     { "mining",             "getmininginfo",          &getmininginfo,          true  },
1019     { "mining",             "prioritisetransaction",  &prioritisetransaction,  true  },
1020     { "mining",             "getblocktemplate",       &getblocktemplate,       true  },
1021     { "mining",             "submitblock",            &submitblock,            true  },
1022     { "mining",             "getblocksubsidy",        &getblocksubsidy,        true  },
1023
1024 #ifdef ENABLE_MINING
1025     { "generating",         "getgenerate",            &getgenerate,            true  },
1026     { "generating",         "setgenerate",            &setgenerate,            true  },
1027     { "generating",         "generate",               &generate,               true  },
1028 #endif
1029
1030     { "util",               "estimatefee",            &estimatefee,            true  },
1031     { "util",               "estimatepriority",       &estimatepriority,       true  },
1032 };
1033
1034 void RegisterMiningRPCCommands(CRPCTable &tableRPC)
1035 {
1036     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1037         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
1038 }
This page took 0.084539 seconds and 4 git commands to generate.