]> Git Repo - VerusCoin.git/blob - src/rpcmining.cpp
Fixed overflow on localsolps and changed sol to hash on mining info
[VerusCoin.git] / src / rpcmining.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 "rpcserver.h"
21 #include "util.h"
22 #include "validationinterface.h"
23 #ifdef ENABLE_WALLET
24 #include "wallet/wallet.h"
25 #endif
26
27 #include <stdint.h>
28
29 #include <boost/assign/list_of.hpp>
30
31 #include <univalue.h>
32
33 using namespace std;
34
35 extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH;
36
37 /**
38  * Return average network hashes per second based on the last 'lookup' blocks,
39  * or over the difficulty averaging window if 'lookup' is nonpositive.
40  * If 'height' is nonnegative, compute the estimate at the time when a given block was found.
41  */
42 int64_t GetNetworkHashPS(int lookup, int height) {
43     CBlockIndex *pb = chainActive.Tip();
44
45     if (height >= 0 && height < chainActive.Height())
46         pb = chainActive[height];
47
48     if (pb == NULL || !pb->nHeight)
49         return 0;
50
51     // If lookup is nonpositive, then use difficulty averaging window.
52     if (lookup <= 0)
53         lookup = Params().GetConsensus().nPowAveragingWindow;
54
55     // If lookup is larger than chain, then set it to chain length.
56     if (lookup > pb->nHeight)
57         lookup = pb->nHeight;
58
59     CBlockIndex *pb0 = pb;
60     int64_t minTime = pb0->GetBlockTime();
61     int64_t maxTime = minTime;
62     for (int i = 0; i < lookup; i++) {
63         pb0 = pb0->pprev;
64         int64_t time = pb0->GetBlockTime();
65         minTime = std::min(time, minTime);
66         maxTime = std::max(time, maxTime);
67     }
68
69     // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
70     if (minTime == maxTime)
71         return 0;
72
73     arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork;
74     int64_t timeDiff = maxTime - minTime;
75
76     return (int64_t)(workDiff.getdouble() / timeDiff);
77 }
78
79 UniValue getlocalsolps(const UniValue& params, bool fHelp)
80 {
81     if (fHelp)
82         throw runtime_error(
83             "getlocalsolps\n"
84             "\nReturns the average local solutions per second since this node was started.\n"
85             "This is the same information shown on the metrics screen (if enabled).\n"
86             "\nResult:\n"
87             "xxx.xxxxx     (numeric) Solutions per second average\n"
88             "\nExamples:\n"
89             + HelpExampleCli("getlocalsolps", "")
90             + HelpExampleRpc("getlocalsolps", "")
91        );
92
93     LOCK(cs_main);
94     return GetLocalSolPS();
95 }
96
97 UniValue getnetworksolps(const UniValue& params, bool fHelp)
98 {
99     if (fHelp || params.size() > 2)
100         throw runtime_error(
101             "getnetworksolps ( blocks height )\n"
102             "\nReturns the estimated network solutions per second based on the last n blocks.\n"
103             "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n"
104             "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
105             "\nArguments:\n"
106             "1. blocks     (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n"
107             "2. height     (numeric, optional, default=-1) To estimate at the time of the given height.\n"
108             "\nResult:\n"
109             "x             (numeric) Solutions per second estimated\n"
110             "\nExamples:\n"
111             + HelpExampleCli("getnetworksolps", "")
112             + HelpExampleRpc("getnetworksolps", "")
113        );
114
115     LOCK(cs_main);
116     return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
117 }
118
119 UniValue getnetworkhashps(const UniValue& params, bool fHelp)
120 {
121     if (fHelp || params.size() > 2)
122         throw runtime_error(
123             "getnetworkhashps ( blocks height )\n"
124             "\nDEPRECATED - left for backwards-compatibility. Use getnetworksolps instead.\n"
125             "\nReturns the estimated network solutions per second based on the last n blocks.\n"
126             "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n"
127             "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
128             "\nArguments:\n"
129             "1. blocks     (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n"
130             "2. height     (numeric, optional, default=-1) To estimate at the time of the given height.\n"
131             "\nResult:\n"
132             "x             (numeric) Solutions per second estimated\n"
133             "\nExamples:\n"
134             + HelpExampleCli("getnetworkhashps", "")
135             + HelpExampleRpc("getnetworkhashps", "")
136        );
137
138     LOCK(cs_main);
139     return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
140 }
141
142 #ifdef ENABLE_MINING
143 UniValue getgenerate(const UniValue& params, bool fHelp)
144 {
145     if (fHelp || params.size() != 0)
146         throw runtime_error(
147             "getgenerate\n"
148             "\nReturn if the server is set to generate coins or not. The default is false.\n"
149             "It is set with the command line argument -gen (or komodo.conf setting gen)\n"
150             "It can also be set with the setgenerate call.\n"
151             "\nResult\n"
152             "true|false      (boolean) If the server is set to generate coins or not\n"
153             "\nExamples:\n"
154             + HelpExampleCli("getgenerate", "")
155             + HelpExampleRpc("getgenerate", "")
156         );
157
158     LOCK(cs_main);
159     return GetBoolArg("-gen", false);
160 }
161
162 extern uint8_t NOTARY_PUBKEY33[33];
163
164 //Value generate(const Array& params, bool fHelp)
165 UniValue generate(const UniValue& params, bool fHelp)
166 {
167     if (fHelp || params.size() < 1 || params.size() > 1)
168         throw runtime_error(
169             "generate numblocks\n"
170             "\nMine blocks immediately (before the RPC call returns)\n"
171             "\nNote: this function can only be used on the regtest network\n"
172             "\nArguments:\n"
173             "1. numblocks    (numeric) How many blocks are generated immediately.\n"
174             "\nResult\n"
175             "[ blockhashes ]     (array) hashes of blocks generated\n"
176             "\nExamples:\n"
177             "\nGenerate 11 blocks\n"
178             + HelpExampleCli("generate", "11")
179         );
180
181     if (GetArg("-mineraddress", "").empty()) {
182 #ifdef ENABLE_WALLET
183         if (!pwalletMain) {
184             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
185         }
186 #else
187         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
188 #endif
189     }
190     if (!Params().MineBlocksOnDemand())
191         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
192
193     int nHeightStart = 0;
194     int nHeightEnd = 0;
195     int nHeight = 0;
196     int nGenerate = params[0].get_int();
197 #ifdef ENABLE_WALLET
198     CReserveKey reservekey(pwalletMain);
199 #endif
200
201     {   // Don't keep cs_main locked
202         LOCK(cs_main);
203         nHeightStart = chainActive.Height();
204         nHeight = nHeightStart;
205         nHeightEnd = nHeightStart+nGenerate;
206     }
207     unsigned int nExtraNonce = 0;
208     UniValue blockHashes(UniValue::VARR);
209     unsigned int n = Params().EquihashN();
210     unsigned int k = Params().EquihashK();
211     while (nHeight < nHeightEnd)
212     {
213 #ifdef ENABLE_WALLET
214         std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
215 #else
216         std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
217 #endif
218         if (!pblocktemplate.get())
219             throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
220         CBlock *pblock = &pblocktemplate->block;
221         {
222             LOCK(cs_main);
223             IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
224         }
225
226         // Hash state
227         crypto_generichash_blake2b_state eh_state;
228         EhInitialiseState(n, k, eh_state);
229
230         // I = the block header minus nonce and solution.
231         CEquihashInput I{*pblock};
232         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
233         ss << I;
234
235         // H(I||...
236         crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
237
238         while (true) {
239             // Yes, there is a chance every nonce could fail to satisfy the -regtest
240             // target -- 1 in 2^(2^256). That ain't gonna happen
241             pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
242
243             // H(I||V||...
244             crypto_generichash_blake2b_state curr_state;
245             curr_state = eh_state;
246             crypto_generichash_blake2b_update(&curr_state,
247                                               pblock->nNonce.begin(),
248                                               pblock->nNonce.size());
249
250             // (x_1, x_2, ...) = A(I, V, n, k)
251             std::function<bool(std::vector<unsigned char>)> validBlock =
252                     [&pblock](std::vector<unsigned char> soln)
253             {
254                 LOCK(cs_main);
255                 pblock->nSolution = soln;
256                 solutionTargetChecks.increment();
257                 return CheckProofOfWork(chainActive.Height(),NOTARY_PUBKEY33,pblock->GetHash(), pblock->nBits, Params().GetConsensus());
258             };
259             bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock);
260             ehSolverRuns.increment();
261             if (found) {
262                 goto endloop;
263             }
264         }
265 endloop:
266         CValidationState state;
267         if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL))
268             throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
269         ++nHeight;
270         blockHashes.push_back(pblock->GetHash().GetHex());
271     }
272     return blockHashes;
273 }
274
275
276 UniValue setgenerate(const UniValue& params, bool fHelp)
277 {
278     if (fHelp || params.size() < 1 || params.size() > 2)
279         throw runtime_error(
280             "setgenerate generate ( genproclimit )\n"
281             "\nSet 'generate' true or false to turn generation on or off.\n"
282             "Generation is limited to 'genproclimit' processors, -1 is unlimited.\n"
283             "See the getgenerate call for the current setting.\n"
284             "\nArguments:\n"
285             "1. generate         (boolean, required) Set to true to turn on generation, off to turn off.\n"
286             "2. genproclimit     (numeric, optional) Set the processor limit for when generation is on. Can be -1 for unlimited.\n"
287             "\nExamples:\n"
288             "\nSet the generation on with a limit of one processor\n"
289             + HelpExampleCli("setgenerate", "true 1") +
290             "\nCheck the setting\n"
291             + HelpExampleCli("getgenerate", "") +
292             "\nTurn off generation\n"
293             + HelpExampleCli("setgenerate", "false") +
294             "\nUsing json rpc\n"
295             + HelpExampleRpc("setgenerate", "true, 1")
296         );
297
298     if (GetArg("-mineraddress", "").empty()) {
299 #ifdef ENABLE_WALLET
300         if (!pwalletMain) {
301             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
302         }
303 #else
304         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
305 #endif
306     }
307     if (Params().MineBlocksOnDemand())
308         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
309
310     bool fGenerate = true;
311     if (params.size() > 0)
312         fGenerate = params[0].get_bool();
313
314     int nGenProcLimit = -1;
315     if (params.size() > 1)
316     {
317         nGenProcLimit = params[1].get_int();
318         if (nGenProcLimit == 0)
319             fGenerate = false;
320     }
321
322     mapArgs["-gen"] = (fGenerate ? "1" : "0");
323     mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
324 #ifdef ENABLE_WALLET
325     GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
326 #else
327     GenerateBitcoins(fGenerate, nGenProcLimit);
328 #endif
329
330     return NullUniValue;
331 }
332 #endif
333
334
335 UniValue getmininginfo(const UniValue& params, bool fHelp)
336 {
337     if (fHelp || params.size() != 0)
338         throw runtime_error(
339             "getmininginfo\n"
340             "\nReturns a json object containing mining-related information."
341             "\nResult:\n"
342             "{\n"
343             "  \"blocks\": nnn,             (numeric) The current block\n"
344             "  \"currentblocksize\": nnn,   (numeric) The last block size\n"
345             "  \"currentblocktx\": nnn,     (numeric) The last block transaction\n"
346             "  \"difficulty\": xxx.xxxxx    (numeric) The current difficulty\n"
347             "  \"errors\": \"...\"          (string) Current errors\n"
348             "  \"generate\": true|false     (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
349             "  \"genproclimit\": n          (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
350             "  \"localsolps\": xxx.xxxxx    (numeric) The average local solution rate in Sol/s since this node was started\n"
351             "  \"networksolps\": x          (numeric) The estimated network solution rate in Sol/s\n"
352             "  \"pooledtx\": n              (numeric) The size of the mem pool\n"
353             "  \"testnet\": true|false      (boolean) If using testnet or not\n"
354             "  \"chain\": \"xxxx\",         (string) current network name as defined in BIP70 (main, test, regtest)\n"
355             "}\n"
356             "\nExamples:\n"
357             + HelpExampleCli("getmininginfo", "")
358             + HelpExampleRpc("getmininginfo", "")
359         );
360
361
362     LOCK(cs_main);
363
364     UniValue obj(UniValue::VOBJ);
365     obj.push_back(Pair("blocks",           (int)chainActive.Height()));
366     obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
367     obj.push_back(Pair("currentblocktx",   (uint64_t)nLastBlockTx));
368     obj.push_back(Pair("difficulty",       (double)GetNetworkDifficulty()));
369     obj.push_back(Pair("errors",           GetWarnings("statusbar")));
370     obj.push_back(Pair("genproclimit",     (int)GetArg("-genproclimit", -1)));
371     if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
372     {
373         obj.push_back(Pair("localsolps"  ,     getlocalsolps(params, false)));
374         obj.push_back(Pair("networksolps",     getnetworksolps(params, false)));
375     }
376     else
377     {
378         obj.push_back(Pair("localhashps"  ,     getlocalsolps(params, false)));
379     }
380     obj.push_back(Pair("networkhashps",    getnetworksolps(params, false)));
381     obj.push_back(Pair("pooledtx",         (uint64_t)mempool.size()));
382     obj.push_back(Pair("testnet",          Params().TestnetToBeDeprecatedFieldRPC()));
383     obj.push_back(Pair("chain",            Params().NetworkIDString()));
384 #ifdef ENABLE_MINING
385     obj.push_back(Pair("generate",         getgenerate(params, false)));
386 #endif
387     return obj;
388 }
389
390
391 // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
392 UniValue prioritisetransaction(const UniValue& params, bool fHelp)
393 {
394     if (fHelp || params.size() != 3)
395         throw runtime_error(
396             "prioritisetransaction <txid> <priority delta> <fee delta>\n"
397             "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
398             "\nArguments:\n"
399             "1. \"txid\"       (string, required) The transaction id.\n"
400             "2. priority delta (numeric, required) The priority to add or subtract.\n"
401             "                  The transaction selection algorithm considers the tx as it would have a higher priority.\n"
402             "                  (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
403             "3. fee delta      (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
404             "                  The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
405             "                  considers the transaction as it would have paid a higher (or lower) fee.\n"
406             "\nResult\n"
407             "true              (boolean) Returns true\n"
408             "\nExamples:\n"
409             + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
410             + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
411         );
412
413     LOCK(cs_main);
414
415     uint256 hash = ParseHashStr(params[0].get_str(), "txid");
416     CAmount nAmount = params[2].get_int64();
417
418     mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
419     return true;
420 }
421
422
423 // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
424 static UniValue BIP22ValidationResult(const CValidationState& state)
425 {
426     if (state.IsValid())
427         return NullUniValue;
428
429     std::string strRejectReason = state.GetRejectReason();
430     if (state.IsError())
431         throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
432     if (state.IsInvalid())
433     {
434         if (strRejectReason.empty())
435             return "rejected";
436         return strRejectReason;
437     }
438     // Should be impossible
439     return "valid?";
440 }
441
442 UniValue getblocktemplate(const UniValue& params, bool fHelp)
443 {
444     if (fHelp || params.size() > 1)
445         throw runtime_error(
446             "getblocktemplate ( \"jsonrequestobject\" )\n"
447             "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
448             "It returns data needed to construct a block to work on.\n"
449             "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
450
451             "\nArguments:\n"
452             "1. \"jsonrequestobject\"       (string, optional) A json object in the following spec\n"
453             "     {\n"
454             "       \"mode\":\"template\"    (string, optional) This must be set to \"template\" or omitted\n"
455             "       \"capabilities\":[       (array, optional) A list of strings\n"
456             "           \"support\"           (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
457             "           ,...\n"
458             "         ]\n"
459             "     }\n"
460             "\n"
461
462             "\nResult:\n"
463             "{\n"
464             "  \"version\" : n,                    (numeric) The block version\n"
465             "  \"previousblockhash\" : \"xxxx\",    (string) The hash of current highest block\n"
466             "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
467             "      {\n"
468             "         \"data\" : \"xxxx\",          (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
469             "         \"hash\" : \"xxxx\",          (string) hash/id encoded in little-endian hexadecimal\n"
470             "         \"depends\" : [              (array) array of numbers \n"
471             "             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"
472             "             ,...\n"
473             "         ],\n"
474             "         \"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"
475             "         \"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"
476             "         \"required\" : true|false     (boolean) if provided and true, this transaction must be in the final block\n"
477             "      }\n"
478             "      ,...\n"
479             "  ],\n"
480 //            "  \"coinbaseaux\" : {                  (json object) data that should be included in the coinbase's scriptSig content\n"
481 //            "      \"flags\" : \"flags\"            (string) \n"
482 //            "  },\n"
483 //            "  \"coinbasevalue\" : n,               (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
484             "  \"coinbasetxn\" : { ... },           (json object) information for coinbase transaction\n"
485             "  \"target\" : \"xxxx\",               (string) The hash target\n"
486             "  \"mintime\" : xxx,                   (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
487             "  \"mutable\" : [                      (array of string) list of ways the block template may be changed \n"
488             "     \"value\"                         (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
489             "     ,...\n"
490             "  ],\n"
491             "  \"noncerange\" : \"00000000ffffffff\",   (string) A range of valid nonces\n"
492             "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
493             "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
494             "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
495             "  \"bits\" : \"xxx\",                 (string) compressed target of next block\n"
496             "  \"height\" : n                      (numeric) The height of the next block\n"
497             "}\n"
498
499             "\nExamples:\n"
500             + HelpExampleCli("getblocktemplate", "")
501             + HelpExampleRpc("getblocktemplate", "")
502          );
503
504     LOCK(cs_main);
505
506     // Wallet or miner address is required because we support coinbasetxn
507     if (GetArg("-mineraddress", "").empty()) {
508 #ifdef ENABLE_WALLET
509         if (!pwalletMain) {
510             throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
511         }
512 #else
513         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
514 #endif
515     }
516
517     std::string strMode = "template";
518     UniValue lpval = NullUniValue;
519     // TODO: Re-enable coinbasevalue once a specification has been written
520     bool coinbasetxn = true;
521     if (params.size() > 0)
522     {
523         const UniValue& oparam = params[0].get_obj();
524         const UniValue& modeval = find_value(oparam, "mode");
525         if (modeval.isStr())
526             strMode = modeval.get_str();
527         else if (modeval.isNull())
528         {
529             /* Do nothing */
530         }
531         else
532             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
533         lpval = find_value(oparam, "longpollid");
534
535         if (strMode == "proposal")
536         {
537             const UniValue& dataval = find_value(oparam, "data");
538             if (!dataval.isStr())
539                 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
540
541             CBlock block;
542             if (!DecodeHexBlk(block, dataval.get_str()))
543                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
544
545             uint256 hash = block.GetHash();
546             BlockMap::iterator mi = mapBlockIndex.find(hash);
547             if (mi != mapBlockIndex.end()) {
548                 CBlockIndex *pindex = mi->second;
549                 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
550                     return "duplicate";
551                 if (pindex->nStatus & BLOCK_FAILED_MASK)
552                     return "duplicate-invalid";
553                 return "duplicate-inconclusive";
554             }
555
556             CBlockIndex* const pindexPrev = chainActive.Tip();
557             // TestBlockValidity only supports blocks built on the current Tip
558             if (block.hashPrevBlock != pindexPrev->GetBlockHash())
559                 return "inconclusive-not-best-prevblk";
560             CValidationState state;
561             TestBlockValidity(state, block, pindexPrev, false, true);
562             return BIP22ValidationResult(state);
563         }
564     }
565
566     if (strMode != "template")
567         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
568
569     if (vNodes.empty())
570         throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Zcash is not connected!");
571
572     //if (IsInitialBlockDownload())
573      //   throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
574
575     static unsigned int nTransactionsUpdatedLast;
576
577     if (!lpval.isNull())
578     {
579         // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
580         uint256 hashWatchedChain;
581         boost::system_time checktxtime;
582         unsigned int nTransactionsUpdatedLastLP;
583
584         if (lpval.isStr())
585         {
586             // Format: <hashBestChain><nTransactionsUpdatedLast>
587             std::string lpstr = lpval.get_str();
588
589             hashWatchedChain.SetHex(lpstr.substr(0, 64));
590             nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
591         }
592         else
593         {
594             // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
595             hashWatchedChain = chainActive.Tip()->GetBlockHash();
596             nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
597         }
598
599         // Release the wallet and main lock while waiting
600         LEAVE_CRITICAL_SECTION(cs_main);
601         {
602             checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
603
604             boost::unique_lock<boost::mutex> lock(csBestBlock);
605             while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
606             {
607                 if (!cvBlockChange.timed_wait(lock, checktxtime))
608                 {
609                     // Timeout: Check transactions for update
610                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
611                         break;
612                     checktxtime += boost::posix_time::seconds(10);
613                 }
614             }
615         }
616         ENTER_CRITICAL_SECTION(cs_main);
617
618         if (!IsRPCRunning())
619             throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
620         // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
621     }
622
623     // Update block
624     static CBlockIndex* pindexPrev;
625     static int64_t nStart;
626     static CBlockTemplate* pblocktemplate;
627     if (pindexPrev != chainActive.Tip() ||
628         (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
629     {
630         // Clear pindexPrev so future calls make a new block, despite any failures from here on
631         pindexPrev = NULL;
632
633         // Store the pindexBest used before CreateNewBlockWithKey, to avoid races
634         nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
635         CBlockIndex* pindexPrevNew = chainActive.Tip();
636         nStart = GetTime();
637
638         // Create new block
639         if(pblocktemplate)
640         {
641             delete pblocktemplate;
642             pblocktemplate = NULL;
643         }
644 #ifdef ENABLE_WALLET
645         CReserveKey reservekey(pwalletMain);
646         pblocktemplate = CreateNewBlockWithKey(reservekey);
647 #else
648         pblocktemplate = CreateNewBlockWithKey();
649 #endif
650         if (!pblocktemplate)
651             throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
652
653         // Need to update only after we know CreateNewBlockWithKey succeeded
654         pindexPrev = pindexPrevNew;
655     }
656     CBlock* pblock = &pblocktemplate->block; // pointer for convenience
657
658     // Update nTime
659     UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
660     pblock->nNonce = uint256();
661
662     UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
663
664     UniValue txCoinbase = NullUniValue;
665     UniValue transactions(UniValue::VARR);
666     map<uint256, int64_t> setTxIndex;
667     int i = 0;
668     BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
669         uint256 txHash = tx.GetHash();
670         setTxIndex[txHash] = i++;
671
672         if (tx.IsCoinBase() && !coinbasetxn)
673             continue;
674
675         UniValue entry(UniValue::VOBJ);
676
677         entry.push_back(Pair("data", EncodeHexTx(tx)));
678
679         entry.push_back(Pair("hash", txHash.GetHex()));
680
681         UniValue deps(UniValue::VARR);
682         BOOST_FOREACH (const CTxIn &in, tx.vin)
683         {
684             if (setTxIndex.count(in.prevout.hash))
685                 deps.push_back(setTxIndex[in.prevout.hash]);
686         }
687         entry.push_back(Pair("depends", deps));
688
689         int index_in_template = i - 1;
690         entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
691         entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template]));
692
693         if (tx.IsCoinBase()) {
694             // Show founders' reward if it is required
695             //if (pblock->vtx[0].vout.size() > 1) {
696                 // Correct this if GetBlockTemplate changes the order
697             //    entry.push_back(Pair("foundersreward", (int64_t)tx.vout[1].nValue));
698             //}
699             entry.push_back(Pair("coinbasevalue", 3*COIN));
700             entry.push_back(Pair("required", true));
701             txCoinbase = entry;
702         } else
703             transactions.push_back(entry);
704     }
705
706     UniValue aux(UniValue::VOBJ);
707     aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
708
709     arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
710
711     static UniValue aMutable(UniValue::VARR);
712     if (aMutable.empty())
713     {
714         aMutable.push_back("time");
715         aMutable.push_back("transactions");
716         aMutable.push_back("prevblock");
717     }
718
719     UniValue result(UniValue::VOBJ);
720     result.push_back(Pair("capabilities", aCaps));
721     result.push_back(Pair("version", pblock->nVersion));
722     result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
723     result.push_back(Pair("transactions", transactions));
724     if (coinbasetxn) {
725         assert(txCoinbase.isObject());
726         result.push_back(Pair("coinbasetxn", txCoinbase));
727     } else {
728         result.push_back(Pair("coinbaseaux", aux));
729         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
730     }
731     result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
732     result.push_back(Pair("target", hashTarget.GetHex()));
733     result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
734     result.push_back(Pair("mutable", aMutable));
735     result.push_back(Pair("noncerange", "00000000ffffffff"));
736     result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
737     result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
738     result.push_back(Pair("curtime", pblock->GetBlockTime()));
739     result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
740     result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
741
742     //fprintf(stderr,"return complete template\n");
743     return result;
744 }
745
746 class submitblock_StateCatcher : public CValidationInterface
747 {
748 public:
749     uint256 hash;
750     bool found;
751     CValidationState state;
752
753     submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
754
755 protected:
756     virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
757         if (block.GetHash() != hash)
758             return;
759         found = true;
760         state = stateIn;
761     };
762 };
763
764 UniValue submitblock(const UniValue& params, bool fHelp)
765 {
766     if (fHelp || params.size() < 1 || params.size() > 2)
767         throw runtime_error(
768             "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
769             "\nAttempts to submit new block to network.\n"
770             "The 'jsonparametersobject' parameter is currently ignored.\n"
771             "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
772
773             "\nArguments\n"
774             "1. \"hexdata\"    (string, required) the hex-encoded block data to submit\n"
775             "2. \"jsonparametersobject\"     (string, optional) object of optional parameters\n"
776             "    {\n"
777             "      \"workid\" : \"id\"    (string, optional) if the server provided a workid, it MUST be included with submissions\n"
778             "    }\n"
779             "\nResult:\n"
780             "\"duplicate\" - node already has valid copy of block\n"
781             "\"duplicate-invalid\" - node already has block, but it is invalid\n"
782             "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
783             "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
784             "\"rejected\" - block was rejected as invalid\n"
785             "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
786             "\nExamples:\n"
787             + HelpExampleCli("submitblock", "\"mydata\"")
788             + HelpExampleRpc("submitblock", "\"mydata\"")
789         );
790
791     CBlock block;
792     if (!DecodeHexBlk(block, params[0].get_str()))
793         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
794
795     uint256 hash = block.GetHash();
796     bool fBlockPresent = false;
797     {
798         LOCK(cs_main);
799         BlockMap::iterator mi = mapBlockIndex.find(hash);
800         if (mi != mapBlockIndex.end()) {
801             CBlockIndex *pindex = mi->second;
802             if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
803                 return "duplicate";
804             if (pindex->nStatus & BLOCK_FAILED_MASK)
805                 return "duplicate-invalid";
806             // Otherwise, we might only have the header - process the block before returning
807             fBlockPresent = true;
808         }
809     }
810
811     CValidationState state;
812     submitblock_StateCatcher sc(block.GetHash());
813     RegisterValidationInterface(&sc);
814     bool fAccepted = ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL);
815     UnregisterValidationInterface(&sc);
816     if (fBlockPresent)
817     {
818         if (fAccepted && !sc.found)
819             return "duplicate-inconclusive";
820         return "duplicate";
821     }
822     if (fAccepted)
823     {
824         if (!sc.found)
825             return "inconclusive";
826         state = sc.state;
827     }
828     return BIP22ValidationResult(state);
829 }
830
831 UniValue estimatefee(const UniValue& params, bool fHelp)
832 {
833     if (fHelp || params.size() != 1)
834         throw runtime_error(
835             "estimatefee nblocks\n"
836             "\nEstimates the approximate fee per kilobyte\n"
837             "needed for a transaction to begin confirmation\n"
838             "within nblocks blocks.\n"
839             "\nArguments:\n"
840             "1. nblocks     (numeric)\n"
841             "\nResult:\n"
842             "n :    (numeric) estimated fee-per-kilobyte\n"
843             "\n"
844             "-1.0 is returned if not enough transactions and\n"
845             "blocks have been observed to make an estimate.\n"
846             "\nExample:\n"
847             + HelpExampleCli("estimatefee", "6")
848             );
849
850     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
851
852     int nBlocks = params[0].get_int();
853     if (nBlocks < 1)
854         nBlocks = 1;
855
856     CFeeRate feeRate = mempool.estimateFee(nBlocks);
857     if (feeRate == CFeeRate(0))
858         return -1.0;
859
860     return ValueFromAmount(feeRate.GetFeePerK());
861 }
862
863 UniValue estimatepriority(const UniValue& params, bool fHelp)
864 {
865     if (fHelp || params.size() != 1)
866         throw runtime_error(
867             "estimatepriority nblocks\n"
868             "\nEstimates the approximate priority\n"
869             "a zero-fee transaction needs to begin confirmation\n"
870             "within nblocks blocks.\n"
871             "\nArguments:\n"
872             "1. nblocks     (numeric)\n"
873             "\nResult:\n"
874             "n :    (numeric) estimated priority\n"
875             "\n"
876             "-1.0 is returned if not enough transactions and\n"
877             "blocks have been observed to make an estimate.\n"
878             "\nExample:\n"
879             + HelpExampleCli("estimatepriority", "6")
880             );
881
882     RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
883
884     int nBlocks = params[0].get_int();
885     if (nBlocks < 1)
886         nBlocks = 1;
887
888     return mempool.estimatePriority(nBlocks);
889 }
890
891 UniValue getblocksubsidy(const UniValue& params, bool fHelp)
892 {
893     if (fHelp || params.size() > 1)
894         throw runtime_error(
895             "getblocksubsidy height\n"
896             "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n"
897             "\nArguments:\n"
898             "1. height         (numeric, optional) The block height.  If not provided, defaults to the current height of the chain.\n"
899             "\nResult:\n"
900             "{\n"
901             "  \"miner\" : x.xxx           (numeric) The mining reward amount in KMD.\n"
902             "}\n"
903             "\nExamples:\n"
904             + HelpExampleCli("getblocksubsidy", "1000")
905             + HelpExampleRpc("getblockubsidy", "1000")
906         );
907
908     LOCK(cs_main);
909     int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height();
910     if (nHeight < 0)
911         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
912
913     CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
914     UniValue result(UniValue::VOBJ);
915     result.push_back(Pair("miner", ValueFromAmount(nReward)));
916     //result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
917     return result;
918 }
This page took 0.077124 seconds and 4 git commands to generate.