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