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