]>
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 | |
a10a6e2a | 31 | #include <univalue.h> |
7600e7fc | 32 | |
7600e7fc JG |
33 | using namespace std; |
34 | ||
72fb3d29 MF |
35 | /** |
36 | * Return average network hashes per second based on the last 'lookup' blocks, | |
f2c48e15 | 37 | * or over the difficulty averaging window if 'lookup' is nonpositive. |
72fb3d29 MF |
38 | * If 'height' is nonnegative, compute the estimate at the time when a given block was found. |
39 | */ | |
eb5b582e | 40 | int64_t GetNetworkHashPS(int lookup, int height) { |
aec55a07 GM |
41 | CBlockIndex *pb = chainActive.Tip(); |
42 | ||
43 | if (height >= 0 && height < chainActive.Height()) | |
44 | pb = chainActive[height]; | |
d64eef48 | 45 | |
46 | if (pb == NULL || !pb->nHeight) | |
47 | return 0; | |
48 | ||
5e207f4e | 49 | // If lookup is nonpositive, then use difficulty averaging window. |
d64eef48 | 50 | if (lookup <= 0) |
cdec0b92 | 51 | lookup = Params().GetConsensus().nPowAveragingWindow; |
f2c48e15 | 52 | |
cdec0b92 JG |
53 | // If lookup is larger than chain, then set it to chain length. |
54 | if (lookup > pb->nHeight) | |
d64eef48 | 55 | lookup = pb->nHeight; |
56 | ||
57 | CBlockIndex *pb0 = pb; | |
51ed9ec9 BD |
58 | int64_t minTime = pb0->GetBlockTime(); |
59 | int64_t maxTime = minTime; | |
d64eef48 | 60 | for (int i = 0; i < lookup; i++) { |
61 | pb0 = pb0->pprev; | |
51ed9ec9 | 62 | int64_t time = pb0->GetBlockTime(); |
d64eef48 | 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 | ||
734f85c4 | 71 | arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork; |
51ed9ec9 | 72 | int64_t timeDiff = maxTime - minTime; |
d64eef48 | 73 | |
4b61a6a4 | 74 | return (int64_t)(workDiff.getdouble() / timeDiff); |
d64eef48 | 75 | } |
76 | ||
0d37ae3a | 77 | UniValue getlocalsolps(const UniValue& params, bool fHelp) |
000499ae JG |
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 | ||
0d37ae3a | 95 | UniValue getnetworksolps(const UniValue& params, bool fHelp) |
000499ae JG |
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 | ||
d014114d | 117 | UniValue getnetworkhashps(const UniValue& params, bool fHelp) |
d64eef48 | 118 | { |
119 | if (fHelp || params.size() > 2) | |
120 | throw runtime_error( | |
a6099ef3 | 121 | "getnetworkhashps ( blocks height )\n" |
000499ae JG |
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" | |
f2c48e15 | 124 | "Pass in [blocks] to override # of blocks, -1 specifies over difficulty averaging window.\n" |
a6099ef3 | 125 | "Pass in [height] to estimate the network speed at the time when a certain block was found.\n" |
126 | "\nArguments:\n" | |
f2c48e15 | 127 | "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks over difficulty averaging window.\n" |
a6099ef3 | 128 | "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n" |
129 | "\nResult:\n" | |
000499ae | 130 | "x (numeric) Solutions per second estimated\n" |
a6099ef3 | 131 | "\nExamples:\n" |
132 | + HelpExampleCli("getnetworkhashps", "") | |
133 | + HelpExampleRpc("getnetworkhashps", "") | |
134 | ); | |
d64eef48 | 135 | |
4401b2d7 | 136 | LOCK(cs_main); |
d64eef48 | 137 | return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); |
138 | } | |
139 | ||
8e8b6d70 | 140 | #ifdef ENABLE_MINING |
d014114d | 141 | UniValue getgenerate(const UniValue& params, bool fHelp) |
7600e7fc JG |
142 | { |
143 | if (fHelp || params.size() != 0) | |
144 | throw runtime_error( | |
145 | "getgenerate\n" | |
a6099ef3 | 146 | "\nReturn if the server is set to generate coins or not. The default is false.\n" |
aaf64959 | 147 | "It is set with the command line argument -gen (or zcash.conf setting gen)\n" |
a6099ef3 | 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 | ); | |
7600e7fc | 155 | |
4401b2d7 | 156 | LOCK(cs_main); |
3260b4c0 | 157 | return GetBoolArg("-gen", false); |
7600e7fc JG |
158 | } |
159 | ||
d014114d | 160 | UniValue generate(const UniValue& params, bool fHelp) |
6b04508e PW |
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" | |
48265f3c | 166 | "\nNote: this function can only be used on the regtest network\n" |
a33cd5ba | 167 | "\nArguments:\n" |
6b04508e PW |
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 | ||
8e8b6d70 JG |
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 | } | |
48265f3c WL |
185 | if (!Params().MineBlocksOnDemand()) |
186 | throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest"); | |
6b04508e PW |
187 | |
188 | int nHeightStart = 0; | |
189 | int nHeightEnd = 0; | |
190 | int nHeight = 0; | |
191 | int nGenerate = params[0].get_int(); | |
8e8b6d70 | 192 | #ifdef ENABLE_WALLET |
48265f3c | 193 | CReserveKey reservekey(pwalletMain); |
8e8b6d70 | 194 | #endif |
6b04508e PW |
195 | |
196 | { // Don't keep cs_main locked | |
197 | LOCK(cs_main); | |
198 | nHeightStart = chainActive.Height(); | |
199 | nHeight = nHeightStart; | |
200 | nHeightEnd = nHeightStart+nGenerate; | |
201 | } | |
48265f3c | 202 | unsigned int nExtraNonce = 0; |
38fc4b70 | 203 | UniValue blockHashes(UniValue::VARR); |
e9574728 JG |
204 | unsigned int n = Params().EquihashN(); |
205 | unsigned int k = Params().EquihashK(); | |
48265f3c WL |
206 | while (nHeight < nHeightEnd) |
207 | { | |
8e8b6d70 | 208 | #ifdef ENABLE_WALLET |
08c58194 | 209 | std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey)); |
8e8b6d70 | 210 | #else |
08c58194 | 211 | std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey()); |
8e8b6d70 | 212 | #endif |
48265f3c | 213 | if (!pblocktemplate.get()) |
6b04508e | 214 | throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty"); |
48265f3c WL |
215 | CBlock *pblock = &pblocktemplate->block; |
216 | { | |
217 | LOCK(cs_main); | |
218 | IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); | |
219 | } | |
fdda3c50 JG |
220 | |
221 | // Hash state | |
222 | crypto_generichash_blake2b_state eh_state; | |
e9574728 | 223 | EhInitialiseState(n, k, eh_state); |
fdda3c50 JG |
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) { | |
48265f3c | 234 | // Yes, there is a chance every nonce could fail to satisfy the -regtest |
fdda3c50 JG |
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) | |
5be6abbf JG |
246 | std::function<bool(std::vector<unsigned char>)> validBlock = |
247 | [&pblock](std::vector<unsigned char> soln) { | |
fdda3c50 | 248 | pblock->nSolution = soln; |
e7d59bbc | 249 | solutionTargetChecks.increment(); |
51eb5273 JG |
250 | return CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus()); |
251 | }; | |
a6df7ab5 JG |
252 | bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock); |
253 | ehSolverRuns.increment(); | |
254 | if (found) { | |
51eb5273 | 255 | goto endloop; |
a6df7ab5 | 256 | } |
48265f3c | 257 | } |
fdda3c50 | 258 | endloop: |
48265f3c | 259 | CValidationState state; |
304892fc | 260 | if (!ProcessNewBlock(state, NULL, pblock, true, NULL)) |
48265f3c | 261 | throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); |
6b04508e | 262 | ++nHeight; |
48265f3c | 263 | blockHashes.push_back(pblock->GetHash().GetHex()); |
6b04508e PW |
264 | } |
265 | return blockHashes; | |
266 | } | |
7600e7fc | 267 | |
48265f3c | 268 | |
d014114d | 269 | UniValue setgenerate(const UniValue& params, bool fHelp) |
7600e7fc JG |
270 | { |
271 | if (fHelp || params.size() < 1 || params.size() > 2) | |
272 | throw runtime_error( | |
a6099ef3 | 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 | ); | |
7600e7fc | 290 | |
8e8b6d70 JG |
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 | } | |
27ce808f WL |
300 | if (Params().MineBlocksOnDemand()) |
301 | throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network"); | |
c8b74258 | 302 | |
7600e7fc JG |
303 | bool fGenerate = true; |
304 | if (params.size() > 0) | |
305 | fGenerate = params[0].get_bool(); | |
306 | ||
c8b74258 | 307 | int nGenProcLimit = -1; |
7600e7fc JG |
308 | if (params.size() > 1) |
309 | { | |
c8b74258 | 310 | nGenProcLimit = params[1].get_int(); |
7600e7fc JG |
311 | if (nGenProcLimit == 0) |
312 | fGenerate = false; | |
313 | } | |
7600e7fc | 314 | |
6b04508e PW |
315 | mapArgs["-gen"] = (fGenerate ? "1" : "0"); |
316 | mapArgs ["-genproclimit"] = itostr(nGenProcLimit); | |
8e8b6d70 | 317 | #ifdef ENABLE_WALLET |
6b04508e | 318 | GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit); |
8e8b6d70 JG |
319 | #else |
320 | GenerateBitcoins(fGenerate, nGenProcLimit); | |
321 | #endif | |
c8b74258 | 322 | |
ed21d5bd | 323 | return NullUniValue; |
7600e7fc | 324 | } |
4a85e067 | 325 | #endif |
7600e7fc JG |
326 | |
327 | ||
d014114d | 328 | UniValue getmininginfo(const UniValue& params, bool fHelp) |
7600e7fc JG |
329 | { |
330 | if (fHelp || params.size() != 0) | |
331 | throw runtime_error( | |
332 | "getmininginfo\n" | |
a6099ef3 | 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" | |
000499ae JG |
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" | |
a6099ef3 | 345 | " \"pooledtx\": n (numeric) The size of the mem pool\n" |
346 | " \"testnet\": true|false (boolean) If using testnet or not\n" | |
f6984e81 | 347 | " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" |
a6099ef3 | 348 | "}\n" |
349 | "\nExamples:\n" | |
350 | + HelpExampleCli("getmininginfo", "") | |
351 | + HelpExampleRpc("getmininginfo", "") | |
352 | ); | |
7600e7fc | 353 | |
4401b2d7 EL |
354 | |
355 | LOCK(cs_main); | |
356 | ||
38fc4b70 | 357 | UniValue obj(UniValue::VOBJ); |
4c6d41b8 | 358 | obj.push_back(Pair("blocks", (int)chainActive.Height())); |
3260b4c0 PK |
359 | obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize)); |
360 | obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); | |
695a7a88 | 361 | obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); |
3260b4c0 | 362 | obj.push_back(Pair("errors", GetWarnings("statusbar"))); |
3260b4c0 | 363 | obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); |
000499ae JG |
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))); | |
3260b4c0 | 367 | obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); |
cc972107 | 368 | obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); |
f6984e81 | 369 | obj.push_back(Pair("chain", Params().NetworkIDString())); |
8e8b6d70 | 370 | #ifdef ENABLE_MINING |
4a85e067 | 371 | obj.push_back(Pair("generate", getgenerate(params, false))); |
4a85e067 | 372 | #endif |
7600e7fc JG |
373 | return obj; |
374 | } | |
375 | ||
376 | ||
8a20cd3c | 377 | // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts |
d014114d | 378 | UniValue prioritisetransaction(const UniValue& params, bool fHelp) |
2a72d459 LD |
379 | { |
380 | if (fHelp || params.size() != 3) | |
381 | throw runtime_error( | |
382 | "prioritisetransaction <txid> <priority delta> <fee delta>\n" | |
ebdcc360 CL |
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" | |
8a20cd3c | 389 | "3. fee delta (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n" |
ebdcc360 CL |
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" | |
8a20cd3c LD |
395 | + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000") |
396 | + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000") | |
ebdcc360 | 397 | ); |
2a72d459 | 398 | |
4401b2d7 | 399 | LOCK(cs_main); |
ebdcc360 | 400 | |
4401b2d7 | 401 | uint256 hash = ParseHashStr(params[0].get_str(), "txid"); |
8a20cd3c | 402 | CAmount nAmount = params[2].get_int64(); |
ebdcc360 CL |
403 | |
404 | mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount); | |
2a72d459 LD |
405 | return true; |
406 | } | |
407 | ||
408 | ||
3dcbb9b6 | 409 | // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller |
851f58f9 | 410 | static UniValue BIP22ValidationResult(const CValidationState& state) |
3dcbb9b6 LD |
411 | { |
412 | if (state.IsValid()) | |
d014114d | 413 | return NullUniValue; |
3dcbb9b6 LD |
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 | ||
d014114d | 428 | UniValue getblocktemplate(const UniValue& params, bool fHelp) |
7600e7fc | 429 | { |
3beac983 | 430 | if (fHelp || params.size() > 1) |
7600e7fc | 431 | throw runtime_error( |
a6099ef3 | 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" | |
53ddbaed JG |
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" | |
a6099ef3 | 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 | ); | |
7600e7fc | 489 | |
4401b2d7 EL |
490 | LOCK(cs_main); |
491 | ||
8e8b6d70 JG |
492 | // Wallet or miner address is required because we support coinbasetxn |
493 | if (GetArg("-mineraddress", "").empty()) { | |
2cc0a252 | 494 | #ifdef ENABLE_WALLET |
8e8b6d70 JG |
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 | |
53ddbaed JG |
501 | } |
502 | ||
7600e7fc | 503 | std::string strMode = "template"; |
851f58f9 | 504 | UniValue lpval = NullUniValue; |
53ddbaed JG |
505 | // TODO: Re-enable coinbasevalue once a specification has been written |
506 | bool coinbasetxn = true; | |
7600e7fc JG |
507 | if (params.size() > 0) |
508 | { | |
d014114d JS |
509 | const UniValue& oparam = params[0].get_obj(); |
510 | const UniValue& modeval = find_value(oparam, "mode"); | |
ed21d5bd | 511 | if (modeval.isStr()) |
7600e7fc | 512 | strMode = modeval.get_str(); |
ed21d5bd | 513 | else if (modeval.isNull()) |
0689a7eb LD |
514 | { |
515 | /* Do nothing */ | |
516 | } | |
7600e7fc | 517 | else |
738835d7 | 518 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); |
ff6a7af1 | 519 | lpval = find_value(oparam, "longpollid"); |
9765a50c LD |
520 | |
521 | if (strMode == "proposal") | |
522 | { | |
d014114d | 523 | const UniValue& dataval = find_value(oparam, "data"); |
f70084cf | 524 | if (!dataval.isStr()) |
9765a50c LD |
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 | } | |
7600e7fc JG |
550 | } |
551 | ||
552 | if (strMode != "template") | |
738835d7 | 553 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); |
7600e7fc JG |
554 | |
555 | if (vNodes.empty()) | |
59ac34e3 | 556 | throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Zcash is not connected!"); |
7600e7fc JG |
557 | |
558 | if (IsInitialBlockDownload()) | |
59ac34e3 | 559 | throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks..."); |
7600e7fc | 560 | |
7600e7fc | 561 | static unsigned int nTransactionsUpdatedLast; |
ff6a7af1 | 562 | |
ed21d5bd | 563 | if (!lpval.isNull()) |
ff6a7af1 LD |
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 | ||
ed21d5bd | 570 | if (lpval.isStr()) |
ff6a7af1 LD |
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 | |
ff6a7af1 LD |
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); | |
ff6a7af1 LD |
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 | |
7600e7fc | 610 | static CBlockIndex* pindexPrev; |
51ed9ec9 | 611 | static int64_t nStart; |
03cac0bb | 612 | static CBlockTemplate* pblocktemplate; |
4c6d41b8 | 613 | if (pindexPrev != chainActive.Tip() || |
319b1160 | 614 | (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) |
7600e7fc JG |
615 | { |
616 | // Clear pindexPrev so future calls make a new block, despite any failures from here on | |
617 | pindexPrev = NULL; | |
618 | ||
53ddbaed | 619 | // Store the pindexBest used before CreateNewBlockWithKey, to avoid races |
319b1160 | 620 | nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); |
48265f3c | 621 | CBlockIndex* pindexPrevNew = chainActive.Tip(); |
7600e7fc JG |
622 | nStart = GetTime(); |
623 | ||
624 | // Create new block | |
03cac0bb | 625 | if(pblocktemplate) |
7600e7fc | 626 | { |
03cac0bb FV |
627 | delete pblocktemplate; |
628 | pblocktemplate = NULL; | |
7600e7fc | 629 | } |
8e8b6d70 | 630 | #ifdef ENABLE_WALLET |
53ddbaed JG |
631 | CReserveKey reservekey(pwalletMain); |
632 | pblocktemplate = CreateNewBlockWithKey(reservekey); | |
8e8b6d70 JG |
633 | #else |
634 | pblocktemplate = CreateNewBlockWithKey(); | |
635 | #endif | |
03cac0bb | 636 | if (!pblocktemplate) |
738835d7 | 637 | throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); |
7600e7fc | 638 | |
53ddbaed | 639 | // Need to update only after we know CreateNewBlockWithKey succeeded |
7600e7fc JG |
640 | pindexPrev = pindexPrevNew; |
641 | } | |
03cac0bb | 642 | CBlock* pblock = &pblocktemplate->block; // pointer for convenience |
7600e7fc JG |
643 | |
644 | // Update nTime | |
bebe7282 | 645 | UpdateTime(pblock, Params().GetConsensus(), pindexPrev); |
fdda3c50 | 646 | pblock->nNonce = uint256(); |
7600e7fc | 647 | |
38fc4b70 | 648 | UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); |
9765a50c | 649 | |
0d37ae3a | 650 | UniValue txCoinbase = NullUniValue; |
38fc4b70 | 651 | UniValue transactions(UniValue::VARR); |
7600e7fc JG |
652 | map<uint256, int64_t> setTxIndex; |
653 | int i = 0; | |
db954a65 | 654 | BOOST_FOREACH (const CTransaction& tx, pblock->vtx) { |
805344dc | 655 | uint256 txHash = tx.GetHash(); |
7600e7fc JG |
656 | setTxIndex[txHash] = i++; |
657 | ||
53ddbaed | 658 | if (tx.IsCoinBase() && !coinbasetxn) |
7600e7fc JG |
659 | continue; |
660 | ||
38fc4b70 | 661 | UniValue entry(UniValue::VOBJ); |
7600e7fc | 662 | |
ae775b5b | 663 | entry.push_back(Pair("data", EncodeHexTx(tx))); |
7600e7fc JG |
664 | |
665 | entry.push_back(Pair("hash", txHash.GetHex())); | |
666 | ||
38fc4b70 | 667 | UniValue deps(UniValue::VARR); |
450cbb09 | 668 | BOOST_FOREACH (const CTxIn &in, tx.vin) |
7600e7fc | 669 | { |
450cbb09 PW |
670 | if (setTxIndex.count(in.prevout.hash)) |
671 | deps.push_back(setTxIndex[in.prevout.hash]); | |
672 | } | |
673 | entry.push_back(Pair("depends", deps)); | |
7600e7fc | 674 | |
ba1d0800 | 675 | int index_in_template = i - 1; |
f3d872d1 FV |
676 | entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); |
677 | entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template])); | |
7600e7fc | 678 | |
53ddbaed | 679 | if (tx.IsCoinBase()) { |
89aa746c JG |
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 | } | |
53ddbaed JG |
685 | entry.push_back(Pair("required", true)); |
686 | txCoinbase = entry; | |
687 | } else { | |
688 | transactions.push_back(entry); | |
689 | } | |
7600e7fc JG |
690 | } |
691 | ||
38fc4b70 | 692 | UniValue aux(UniValue::VOBJ); |
7600e7fc JG |
693 | aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); |
694 | ||
734f85c4 | 695 | arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); |
7600e7fc | 696 | |
38fc4b70 | 697 | static UniValue aMutable(UniValue::VARR); |
7600e7fc JG |
698 | if (aMutable.empty()) |
699 | { | |
700 | aMutable.push_back("time"); | |
701 | aMutable.push_back("transactions"); | |
702 | aMutable.push_back("prevblock"); | |
703 | } | |
704 | ||
38fc4b70 | 705 | UniValue result(UniValue::VOBJ); |
9765a50c | 706 | result.push_back(Pair("capabilities", aCaps)); |
7600e7fc JG |
707 | result.push_back(Pair("version", pblock->nVersion)); |
708 | result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); | |
709 | result.push_back(Pair("transactions", transactions)); | |
53ddbaed | 710 | if (coinbasetxn) { |
0d37ae3a | 711 | assert(txCoinbase.isObject()); |
53ddbaed JG |
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 | } | |
ff6a7af1 | 717 | result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); |
7600e7fc JG |
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)); | |
209377a7 | 724 | result.push_back(Pair("curtime", pblock->GetBlockTime())); |
645d497a | 725 | result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); |
7600e7fc JG |
726 | result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); |
727 | ||
728 | return result; | |
729 | } | |
730 | ||
f877aaaf LD |
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 | ||
d014114d | 749 | UniValue submitblock(const UniValue& params, bool fHelp) |
7600e7fc JG |
750 | { |
751 | if (fHelp || params.size() < 1 || params.size() > 2) | |
752 | throw runtime_error( | |
a6099ef3 | 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" | |
552d7553 JG |
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" | |
a6099ef3 | 771 | "\nExamples:\n" |
772 | + HelpExampleCli("submitblock", "\"mydata\"") | |
773 | + HelpExampleRpc("submitblock", "\"mydata\"") | |
774 | ); | |
7600e7fc | 775 | |
60755dbf LD |
776 | CBlock block; |
777 | if (!DecodeHexBlk(block, params[0].get_str())) | |
738835d7 | 778 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); |
7600e7fc | 779 | |
60755dbf | 780 | uint256 hash = block.GetHash(); |
eb63bf86 MC |
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 | } | |
7600e7fc JG |
794 | } |
795 | ||
ef3988ca | 796 | CValidationState state; |
60755dbf | 797 | submitblock_StateCatcher sc(block.GetHash()); |
f877aaaf | 798 | RegisterValidationInterface(&sc); |
304892fc | 799 | bool fAccepted = ProcessNewBlock(state, NULL, &block, true, NULL); |
f877aaaf | 800 | UnregisterValidationInterface(&sc); |
eb63bf86 | 801 | if (fBlockPresent) |
60755dbf LD |
802 | { |
803 | if (fAccepted && !sc.found) | |
804 | return "duplicate-inconclusive"; | |
805 | return "duplicate"; | |
806 | } | |
f877aaaf LD |
807 | if (fAccepted) |
808 | { | |
809 | if (!sc.found) | |
810 | return "inconclusive"; | |
811 | state = sc.state; | |
812 | } | |
3dcbb9b6 | 813 | return BIP22ValidationResult(state); |
7600e7fc | 814 | } |
171ca774 | 815 | |
d014114d | 816 | UniValue estimatefee(const UniValue& params, bool fHelp) |
171ca774 GA |
817 | { |
818 | if (fHelp || params.size() != 1) | |
819 | throw runtime_error( | |
820 | "estimatefee nblocks\n" | |
821 | "\nEstimates the approximate fee per kilobyte\n" | |
a15dba5d | 822 | "needed for a transaction to begin confirmation\n" |
171ca774 GA |
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 | ||
ed21d5bd | 835 | RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); |
171ca774 GA |
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 | ||
d014114d | 848 | UniValue estimatepriority(const UniValue& params, bool fHelp) |
171ca774 GA |
849 | { |
850 | if (fHelp || params.size() != 1) | |
851 | throw runtime_error( | |
852 | "estimatepriority nblocks\n" | |
853 | "\nEstimates the approximate priority\n" | |
a15dba5d | 854 | "a zero-fee transaction needs to begin confirmation\n" |
171ca774 GA |
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 | ||
ed21d5bd | 867 | RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM)); |
171ca774 GA |
868 | |
869 | int nBlocks = params[0].get_int(); | |
870 | if (nBlocks < 1) | |
871 | nBlocks = 1; | |
872 | ||
873 | return mempool.estimatePriority(nBlocks); | |
874 | } | |
1b114e54 | 875 | |
0d37ae3a | 876 | UniValue getblocksubsidy(const UniValue& params, bool fHelp) |
1b114e54 | 877 | { |
5d50130b | 878 | if (fHelp || params.size() > 1) |
1b114e54 | 879 | throw runtime_error( |
1db13d50 | 880 | "getblocksubsidy height\n" |
ea26d328 | 881 | "\nReturns block subsidy reward, taking into account the mining slow start and the founders reward, of block at index provided.\n" |
1b114e54 | 882 | "\nArguments:\n" |
5d50130b | 883 | "1. height (numeric, optional) The block height. If not provided, defaults to the current height of the chain.\n" |
1b114e54 | 884 | "\nResult:\n" |
ea26d328 S |
885 | "{\n" |
886 | " \"miner\" : x.xxx (numeric) The mining reward amount in ZEC.\n" | |
887 | " \"founders\" : x.xxx (numeric) The founders reward amount in ZEC.\n" | |
888 | "}\n" | |
1b114e54 S |
889 | "\nExamples:\n" |
890 | + HelpExampleCli("getblocksubsidy", "1000") | |
891 | + HelpExampleRpc("getblockubsidy", "1000") | |
892 | ); | |
893 | ||
933bff47 | 894 | LOCK(cs_main); |
5d50130b S |
895 | int nHeight = (params.size()==1) ? params[0].get_int() : chainActive.Height(); |
896 | if (nHeight < 0) | |
1b114e54 S |
897 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); |
898 | ||
899 | CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus()); | |
ea26d328 | 900 | CAmount nFoundersReward = 0; |
db0f9315 | 901 | if ((nHeight > 0) && (nHeight <= Params().GetConsensus().GetLastFoundersRewardBlockHeight())) { |
ea26d328 S |
902 | nFoundersReward = nReward/5; |
903 | nReward -= nFoundersReward; | |
904 | } | |
0d37ae3a | 905 | UniValue result(UniValue::VOBJ); |
ea26d328 S |
906 | result.push_back(Pair("miner", ValueFromAmount(nReward))); |
907 | result.push_back(Pair("founders", ValueFromAmount(nFoundersReward))); | |
908 | return result; | |
1b114e54 | 909 | } |