]>
Commit | Line | Data |
---|---|---|
7600e7fc | 1 | // Copyright (c) 2010 Satoshi Nakamoto |
db0e8ccd | 2 | // Copyright (c) 2009-2013 The Bitcoin developers |
7600e7fc JG |
3 | // Distributed under the MIT/X11 software license, see the accompanying |
4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | |
5 | ||
51ed9ec9 | 6 | #include "bitcoinrpc.h" |
0e4b3175 | 7 | #include "chainparams.h" |
7600e7fc JG |
8 | #include "db.h" |
9 | #include "init.h" | |
51ed9ec9 BD |
10 | #include "net.h" |
11 | #include "main.h" | |
d247a5d1 | 12 | #include "miner.h" |
51ed9ec9 BD |
13 | #include "wallet.h" |
14 | ||
15 | #include <stdint.h> | |
16 | ||
17 | #include "json/json_spirit_utils.h" | |
18 | #include "json/json_spirit_value.h" | |
7600e7fc JG |
19 | |
20 | using namespace json_spirit; | |
21 | using namespace std; | |
22 | ||
d98bf10f WL |
23 | // Key used by getwork/getblocktemplate miners. |
24 | // Allocated in InitRPCMining, free'd in ShutdownRPCMining | |
25 | static CReserveKey* pMiningKey = NULL; | |
26 | ||
27 | void InitRPCMining() | |
28 | { | |
b0730874 JG |
29 | if (!pwalletMain) |
30 | return; | |
31 | ||
d98bf10f WL |
32 | // getwork/getblocktemplate mining rewards paid here: |
33 | pMiningKey = new CReserveKey(pwalletMain); | |
34 | } | |
35 | ||
36 | void ShutdownRPCMining() | |
37 | { | |
b0730874 JG |
38 | if (!pMiningKey) |
39 | return; | |
40 | ||
d98bf10f WL |
41 | delete pMiningKey; pMiningKey = NULL; |
42 | } | |
43 | ||
d64eef48 | 44 | // Return average network hashes per second based on the last 'lookup' blocks, |
45 | // or from the last difficulty change if 'lookup' is nonpositive. | |
46 | // If 'height' is nonnegative, compute the estimate at the time when a given block was found. | |
47 | Value GetNetworkHashPS(int lookup, int height) { | |
4c6d41b8 | 48 | CBlockIndex *pb = chainActive[height]; |
d64eef48 | 49 | |
50 | if (pb == NULL || !pb->nHeight) | |
51 | return 0; | |
52 | ||
53 | // If lookup is -1, then use blocks since last difficulty change. | |
54 | if (lookup <= 0) | |
55 | lookup = pb->nHeight % 2016 + 1; | |
56 | ||
57 | // If lookup is larger than chain, then set it to chain length. | |
58 | if (lookup > pb->nHeight) | |
59 | lookup = pb->nHeight; | |
60 | ||
61 | CBlockIndex *pb0 = pb; | |
51ed9ec9 BD |
62 | int64_t minTime = pb0->GetBlockTime(); |
63 | int64_t maxTime = minTime; | |
d64eef48 | 64 | for (int i = 0; i < lookup; i++) { |
65 | pb0 = pb0->pprev; | |
51ed9ec9 | 66 | int64_t time = pb0->GetBlockTime(); |
d64eef48 | 67 | minTime = std::min(time, minTime); |
68 | maxTime = std::max(time, maxTime); | |
69 | } | |
70 | ||
71 | // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception. | |
72 | if (minTime == maxTime) | |
73 | return 0; | |
74 | ||
75 | uint256 workDiff = pb->nChainWork - pb0->nChainWork; | |
51ed9ec9 | 76 | int64_t timeDiff = maxTime - minTime; |
d64eef48 | 77 | |
78 | return (boost::int64_t)(workDiff.getdouble() / timeDiff); | |
79 | } | |
80 | ||
81 | Value getnetworkhashps(const Array& params, bool fHelp) | |
82 | { | |
83 | if (fHelp || params.size() > 2) | |
84 | throw runtime_error( | |
a6099ef3 | 85 | "getnetworkhashps ( blocks height )\n" |
86 | "\nReturns the estimated network hashes per second based on the last n blocks.\n" | |
d64eef48 | 87 | "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n" |
a6099ef3 | 88 | "Pass in [height] to estimate the network speed at the time when a certain block was found.\n" |
89 | "\nArguments:\n" | |
90 | "1. blocks (numeric, optional, default=120) The number of blocks, or -1 for blocks since last difficulty change.\n" | |
91 | "2. height (numeric, optional, default=-1) To estimate at the time of the given height.\n" | |
92 | "\nResult:\n" | |
93 | "x (numeric) Hashes per second estimated\n" | |
94 | "\nExamples:\n" | |
95 | + HelpExampleCli("getnetworkhashps", "") | |
96 | + HelpExampleRpc("getnetworkhashps", "") | |
97 | ); | |
d64eef48 | 98 | |
99 | return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); | |
100 | } | |
101 | ||
102 | ||
7600e7fc JG |
103 | Value getgenerate(const Array& params, bool fHelp) |
104 | { | |
105 | if (fHelp || params.size() != 0) | |
106 | throw runtime_error( | |
107 | "getgenerate\n" | |
a6099ef3 | 108 | "\nReturn if the server is set to generate coins or not. The default is false.\n" |
109 | "It is set with the command line argument -gen (or bitcoin.conf setting gen)\n" | |
110 | "It can also be set with the setgenerate call.\n" | |
111 | "\nResult\n" | |
112 | "true|false (boolean) If the server is set to generate coins or not\n" | |
113 | "\nExamples:\n" | |
114 | + HelpExampleCli("getgenerate", "") | |
115 | + HelpExampleRpc("getgenerate", "") | |
116 | ); | |
7600e7fc | 117 | |
b0730874 JG |
118 | if (!pMiningKey) |
119 | return false; | |
120 | ||
3260b4c0 | 121 | return GetBoolArg("-gen", false); |
7600e7fc JG |
122 | } |
123 | ||
124 | ||
125 | Value setgenerate(const Array& params, bool fHelp) | |
126 | { | |
127 | if (fHelp || params.size() < 1 || params.size() > 2) | |
128 | throw runtime_error( | |
a6099ef3 | 129 | "setgenerate generate ( genproclimit )\n" |
130 | "\nSet 'generate' true or false to turn generation on or off.\n" | |
131 | "Generation is limited to 'genproclimit' processors, -1 is unlimited.\n" | |
132 | "See the getgenerate call for the current setting.\n" | |
133 | "\nArguments:\n" | |
134 | "1. generate (boolean, required) Set to true to turn on generation, off to turn off.\n" | |
135 | "2. genproclimit (numeric, optional) Set the processor limit for when generation is on. Can be -1 for unlimited.\n" | |
c8b74258 | 136 | " Note: in -regtest mode, genproclimit controls how many blocks are generated immediately.\n" |
a6099ef3 | 137 | "\nExamples:\n" |
138 | "\nSet the generation on with a limit of one processor\n" | |
139 | + HelpExampleCli("setgenerate", "true 1") + | |
140 | "\nCheck the setting\n" | |
141 | + HelpExampleCli("getgenerate", "") + | |
142 | "\nTurn off generation\n" | |
143 | + HelpExampleCli("setgenerate", "false") + | |
144 | "\nUsing json rpc\n" | |
145 | + HelpExampleRpc("setgenerate", "true, 1") | |
146 | ); | |
7600e7fc | 147 | |
c8b74258 GA |
148 | if (pwalletMain == NULL) |
149 | throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); | |
150 | ||
7600e7fc JG |
151 | bool fGenerate = true; |
152 | if (params.size() > 0) | |
153 | fGenerate = params[0].get_bool(); | |
154 | ||
c8b74258 | 155 | int nGenProcLimit = -1; |
7600e7fc JG |
156 | if (params.size() > 1) |
157 | { | |
c8b74258 | 158 | nGenProcLimit = params[1].get_int(); |
7600e7fc JG |
159 | if (nGenProcLimit == 0) |
160 | fGenerate = false; | |
161 | } | |
7600e7fc | 162 | |
c8b74258 GA |
163 | // -regtest mode: don't return until nGenProcLimit blocks are generated |
164 | if (fGenerate && Params().NetworkID() == CChainParams::REGTEST) | |
165 | { | |
166 | int nHeightStart = 0; | |
167 | int nHeightEnd = 0; | |
168 | int nHeight = 0; | |
169 | int nGenerate = (nGenProcLimit > 0 ? nGenProcLimit : 1); | |
170 | { // Don't keep cs_main locked | |
171 | LOCK(cs_main); | |
172 | nHeightStart = chainActive.Height(); | |
173 | nHeight = nHeightStart; | |
174 | nHeightEnd = nHeightStart+nGenerate; | |
175 | } | |
176 | int nHeightLast = -1; | |
177 | while (nHeight < nHeightEnd) | |
178 | { | |
179 | if (nHeightLast != nHeight) | |
180 | { | |
181 | nHeightLast = nHeight; | |
182 | GenerateBitcoins(fGenerate, pwalletMain, 1); | |
183 | } | |
184 | MilliSleep(1); | |
185 | { // Don't keep cs_main locked | |
186 | LOCK(cs_main); | |
187 | nHeight = chainActive.Height(); | |
188 | } | |
189 | } | |
190 | } | |
191 | else // Not -regtest: start generate thread, return immediately | |
192 | { | |
193 | mapArgs["-gen"] = (fGenerate ? "1" : "0"); | |
194 | GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit); | |
195 | } | |
196 | ||
7600e7fc JG |
197 | return Value::null; |
198 | } | |
199 | ||
200 | ||
201 | Value gethashespersec(const Array& params, bool fHelp) | |
202 | { | |
203 | if (fHelp || params.size() != 0) | |
204 | throw runtime_error( | |
205 | "gethashespersec\n" | |
a6099ef3 | 206 | "\nReturns a recent hashes per second performance measurement while generating.\n" |
207 | "See the getgenerate and setgenerate calls to turn generation on and off.\n" | |
208 | "\nResult:\n" | |
209 | "n (numeric) The recent hashes per second when generation is on (will return 0 if generation is off)\n" | |
210 | "\nExamples:\n" | |
211 | + HelpExampleCli("gethashespersec", "") | |
212 | + HelpExampleRpc("gethashespersec", "") | |
213 | ); | |
7600e7fc JG |
214 | |
215 | if (GetTimeMillis() - nHPSTimerStart > 8000) | |
216 | return (boost::int64_t)0; | |
217 | return (boost::int64_t)dHashesPerSec; | |
218 | } | |
219 | ||
220 | ||
221 | Value getmininginfo(const Array& params, bool fHelp) | |
222 | { | |
223 | if (fHelp || params.size() != 0) | |
224 | throw runtime_error( | |
225 | "getmininginfo\n" | |
a6099ef3 | 226 | "\nReturns a json object containing mining-related information." |
227 | "\nResult:\n" | |
228 | "{\n" | |
229 | " \"blocks\": nnn, (numeric) The current block\n" | |
230 | " \"currentblocksize\": nnn, (numeric) The last block size\n" | |
231 | " \"currentblocktx\": nnn, (numeric) The last block transaction\n" | |
232 | " \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n" | |
233 | " \"errors\": \"...\" (string) Current errors\n" | |
234 | " \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n" | |
235 | " \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n" | |
236 | " \"hashespersec\": n (numeric) The hashes per second of the generation, or 0 if no generation.\n" | |
237 | " \"pooledtx\": n (numeric) The size of the mem pool\n" | |
238 | " \"testnet\": true|false (boolean) If using testnet or not\n" | |
239 | "}\n" | |
240 | "\nExamples:\n" | |
241 | + HelpExampleCli("getmininginfo", "") | |
242 | + HelpExampleRpc("getmininginfo", "") | |
243 | ); | |
7600e7fc JG |
244 | |
245 | Object obj; | |
4c6d41b8 | 246 | obj.push_back(Pair("blocks", (int)chainActive.Height())); |
3260b4c0 PK |
247 | obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize)); |
248 | obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); | |
249 | obj.push_back(Pair("difficulty", (double)GetDifficulty())); | |
250 | obj.push_back(Pair("errors", GetWarnings("statusbar"))); | |
b0730874 | 251 | obj.push_back(Pair("generate", getgenerate(params, false))); |
3260b4c0 PK |
252 | obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); |
253 | obj.push_back(Pair("hashespersec", gethashespersec(params, false))); | |
d64eef48 | 254 | obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); |
3260b4c0 | 255 | obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); |
0e4b3175 | 256 | obj.push_back(Pair("testnet", TestNet())); |
7600e7fc JG |
257 | return obj; |
258 | } | |
259 | ||
260 | ||
261 | Value getwork(const Array& params, bool fHelp) | |
262 | { | |
263 | if (fHelp || params.size() > 1) | |
264 | throw runtime_error( | |
a6099ef3 | 265 | "getwork ( \"data\" )\n" |
266 | "\nIf 'data' is not specified, it returns the formatted hash data to work on.\n" | |
267 | "If 'data' is specified, tries to solve the block and returns true if it was successful.\n" | |
268 | "\nArguments:\n" | |
269 | "1. \"data\" (string, optional) The hex encoded data to solve\n" | |
270 | "\nResult (when 'data' is not specified):\n" | |
271 | "{\n" | |
272 | " \"midstate\" : \"xxxx\", (string) The precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated | |
273 | " \"data\" : \"xxxxx\", (string) The block data\n" | |
274 | " \"hash1\" : \"xxxxx\", (string) The formatted hash buffer for second hash (DEPRECATED)\n" // deprecated | |
275 | " \"target\" : \"xxxx\" (string) The little endian hash target\n" | |
276 | "}\n" | |
277 | "\nResult (when 'data' is specified):\n" | |
278 | "true|false (boolean) If solving the block specified in the 'data' was successfull\n" | |
279 | "\nExamples:\n" | |
280 | + HelpExampleCli("getwork", "") | |
281 | + HelpExampleRpc("getwork", "") | |
282 | ); | |
7600e7fc JG |
283 | |
284 | if (vNodes.empty()) | |
738835d7 | 285 | throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); |
7600e7fc JG |
286 | |
287 | if (IsInitialBlockDownload()) | |
738835d7 | 288 | throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); |
7600e7fc JG |
289 | |
290 | typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t; | |
291 | static mapNewBlock_t mapNewBlock; // FIXME: thread safety | |
03cac0bb | 292 | static vector<CBlockTemplate*> vNewBlockTemplate; |
7600e7fc JG |
293 | |
294 | if (params.size() == 0) | |
295 | { | |
296 | // Update block | |
297 | static unsigned int nTransactionsUpdatedLast; | |
298 | static CBlockIndex* pindexPrev; | |
51ed9ec9 | 299 | static int64_t nStart; |
03cac0bb | 300 | static CBlockTemplate* pblocktemplate; |
4c6d41b8 | 301 | if (pindexPrev != chainActive.Tip() || |
319b1160 | 302 | (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)) |
7600e7fc | 303 | { |
4c6d41b8 | 304 | if (pindexPrev != chainActive.Tip()) |
7600e7fc JG |
305 | { |
306 | // Deallocate old blocks since they're obsolete now | |
307 | mapNewBlock.clear(); | |
03cac0bb FV |
308 | BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate) |
309 | delete pblocktemplate; | |
310 | vNewBlockTemplate.clear(); | |
7600e7fc JG |
311 | } |
312 | ||
313 | // Clear pindexPrev so future getworks make a new block, despite any failures from here on | |
314 | pindexPrev = NULL; | |
315 | ||
316 | // Store the pindexBest used before CreateNewBlock, to avoid races | |
319b1160 | 317 | nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); |
4c6d41b8 | 318 | CBlockIndex* pindexPrevNew = chainActive.Tip(); |
7600e7fc JG |
319 | nStart = GetTime(); |
320 | ||
321 | // Create new block | |
7e170189 | 322 | pblocktemplate = CreateNewBlockWithKey(*pMiningKey); |
03cac0bb | 323 | if (!pblocktemplate) |
738835d7 | 324 | throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); |
03cac0bb | 325 | vNewBlockTemplate.push_back(pblocktemplate); |
7600e7fc JG |
326 | |
327 | // Need to update only after we know CreateNewBlock succeeded | |
328 | pindexPrev = pindexPrevNew; | |
329 | } | |
03cac0bb | 330 | CBlock* pblock = &pblocktemplate->block; // pointer for convenience |
7600e7fc JG |
331 | |
332 | // Update nTime | |
aabdf9e8 | 333 | UpdateTime(*pblock, pindexPrev); |
7600e7fc JG |
334 | pblock->nNonce = 0; |
335 | ||
336 | // Update nExtraNonce | |
337 | static unsigned int nExtraNonce = 0; | |
338 | IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); | |
339 | ||
340 | // Save | |
341 | mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); | |
342 | ||
343 | // Pre-build hash buffers | |
344 | char pmidstate[32]; | |
345 | char pdata[128]; | |
346 | char phash1[64]; | |
347 | FormatHashBuffers(pblock, pmidstate, pdata, phash1); | |
348 | ||
349 | uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); | |
350 | ||
351 | Object result; | |
352 | result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated | |
353 | result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); | |
354 | result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated | |
355 | result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); | |
356 | return result; | |
357 | } | |
358 | else | |
359 | { | |
360 | // Parse parameters | |
361 | vector<unsigned char> vchData = ParseHex(params[0].get_str()); | |
362 | if (vchData.size() != 128) | |
738835d7 | 363 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); |
7600e7fc JG |
364 | CBlock* pdata = (CBlock*)&vchData[0]; |
365 | ||
366 | // Byte reverse | |
367 | for (int i = 0; i < 128/4; i++) | |
368 | ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]); | |
369 | ||
370 | // Get saved block | |
371 | if (!mapNewBlock.count(pdata->hashMerkleRoot)) | |
372 | return false; | |
373 | CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first; | |
374 | ||
375 | pblock->nTime = pdata->nTime; | |
376 | pblock->nNonce = pdata->nNonce; | |
377 | pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; | |
378 | pblock->hashMerkleRoot = pblock->BuildMerkleTree(); | |
379 | ||
b0730874 | 380 | assert(pwalletMain != NULL); |
36e826ce | 381 | return CheckWork(pblock, *pwalletMain, *pMiningKey); |
7600e7fc JG |
382 | } |
383 | } | |
384 | ||
385 | ||
386 | Value getblocktemplate(const Array& params, bool fHelp) | |
387 | { | |
3beac983 | 388 | if (fHelp || params.size() > 1) |
7600e7fc | 389 | throw runtime_error( |
a6099ef3 | 390 | "getblocktemplate ( \"jsonrequestobject\" )\n" |
391 | "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" | |
392 | "It returns data needed to construct a block to work on.\n" | |
393 | "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n" | |
394 | ||
395 | "\nArguments:\n" | |
396 | "1. \"jsonrequestobject\" (string, optional) A json object in the following spec\n" | |
397 | " {\n" | |
398 | " \"mode\":\"template\" (string, optional) This must be set to \"template\" or omitted\n" | |
399 | " \"capabilities\":[ (array, optional) A list of strings\n" | |
400 | " \"support\" (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n" | |
401 | " ,...\n" | |
402 | " ]\n" | |
403 | " }\n" | |
404 | "\n" | |
405 | ||
406 | "\nResult:\n" | |
407 | "{\n" | |
408 | " \"version\" : n, (numeric) The block version\n" | |
409 | " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" | |
410 | " \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n" | |
411 | " {\n" | |
412 | " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" | |
413 | " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n" | |
414 | " \"depends\" : [ (array) array of numbers \n" | |
415 | " 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" | |
416 | " ,...\n" | |
417 | " ],\n" | |
418 | " \"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" | |
419 | " \"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" | |
420 | " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n" | |
421 | " }\n" | |
422 | " ,...\n" | |
423 | " ],\n" | |
424 | " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n" | |
425 | " \"flags\" : \"flags\" (string) \n" | |
426 | " },\n" | |
427 | " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n" | |
428 | " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" | |
429 | " \"target\" : \"xxxx\", (string) The hash target\n" | |
430 | " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n" | |
431 | " \"mutable\" : [ (array of string) list of ways the block template may be changed \n" | |
432 | " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n" | |
433 | " ,...\n" | |
434 | " ],\n" | |
435 | " \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n" | |
436 | " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n" | |
437 | " \"sizelimit\" : n, (numeric) limit of block size\n" | |
438 | " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n" | |
439 | " \"bits\" : \"xxx\", (string) compressed target of next block\n" | |
440 | " \"height\" : n (numeric) The height of the next block\n" | |
441 | "}\n" | |
442 | ||
443 | "\nExamples:\n" | |
444 | + HelpExampleCli("getblocktemplate", "") | |
445 | + HelpExampleRpc("getblocktemplate", "") | |
446 | ); | |
7600e7fc JG |
447 | |
448 | std::string strMode = "template"; | |
449 | if (params.size() > 0) | |
450 | { | |
451 | const Object& oparam = params[0].get_obj(); | |
452 | const Value& modeval = find_value(oparam, "mode"); | |
453 | if (modeval.type() == str_type) | |
454 | strMode = modeval.get_str(); | |
0689a7eb LD |
455 | else if (modeval.type() == null_type) |
456 | { | |
457 | /* Do nothing */ | |
458 | } | |
7600e7fc | 459 | else |
738835d7 | 460 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); |
7600e7fc JG |
461 | } |
462 | ||
463 | if (strMode != "template") | |
738835d7 | 464 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); |
7600e7fc JG |
465 | |
466 | if (vNodes.empty()) | |
738835d7 | 467 | throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); |
7600e7fc JG |
468 | |
469 | if (IsInitialBlockDownload()) | |
738835d7 | 470 | throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); |
7600e7fc | 471 | |
7600e7fc JG |
472 | // Update block |
473 | static unsigned int nTransactionsUpdatedLast; | |
474 | static CBlockIndex* pindexPrev; | |
51ed9ec9 | 475 | static int64_t nStart; |
03cac0bb | 476 | static CBlockTemplate* pblocktemplate; |
4c6d41b8 | 477 | if (pindexPrev != chainActive.Tip() || |
319b1160 | 478 | (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) |
7600e7fc JG |
479 | { |
480 | // Clear pindexPrev so future calls make a new block, despite any failures from here on | |
481 | pindexPrev = NULL; | |
482 | ||
483 | // Store the pindexBest used before CreateNewBlock, to avoid races | |
319b1160 | 484 | nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); |
4c6d41b8 | 485 | CBlockIndex* pindexPrevNew = chainActive.Tip(); |
7600e7fc JG |
486 | nStart = GetTime(); |
487 | ||
488 | // Create new block | |
03cac0bb | 489 | if(pblocktemplate) |
7600e7fc | 490 | { |
03cac0bb FV |
491 | delete pblocktemplate; |
492 | pblocktemplate = NULL; | |
7600e7fc | 493 | } |
7bb0f6c5 JG |
494 | CScript scriptDummy = CScript() << OP_TRUE; |
495 | pblocktemplate = CreateNewBlock(scriptDummy); | |
03cac0bb | 496 | if (!pblocktemplate) |
738835d7 | 497 | throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); |
7600e7fc JG |
498 | |
499 | // Need to update only after we know CreateNewBlock succeeded | |
500 | pindexPrev = pindexPrevNew; | |
501 | } | |
03cac0bb | 502 | CBlock* pblock = &pblocktemplate->block; // pointer for convenience |
7600e7fc JG |
503 | |
504 | // Update nTime | |
aabdf9e8 | 505 | UpdateTime(*pblock, pindexPrev); |
7600e7fc JG |
506 | pblock->nNonce = 0; |
507 | ||
508 | Array transactions; | |
509 | map<uint256, int64_t> setTxIndex; | |
510 | int i = 0; | |
7600e7fc JG |
511 | BOOST_FOREACH (CTransaction& tx, pblock->vtx) |
512 | { | |
513 | uint256 txHash = tx.GetHash(); | |
514 | setTxIndex[txHash] = i++; | |
515 | ||
516 | if (tx.IsCoinBase()) | |
517 | continue; | |
518 | ||
519 | Object entry; | |
520 | ||
521 | CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | |
522 | ssTx << tx; | |
523 | entry.push_back(Pair("data", HexStr(ssTx.begin(), ssTx.end()))); | |
524 | ||
525 | entry.push_back(Pair("hash", txHash.GetHex())); | |
526 | ||
450cbb09 PW |
527 | Array deps; |
528 | BOOST_FOREACH (const CTxIn &in, tx.vin) | |
7600e7fc | 529 | { |
450cbb09 PW |
530 | if (setTxIndex.count(in.prevout.hash)) |
531 | deps.push_back(setTxIndex[in.prevout.hash]); | |
532 | } | |
533 | entry.push_back(Pair("depends", deps)); | |
7600e7fc | 534 | |
ba1d0800 | 535 | int index_in_template = i - 1; |
f3d872d1 FV |
536 | entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); |
537 | entry.push_back(Pair("sigops", pblocktemplate->vTxSigOps[index_in_template])); | |
7600e7fc JG |
538 | |
539 | transactions.push_back(entry); | |
540 | } | |
541 | ||
542 | Object aux; | |
543 | aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); | |
544 | ||
545 | uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); | |
546 | ||
547 | static Array aMutable; | |
548 | if (aMutable.empty()) | |
549 | { | |
550 | aMutable.push_back("time"); | |
551 | aMutable.push_back("transactions"); | |
552 | aMutable.push_back("prevblock"); | |
553 | } | |
554 | ||
555 | Object result; | |
556 | result.push_back(Pair("version", pblock->nVersion)); | |
557 | result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); | |
558 | result.push_back(Pair("transactions", transactions)); | |
559 | result.push_back(Pair("coinbaseaux", aux)); | |
560 | result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); | |
561 | result.push_back(Pair("target", hashTarget.GetHex())); | |
562 | result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); | |
563 | result.push_back(Pair("mutable", aMutable)); | |
564 | result.push_back(Pair("noncerange", "00000000ffffffff")); | |
565 | result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS)); | |
566 | result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE)); | |
567 | result.push_back(Pair("curtime", (int64_t)pblock->nTime)); | |
568 | result.push_back(Pair("bits", HexBits(pblock->nBits))); | |
569 | result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); | |
570 | ||
571 | return result; | |
572 | } | |
573 | ||
574 | Value submitblock(const Array& params, bool fHelp) | |
575 | { | |
576 | if (fHelp || params.size() < 1 || params.size() > 2) | |
577 | throw runtime_error( | |
a6099ef3 | 578 | "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n" |
579 | "\nAttempts to submit new block to network.\n" | |
580 | "The 'jsonparametersobject' parameter is currently ignored.\n" | |
581 | "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n" | |
582 | ||
583 | "\nArguments\n" | |
584 | "1. \"hexdata\" (string, required) the hex-encoded block data to submit\n" | |
585 | "2. \"jsonparametersobject\" (string, optional) object of optional parameters\n" | |
586 | " {\n" | |
587 | " \"workid\" : \"id\" (string, optional) if the server provided a workid, it MUST be included with submissions\n" | |
588 | " }\n" | |
589 | "\nResult:\n" | |
590 | "\nExamples:\n" | |
591 | + HelpExampleCli("submitblock", "\"mydata\"") | |
592 | + HelpExampleRpc("submitblock", "\"mydata\"") | |
593 | ); | |
7600e7fc JG |
594 | |
595 | vector<unsigned char> blockData(ParseHex(params[0].get_str())); | |
596 | CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION); | |
450cbb09 | 597 | CBlock pblock; |
7600e7fc | 598 | try { |
450cbb09 | 599 | ssBlock >> pblock; |
7600e7fc JG |
600 | } |
601 | catch (std::exception &e) { | |
738835d7 | 602 | throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); |
7600e7fc JG |
603 | } |
604 | ||
ef3988ca PW |
605 | CValidationState state; |
606 | bool fAccepted = ProcessBlock(state, NULL, &pblock); | |
7600e7fc | 607 | if (!fAccepted) |
ef3988ca | 608 | return "rejected"; // TODO: report validation state |
7600e7fc | 609 | |
a2168d94 | 610 | return Value::null; |
7600e7fc | 611 | } |