Line data Source code
1 : // Copyright (c) 2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "amount.h"
7 : #include "chain.h"
8 : #include "chainparams.h"
9 : #include "checkpoints.h"
10 : #include "coins.h"
11 : #include "consensus/validation.h"
12 : #include "main.h"
13 : #include "primitives/transaction.h"
14 : #include "rpcserver.h"
15 : #include "streams.h"
16 : #include "sync.h"
17 : #include "txmempool.h"
18 : #include "util.h"
19 : #include "utilstrencodings.h"
20 :
21 : #include <stdint.h>
22 :
23 : #include <univalue.h>
24 :
25 : using namespace std;
26 :
27 : extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
28 : void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
29 :
30 20 : double GetDifficulty(const CBlockIndex* blockindex)
31 : {
32 : // Floating point number that is a multiple of the minimum difficulty,
33 : // minimum difficulty = 1.0.
34 20 : if (blockindex == NULL)
35 : {
36 1 : if (chainActive.Tip() == NULL)
37 : return 1.0;
38 : else
39 1 : blockindex = chainActive.Tip();
40 : }
41 :
42 20 : int nShift = (blockindex->nBits >> 24) & 0xff;
43 :
44 : double dDiff =
45 20 : (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
46 :
47 40 : while (nShift < 29)
48 : {
49 0 : dDiff *= 256.0;
50 0 : nShift++;
51 : }
52 80 : while (nShift > 29)
53 : {
54 60 : dDiff /= 256.0;
55 60 : nShift--;
56 : }
57 :
58 20 : return dDiff;
59 : }
60 :
61 6 : UniValue blockheaderToJSON(const CBlockIndex* blockindex)
62 : {
63 18 : UniValue result(UniValue::VOBJ);
64 24 : result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
65 6 : int confirmations = -1;
66 : // Only report confirmations if the block is on the main chain
67 6 : if (chainActive.Contains(blockindex))
68 6 : confirmations = chainActive.Height() - blockindex->nHeight + 1;
69 12 : result.push_back(Pair("confirmations", confirmations));
70 12 : result.push_back(Pair("height", blockindex->nHeight));
71 12 : result.push_back(Pair("version", blockindex->nVersion));
72 18 : result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
73 12 : result.push_back(Pair("time", (int64_t)blockindex->nTime));
74 12 : result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce));
75 18 : result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
76 12 : result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
77 18 : result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
78 :
79 6 : if (blockindex->pprev)
80 24 : result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
81 6 : CBlockIndex *pnext = chainActive.Next(blockindex);
82 6 : if (pnext)
83 24 : result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
84 6 : return result;
85 : }
86 :
87 13 : UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
88 : {
89 39 : UniValue result(UniValue::VOBJ);
90 39 : result.push_back(Pair("hash", block.GetHash().GetHex()));
91 13 : int confirmations = -1;
92 : // Only report confirmations if the block is on the main chain
93 13 : if (chainActive.Contains(blockindex))
94 13 : confirmations = chainActive.Height() - blockindex->nHeight + 1;
95 26 : result.push_back(Pair("confirmations", confirmations));
96 26 : result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
97 26 : result.push_back(Pair("height", blockindex->nHeight));
98 26 : result.push_back(Pair("version", block.nVersion));
99 39 : result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
100 52 : UniValue txs(UniValue::VARR);
101 203 : BOOST_FOREACH(const CTransaction&tx, block.vtx)
102 : {
103 23 : if(txDetails)
104 : {
105 18 : UniValue objTx(UniValue::VOBJ);
106 6 : TxToJSON(tx, uint256(), objTx);
107 6 : txs.push_back(objTx);
108 : }
109 : else
110 34 : txs.push_back(tx.GetHash().GetHex());
111 : }
112 26 : result.push_back(Pair("tx", txs));
113 39 : result.push_back(Pair("time", block.GetBlockTime()));
114 26 : result.push_back(Pair("nonce", (uint64_t)block.nNonce));
115 39 : result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
116 26 : result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
117 39 : result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
118 :
119 13 : if (blockindex->pprev)
120 52 : result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
121 13 : CBlockIndex *pnext = chainActive.Next(blockindex);
122 13 : if (pnext)
123 40 : result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
124 13 : return result;
125 : }
126 :
127 723 : UniValue getblockcount(const UniValue& params, bool fHelp)
128 : {
129 1446 : if (fHelp || params.size() != 0)
130 : throw runtime_error(
131 : "getblockcount\n"
132 : "\nReturns the number of blocks in the longest block chain.\n"
133 : "\nResult:\n"
134 : "n (numeric) The current block count\n"
135 : "\nExamples:\n"
136 0 : + HelpExampleCli("getblockcount", "")
137 0 : + HelpExampleRpc("getblockcount", "")
138 0 : );
139 :
140 723 : LOCK(cs_main);
141 1446 : return chainActive.Height();
142 : }
143 :
144 9 : UniValue getbestblockhash(const UniValue& params, bool fHelp)
145 : {
146 18 : if (fHelp || params.size() != 0)
147 : throw runtime_error(
148 : "getbestblockhash\n"
149 : "\nReturns the hash of the best (tip) block in the longest block chain.\n"
150 : "\nResult\n"
151 : "\"hex\" (string) the block hash hex encoded\n"
152 : "\nExamples\n"
153 0 : + HelpExampleCli("getbestblockhash", "")
154 0 : + HelpExampleRpc("getbestblockhash", "")
155 0 : );
156 :
157 9 : LOCK(cs_main);
158 36 : return chainActive.Tip()->GetBlockHash().GetHex();
159 : }
160 :
161 0 : UniValue getdifficulty(const UniValue& params, bool fHelp)
162 : {
163 0 : if (fHelp || params.size() != 0)
164 : throw runtime_error(
165 : "getdifficulty\n"
166 : "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
167 : "\nResult:\n"
168 : "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
169 : "\nExamples:\n"
170 0 : + HelpExampleCli("getdifficulty", "")
171 0 : + HelpExampleRpc("getdifficulty", "")
172 0 : );
173 :
174 0 : LOCK(cs_main);
175 0 : return GetDifficulty();
176 : }
177 :
178 486 : UniValue mempoolToJSON(bool fVerbose = false)
179 : {
180 486 : if (fVerbose)
181 : {
182 6 : LOCK(mempool.cs);
183 24 : UniValue o(UniValue::VOBJ);
184 106 : BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx)
185 : {
186 14 : const uint256& hash = e.GetTx().GetHash();
187 42 : UniValue info(UniValue::VOBJ);
188 28 : info.push_back(Pair("size", (int)e.GetTxSize()));
189 28 : info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
190 28 : info.push_back(Pair("time", e.GetTime()));
191 28 : info.push_back(Pair("height", (int)e.GetHeight()));
192 28 : info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight())));
193 28 : info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height())));
194 28 : info.push_back(Pair("descendantcount", e.GetCountWithDescendants()));
195 28 : info.push_back(Pair("descendantsize", e.GetSizeWithDescendants()));
196 28 : info.push_back(Pair("descendantfees", e.GetFeesWithDescendants()));
197 14 : const CTransaction& tx = e.GetTx();
198 : set<string> setDepends;
199 268 : BOOST_FOREACH(const CTxIn& txin, tx.vin)
200 : {
201 33 : if (mempool.exists(txin.prevout.hash))
202 4 : setDepends.insert(txin.prevout.hash.ToString());
203 : }
204 :
205 56 : UniValue depends(UniValue::VARR);
206 96 : BOOST_FOREACH(const string& dep, setDepends)
207 : {
208 2 : depends.push_back(dep);
209 : }
210 :
211 28 : info.push_back(Pair("depends", depends));
212 42 : o.push_back(Pair(hash.ToString(), info));
213 14 : }
214 6 : return o;
215 : }
216 : else
217 : {
218 : vector<uint256> vtxid;
219 480 : mempool.queryHashes(vtxid);
220 :
221 1920 : UniValue a(UniValue::VARR);
222 6425 : BOOST_FOREACH(const uint256& hash, vtxid)
223 1418 : a.push_back(hash.ToString());
224 :
225 480 : return a;
226 : }
227 : }
228 :
229 485 : UniValue getrawmempool(const UniValue& params, bool fHelp)
230 : {
231 970 : if (fHelp || params.size() > 1)
232 : throw runtime_error(
233 : "getrawmempool ( verbose )\n"
234 : "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
235 : "\nArguments:\n"
236 : "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
237 : "\nResult: (for verbose = false):\n"
238 : "[ (json array of string)\n"
239 : " \"transactionid\" (string) The transaction id\n"
240 : " ,...\n"
241 : "]\n"
242 : "\nResult: (for verbose = true):\n"
243 : "{ (json object)\n"
244 : " \"transactionid\" : { (json object)\n"
245 : " \"size\" : n, (numeric) transaction size in bytes\n"
246 0 : " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
247 : " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
248 : " \"height\" : n, (numeric) block height when transaction entered pool\n"
249 : " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
250 : " \"currentpriority\" : n, (numeric) transaction priority now\n"
251 : " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n"
252 : " \"descendantsize\" : n, (numeric) size of in-mempool descendants (including this one)\n"
253 : " \"descendantfees\" : n, (numeric) fees of in-mempool descendants (including this one)\n"
254 : " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
255 : " \"transactionid\", (string) parent transaction id\n"
256 : " ... ]\n"
257 : " }, ...\n"
258 : "}\n"
259 : "\nExamples\n"
260 0 : + HelpExampleCli("getrawmempool", "true")
261 0 : + HelpExampleRpc("getrawmempool", "true")
262 0 : );
263 :
264 485 : LOCK(cs_main);
265 :
266 485 : bool fVerbose = false;
267 485 : if (params.size() > 0)
268 5 : fVerbose = params[0].get_bool();
269 :
270 970 : return mempoolToJSON(fVerbose);
271 : }
272 :
273 9 : UniValue getblockhash(const UniValue& params, bool fHelp)
274 : {
275 18 : if (fHelp || params.size() != 1)
276 : throw runtime_error(
277 : "getblockhash index\n"
278 : "\nReturns hash of block in best-block-chain at index provided.\n"
279 : "\nArguments:\n"
280 : "1. index (numeric, required) The block index\n"
281 : "\nResult:\n"
282 : "\"hash\" (string) The block hash\n"
283 : "\nExamples:\n"
284 0 : + HelpExampleCli("getblockhash", "1000")
285 0 : + HelpExampleRpc("getblockhash", "1000")
286 0 : );
287 :
288 9 : LOCK(cs_main);
289 :
290 9 : int nHeight = params[0].get_int();
291 18 : if (nHeight < 0 || nHeight > chainActive.Height())
292 0 : throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
293 :
294 9 : CBlockIndex* pblockindex = chainActive[nHeight];
295 36 : return pblockindex->GetBlockHash().GetHex();
296 : }
297 :
298 0 : UniValue getblockheader(const UniValue& params, bool fHelp)
299 : {
300 0 : if (fHelp || params.size() < 1 || params.size() > 2)
301 : throw runtime_error(
302 : "getblockheader \"hash\" ( verbose )\n"
303 : "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
304 : "If verbose is true, returns an Object with information about blockheader <hash>.\n"
305 : "\nArguments:\n"
306 : "1. \"hash\" (string, required) The block hash\n"
307 : "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
308 : "\nResult (for verbose = true):\n"
309 : "{\n"
310 : " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
311 : " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
312 : " \"height\" : n, (numeric) The block height or index\n"
313 : " \"version\" : n, (numeric) The block version\n"
314 : " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
315 : " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
316 : " \"nonce\" : n, (numeric) The nonce\n"
317 : " \"bits\" : \"1d00ffff\", (string) The bits\n"
318 : " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
319 : " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
320 : " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
321 : "}\n"
322 : "\nResult (for verbose=false):\n"
323 : "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
324 : "\nExamples:\n"
325 0 : + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
326 0 : + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
327 0 : );
328 :
329 0 : LOCK(cs_main);
330 :
331 0 : std::string strHash = params[0].get_str();
332 : uint256 hash(uint256S(strHash));
333 :
334 0 : bool fVerbose = true;
335 0 : if (params.size() > 1)
336 0 : fVerbose = params[1].get_bool();
337 :
338 0 : if (mapBlockIndex.count(hash) == 0)
339 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
340 :
341 0 : CBlockIndex* pblockindex = mapBlockIndex[hash];
342 :
343 0 : if (!fVerbose)
344 : {
345 : CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
346 0 : ssBlock << pblockindex->GetBlockHeader();
347 0 : std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
348 0 : return strHex;
349 : }
350 :
351 0 : return blockheaderToJSON(pblockindex);
352 : }
353 :
354 10 : UniValue getblock(const UniValue& params, bool fHelp)
355 : {
356 30 : if (fHelp || params.size() < 1 || params.size() > 2)
357 : throw runtime_error(
358 : "getblock \"hash\" ( verbose )\n"
359 : "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
360 : "If verbose is true, returns an Object with information about block <hash>.\n"
361 : "\nArguments:\n"
362 : "1. \"hash\" (string, required) The block hash\n"
363 : "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
364 : "\nResult (for verbose = true):\n"
365 : "{\n"
366 : " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
367 : " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
368 : " \"size\" : n, (numeric) The block size\n"
369 : " \"height\" : n, (numeric) The block height or index\n"
370 : " \"version\" : n, (numeric) The block version\n"
371 : " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
372 : " \"tx\" : [ (array of string) The transaction ids\n"
373 : " \"transactionid\" (string) The transaction id\n"
374 : " ,...\n"
375 : " ],\n"
376 : " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
377 : " \"nonce\" : n, (numeric) The nonce\n"
378 : " \"bits\" : \"1d00ffff\", (string) The bits\n"
379 : " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
380 : " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
381 : " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
382 : "}\n"
383 : "\nResult (for verbose=false):\n"
384 : "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
385 : "\nExamples:\n"
386 0 : + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
387 0 : + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
388 0 : );
389 :
390 10 : LOCK(cs_main);
391 :
392 10 : std::string strHash = params[0].get_str();
393 : uint256 hash(uint256S(strHash));
394 :
395 10 : bool fVerbose = true;
396 10 : if (params.size() > 1)
397 1 : fVerbose = params[1].get_bool();
398 :
399 10 : if (mapBlockIndex.count(hash) == 0)
400 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
401 :
402 10 : CBlock block;
403 10 : CBlockIndex* pblockindex = mapBlockIndex[hash];
404 :
405 10 : if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
406 0 : throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
407 :
408 10 : if(!ReadBlockFromDisk(block, pblockindex))
409 0 : throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
410 :
411 10 : if (!fVerbose)
412 : {
413 : CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
414 : ssBlock << block;
415 0 : std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
416 0 : return strHex;
417 : }
418 :
419 10 : return blockToJSON(block, pblockindex);
420 : }
421 :
422 0 : UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
423 : {
424 0 : if (fHelp || params.size() != 0)
425 : throw runtime_error(
426 : "gettxoutsetinfo\n"
427 : "\nReturns statistics about the unspent transaction output set.\n"
428 : "Note this call may take some time.\n"
429 : "\nResult:\n"
430 : "{\n"
431 : " \"height\":n, (numeric) The current block height (index)\n"
432 : " \"bestblock\": \"hex\", (string) the best block hash hex\n"
433 : " \"transactions\": n, (numeric) The number of transactions\n"
434 : " \"txouts\": n, (numeric) The number of output transactions\n"
435 : " \"bytes_serialized\": n, (numeric) The serialized size\n"
436 : " \"hash_serialized\": \"hash\", (string) The serialized hash\n"
437 : " \"total_amount\": x.xxx (numeric) The total amount\n"
438 : "}\n"
439 : "\nExamples:\n"
440 0 : + HelpExampleCli("gettxoutsetinfo", "")
441 0 : + HelpExampleRpc("gettxoutsetinfo", "")
442 0 : );
443 :
444 0 : UniValue ret(UniValue::VOBJ);
445 :
446 0 : CCoinsStats stats;
447 0 : FlushStateToDisk();
448 0 : if (pcoinsTip->GetStats(stats)) {
449 0 : ret.push_back(Pair("height", (int64_t)stats.nHeight));
450 0 : ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
451 0 : ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
452 0 : ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
453 0 : ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
454 0 : ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
455 0 : ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
456 : }
457 0 : return ret;
458 : }
459 :
460 0 : UniValue gettxout(const UniValue& params, bool fHelp)
461 : {
462 0 : if (fHelp || params.size() < 2 || params.size() > 3)
463 : throw runtime_error(
464 : "gettxout \"txid\" n ( includemempool )\n"
465 : "\nReturns details about an unspent transaction output.\n"
466 : "\nArguments:\n"
467 : "1. \"txid\" (string, required) The transaction id\n"
468 : "2. n (numeric, required) vout value\n"
469 : "3. includemempool (boolean, optional) Whether to included the mem pool\n"
470 : "\nResult:\n"
471 : "{\n"
472 : " \"bestblock\" : \"hash\", (string) the block hash\n"
473 : " \"confirmations\" : n, (numeric) The number of confirmations\n"
474 0 : " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n"
475 : " \"scriptPubKey\" : { (json object)\n"
476 : " \"asm\" : \"code\", (string) \n"
477 : " \"hex\" : \"hex\", (string) \n"
478 : " \"reqSigs\" : n, (numeric) Number of required signatures\n"
479 : " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
480 : " \"addresses\" : [ (array of string) array of bitcoin addresses\n"
481 : " \"bitcoinaddress\" (string) bitcoin address\n"
482 : " ,...\n"
483 : " ]\n"
484 : " },\n"
485 : " \"version\" : n, (numeric) The version\n"
486 : " \"coinbase\" : true|false (boolean) Coinbase or not\n"
487 : "}\n"
488 :
489 : "\nExamples:\n"
490 : "\nGet unspent transactions\n"
491 0 : + HelpExampleCli("listunspent", "") +
492 : "\nView the details\n"
493 0 : + HelpExampleCli("gettxout", "\"txid\" 1") +
494 : "\nAs a json rpc call\n"
495 0 : + HelpExampleRpc("gettxout", "\"txid\", 1")
496 0 : );
497 :
498 0 : LOCK(cs_main);
499 :
500 0 : UniValue ret(UniValue::VOBJ);
501 :
502 0 : std::string strHash = params[0].get_str();
503 : uint256 hash(uint256S(strHash));
504 0 : int n = params[1].get_int();
505 0 : bool fMempool = true;
506 0 : if (params.size() > 2)
507 0 : fMempool = params[2].get_bool();
508 :
509 0 : CCoins coins;
510 0 : if (fMempool) {
511 0 : LOCK(mempool.cs);
512 0 : CCoinsViewMemPool view(pcoinsTip, mempool);
513 0 : if (!view.GetCoins(hash, coins))
514 0 : return NullUniValue;
515 0 : mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
516 : } else {
517 0 : if (!pcoinsTip->GetCoins(hash, coins))
518 0 : return NullUniValue;
519 : }
520 0 : if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
521 0 : return NullUniValue;
522 :
523 0 : BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
524 0 : CBlockIndex *pindex = it->second;
525 0 : ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
526 0 : if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
527 0 : ret.push_back(Pair("confirmations", 0));
528 : else
529 0 : ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
530 0 : ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
531 0 : UniValue o(UniValue::VOBJ);
532 0 : ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
533 0 : ret.push_back(Pair("scriptPubKey", o));
534 0 : ret.push_back(Pair("version", coins.nVersion));
535 0 : ret.push_back(Pair("coinbase", coins.fCoinBase));
536 :
537 0 : return ret;
538 : }
539 :
540 0 : UniValue verifychain(const UniValue& params, bool fHelp)
541 : {
542 0 : if (fHelp || params.size() > 2)
543 : throw runtime_error(
544 : "verifychain ( checklevel numblocks )\n"
545 : "\nVerifies blockchain database.\n"
546 : "\nArguments:\n"
547 : "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
548 : "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
549 : "\nResult:\n"
550 : "true|false (boolean) Verified or not\n"
551 : "\nExamples:\n"
552 0 : + HelpExampleCli("verifychain", "")
553 0 : + HelpExampleRpc("verifychain", "")
554 0 : );
555 :
556 0 : LOCK(cs_main);
557 :
558 0 : int nCheckLevel = GetArg("-checklevel", 3);
559 0 : int nCheckDepth = GetArg("-checkblocks", 288);
560 0 : if (params.size() > 0)
561 0 : nCheckLevel = params[0].get_int();
562 0 : if (params.size() > 1)
563 0 : nCheckDepth = params[1].get_int();
564 :
565 0 : return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
566 : }
567 :
568 : /** Implementation of IsSuperMajority with better feedback */
569 4 : static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
570 : {
571 0 : int nFound = 0;
572 0 : CBlockIndex* pstart = pindex;
573 440 : for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
574 : {
575 440 : if (pstart->nVersion >= minVersion)
576 436 : ++nFound;
577 440 : pstart = pstart->pprev;
578 : }
579 :
580 12 : UniValue rv(UniValue::VOBJ);
581 8 : rv.push_back(Pair("status", nFound >= nRequired));
582 8 : rv.push_back(Pair("found", nFound));
583 8 : rv.push_back(Pair("required", nRequired));
584 8 : rv.push_back(Pair("window", consensusParams.nMajorityWindow));
585 4 : return rv;
586 : }
587 :
588 2 : static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
589 : {
590 6 : UniValue rv(UniValue::VOBJ);
591 6 : rv.push_back(Pair("id", name));
592 4 : rv.push_back(Pair("version", version));
593 4 : rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
594 4 : rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
595 2 : return rv;
596 : }
597 :
598 1 : UniValue getblockchaininfo(const UniValue& params, bool fHelp)
599 : {
600 2 : if (fHelp || params.size() != 0)
601 : throw runtime_error(
602 : "getblockchaininfo\n"
603 : "Returns an object containing various state info regarding block chain processing.\n"
604 : "\nResult:\n"
605 : "{\n"
606 : " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
607 : " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
608 : " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
609 : " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
610 : " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
611 : " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
612 : " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
613 : " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n"
614 : " \"pruneheight\": xxxxxx, (numeric) heighest block available\n"
615 : " \"softforks\": [ (array) status of softforks in progress\n"
616 : " {\n"
617 : " \"id\": \"xxxx\", (string) name of softfork\n"
618 : " \"version\": xx, (numeric) block version\n"
619 : " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n"
620 : " \"status\": xx, (boolean) true if threshold reached\n"
621 : " \"found\": xx, (numeric) number of blocks with the new version found\n"
622 : " \"required\": xx, (numeric) number of blocks required to trigger\n"
623 : " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n"
624 : " },\n"
625 : " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
626 : " }, ...\n"
627 : " ]\n"
628 : "}\n"
629 : "\nExamples:\n"
630 0 : + HelpExampleCli("getblockchaininfo", "")
631 0 : + HelpExampleRpc("getblockchaininfo", "")
632 0 : );
633 :
634 1 : LOCK(cs_main);
635 :
636 3 : UniValue obj(UniValue::VOBJ);
637 4 : obj.push_back(Pair("chain", Params().NetworkIDString()));
638 2 : obj.push_back(Pair("blocks", (int)chainActive.Height()));
639 2 : obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
640 4 : obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
641 2 : obj.push_back(Pair("difficulty", (double)GetDifficulty()));
642 3 : obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
643 3 : obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
644 2 : obj.push_back(Pair("pruned", fPruneMode));
645 :
646 2 : const Consensus::Params& consensusParams = Params().GetConsensus();
647 1 : CBlockIndex* tip = chainActive.Tip();
648 4 : UniValue softforks(UniValue::VARR);
649 3 : softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
650 3 : softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
651 2 : obj.push_back(Pair("softforks", softforks));
652 :
653 1 : if (fPruneMode)
654 : {
655 0 : CBlockIndex *block = chainActive.Tip();
656 0 : while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
657 : block = block->pprev;
658 :
659 0 : obj.push_back(Pair("pruneheight", block->nHeight));
660 : }
661 1 : return obj;
662 : }
663 :
664 : /** Comparison function for sorting the getchaintips heads. */
665 : struct CompareBlocksByHeight
666 : {
667 0 : bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
668 : {
669 : /* Make sure that unequal blocks with the same height do not compare
670 : equal. Use the pointers themselves to make a distinction. */
671 :
672 24482 : if (a->nHeight != b->nHeight)
673 21921 : return (a->nHeight > b->nHeight);
674 :
675 2561 : return a < b;
676 : }
677 : };
678 :
679 6 : UniValue getchaintips(const UniValue& params, bool fHelp)
680 : {
681 12 : if (fHelp || params.size() != 0)
682 : throw runtime_error(
683 : "getchaintips\n"
684 : "Return information about all known tips in the block tree,"
685 : " including the main chain as well as orphaned branches.\n"
686 : "\nResult:\n"
687 : "[\n"
688 : " {\n"
689 : " \"height\": xxxx, (numeric) height of the chain tip\n"
690 : " \"hash\": \"xxxx\", (string) block hash of the tip\n"
691 : " \"branchlen\": 0 (numeric) zero for main chain\n"
692 : " \"status\": \"active\" (string) \"active\" for the main chain\n"
693 : " },\n"
694 : " {\n"
695 : " \"height\": xxxx,\n"
696 : " \"hash\": \"xxxx\",\n"
697 : " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
698 : " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
699 : " }\n"
700 : "]\n"
701 : "Possible values for status:\n"
702 : "1. \"invalid\" This branch contains at least one invalid block\n"
703 : "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
704 : "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
705 : "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
706 : "5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
707 : "\nExamples:\n"
708 0 : + HelpExampleCli("getchaintips", "")
709 0 : + HelpExampleRpc("getchaintips", "")
710 0 : );
711 :
712 6 : LOCK(cs_main);
713 :
714 : /* Build up a list of chain tips. We start with the list of all
715 : known blocks, and successively remove blocks that appear as pprev
716 : of another block. */
717 : std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
718 6366 : BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
719 2532 : setTips.insert(item.second);
720 6366 : BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
721 : {
722 1266 : const CBlockIndex* pprev = item.second->pprev;
723 1266 : if (pprev)
724 : setTips.erase(pprev);
725 : }
726 :
727 : // Always report the currently active tip.
728 12 : setTips.insert(chainActive.Tip());
729 :
730 : /* Construct the output array. */
731 18 : UniValue res(UniValue::VARR);
732 71 : BOOST_FOREACH(const CBlockIndex* block, setTips)
733 : {
734 21 : UniValue obj(UniValue::VOBJ);
735 14 : obj.push_back(Pair("height", block->nHeight));
736 21 : obj.push_back(Pair("hash", block->phashBlock->GetHex()));
737 :
738 7 : const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
739 14 : obj.push_back(Pair("branchlen", branchLen));
740 :
741 : string status;
742 7 : if (chainActive.Contains(block)) {
743 : // This block is part of the currently active chain.
744 : status = "active";
745 1 : } else if (block->nStatus & BLOCK_FAILED_MASK) {
746 : // This block or one of its ancestors is invalid.
747 : status = "invalid";
748 1 : } else if (block->nChainTx == 0) {
749 : // This block cannot be connected because full block data for it or one of its parents is missing.
750 : status = "headers-only";
751 1 : } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
752 : // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
753 : status = "valid-fork";
754 0 : } else if (block->IsValid(BLOCK_VALID_TREE)) {
755 : // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
756 : status = "valid-headers";
757 : } else {
758 : // No clue.
759 : status = "unknown";
760 : }
761 21 : obj.push_back(Pair("status", status));
762 :
763 7 : res.push_back(obj);
764 7 : }
765 :
766 6 : return res;
767 : }
768 :
769 1 : UniValue mempoolInfoToJSON()
770 : {
771 3 : UniValue ret(UniValue::VOBJ);
772 2 : ret.push_back(Pair("size", (int64_t) mempool.size()));
773 2 : ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
774 2 : ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
775 :
776 1 : return ret;
777 : }
778 :
779 0 : UniValue getmempoolinfo(const UniValue& params, bool fHelp)
780 : {
781 0 : if (fHelp || params.size() != 0)
782 : throw runtime_error(
783 : "getmempoolinfo\n"
784 : "\nReturns details on the active state of the TX memory pool.\n"
785 : "\nResult:\n"
786 : "{\n"
787 : " \"size\": xxxxx (numeric) Current tx count\n"
788 : " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n"
789 : " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n"
790 : "}\n"
791 : "\nExamples:\n"
792 0 : + HelpExampleCli("getmempoolinfo", "")
793 0 : + HelpExampleRpc("getmempoolinfo", "")
794 0 : );
795 :
796 0 : return mempoolInfoToJSON();
797 : }
798 :
799 3 : UniValue invalidateblock(const UniValue& params, bool fHelp)
800 : {
801 6 : if (fHelp || params.size() != 1)
802 : throw runtime_error(
803 : "invalidateblock \"hash\"\n"
804 : "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
805 : "\nArguments:\n"
806 : "1. hash (string, required) the hash of the block to mark as invalid\n"
807 : "\nResult:\n"
808 : "\nExamples:\n"
809 0 : + HelpExampleCli("invalidateblock", "\"blockhash\"")
810 0 : + HelpExampleRpc("invalidateblock", "\"blockhash\"")
811 0 : );
812 :
813 3 : std::string strHash = params[0].get_str();
814 : uint256 hash(uint256S(strHash));
815 3 : CValidationState state;
816 :
817 : {
818 3 : LOCK(cs_main);
819 3 : if (mapBlockIndex.count(hash) == 0)
820 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
821 :
822 3 : CBlockIndex* pblockindex = mapBlockIndex[hash];
823 3 : InvalidateBlock(state, pblockindex);
824 : }
825 :
826 3 : if (state.IsValid()) {
827 3 : ActivateBestChain(state);
828 : }
829 :
830 3 : if (!state.IsValid()) {
831 0 : throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
832 : }
833 :
834 6 : return NullUniValue;
835 : }
836 :
837 0 : UniValue reconsiderblock(const UniValue& params, bool fHelp)
838 : {
839 0 : if (fHelp || params.size() != 1)
840 : throw runtime_error(
841 : "reconsiderblock \"hash\"\n"
842 : "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
843 : "This can be used to undo the effects of invalidateblock.\n"
844 : "\nArguments:\n"
845 : "1. hash (string, required) the hash of the block to reconsider\n"
846 : "\nResult:\n"
847 : "\nExamples:\n"
848 0 : + HelpExampleCli("reconsiderblock", "\"blockhash\"")
849 0 : + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
850 0 : );
851 :
852 0 : std::string strHash = params[0].get_str();
853 : uint256 hash(uint256S(strHash));
854 0 : CValidationState state;
855 :
856 : {
857 0 : LOCK(cs_main);
858 0 : if (mapBlockIndex.count(hash) == 0)
859 0 : throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
860 :
861 0 : CBlockIndex* pblockindex = mapBlockIndex[hash];
862 0 : ReconsiderBlock(state, pblockindex);
863 : }
864 :
865 0 : if (state.IsValid()) {
866 0 : ActivateBestChain(state);
867 : }
868 :
869 0 : if (!state.IsValid()) {
870 0 : throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
871 : }
872 :
873 0 : return NullUniValue;
874 288 : }
|