1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 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 "policy/policy.h"
14 #include "primitives/transaction.h"
15 #include "rpc/server.h"
16 #include "streams.h"
17 #include "sync.h"
18 #include "txmempool.h"
19 #include "util.h"
20 #include "utilstrencodings.h"
21 #include "hash.h"
22 
23 #include <stdint.h>
24 
25 #include <univalue.h>
26 
27 #include <boost/thread/thread.hpp> // boost::thread::interrupt
28 
29 using namespace std;
30 
31 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
32 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
33 
GetDifficulty(const CBlockIndex * blockindex)34 double GetDifficulty(const CBlockIndex* blockindex)
35 {
36     // Floating point number that is a multiple of the minimum difficulty,
37     // minimum difficulty = 1.0.
38     if (blockindex == NULL)
39     {
40         if (chainActive.Tip() == NULL)
41             return 1.0;
42         else
43             blockindex = chainActive.Tip();
44     }
45 
46     int nShift = (blockindex->nBits >> 24) & 0xff;
47 
48     double dDiff =
49         (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
50 
51     while (nShift < 29)
52     {
53         dDiff *= 256.0;
54         nShift++;
55     }
56     while (nShift > 29)
57     {
58         dDiff /= 256.0;
59         nShift--;
60     }
61 
62     return dDiff;
63 }
64 
blockheaderToJSON(const CBlockIndex * blockindex)65 UniValue blockheaderToJSON(const CBlockIndex* blockindex)
66 {
67     UniValue result(UniValue::VOBJ);
68     result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
69     int confirmations = -1;
70     // Only report confirmations if the block is on the main chain
71     if (chainActive.Contains(blockindex))
72         confirmations = chainActive.Height() - blockindex->nHeight + 1;
73     result.push_back(Pair("confirmations", confirmations));
74     result.push_back(Pair("height", blockindex->nHeight));
75     result.push_back(Pair("version", blockindex->nVersion));
76     result.push_back(Pair("versionHex", strprintf("%08x", blockindex->nVersion)));
77     result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
78     result.push_back(Pair("time", (int64_t)blockindex->nTime));
79     result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
80     result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce));
81     result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
82     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
83     result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
84 
85     if (blockindex->pprev)
86         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
87     CBlockIndex *pnext = chainActive.Next(blockindex);
88     if (pnext)
89         result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
90     return result;
91 }
92 
blockToJSON(const CBlock & block,const CBlockIndex * blockindex,bool txDetails=false)93 UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
94 {
95     UniValue result(UniValue::VOBJ);
96     result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
97     int confirmations = -1;
98     // Only report confirmations if the block is on the main chain
99     if (chainActive.Contains(blockindex))
100         confirmations = chainActive.Height() - blockindex->nHeight + 1;
101     result.push_back(Pair("confirmations", confirmations));
102     result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)));
103     result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
104     result.push_back(Pair("weight", (int)::GetBlockWeight(block)));
105     result.push_back(Pair("height", blockindex->nHeight));
106     result.push_back(Pair("version", block.nVersion));
107     result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
108     result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
109     UniValue txs(UniValue::VARR);
110     BOOST_FOREACH(const CTransaction&tx, block.vtx)
111     {
112         if(txDetails)
113         {
114             UniValue objTx(UniValue::VOBJ);
115             TxToJSON(tx, uint256(), objTx);
116             txs.push_back(objTx);
117         }
118         else
119             txs.push_back(tx.GetHash().GetHex());
120     }
121     result.push_back(Pair("tx", txs));
122     result.push_back(Pair("time", block.GetBlockTime()));
123     result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
124     result.push_back(Pair("nonce", (uint64_t)block.nNonce));
125     result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
126     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
127     result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
128 
129     if (blockindex->pprev)
130         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
131     CBlockIndex *pnext = chainActive.Next(blockindex);
132     if (pnext)
133         result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
134     return result;
135 }
136 
getblockcount(const UniValue & params,bool fHelp)137 UniValue getblockcount(const UniValue& params, bool fHelp)
138 {
139     if (fHelp || params.size() != 0)
140         throw runtime_error(
141             "getblockcount\n"
142             "\nReturns the number of blocks in the longest block chain.\n"
143             "\nResult:\n"
144             "n    (numeric) The current block count\n"
145             "\nExamples:\n"
146             + HelpExampleCli("getblockcount", "")
147             + HelpExampleRpc("getblockcount", "")
148         );
149 
150     LOCK(cs_main);
151     return chainActive.Height();
152 }
153 
getbestblockhash(const UniValue & params,bool fHelp)154 UniValue getbestblockhash(const UniValue& params, bool fHelp)
155 {
156     if (fHelp || params.size() != 0)
157         throw runtime_error(
158             "getbestblockhash\n"
159             "\nReturns the hash of the best (tip) block in the longest block chain.\n"
160             "\nResult\n"
161             "\"hex\"      (string) the block hash hex encoded\n"
162             "\nExamples\n"
163             + HelpExampleCli("getbestblockhash", "")
164             + HelpExampleRpc("getbestblockhash", "")
165         );
166 
167     LOCK(cs_main);
168     return chainActive.Tip()->GetBlockHash().GetHex();
169 }
170 
getdifficulty(const UniValue & params,bool fHelp)171 UniValue getdifficulty(const UniValue& params, bool fHelp)
172 {
173     if (fHelp || params.size() != 0)
174         throw runtime_error(
175             "getdifficulty\n"
176             "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
177             "\nResult:\n"
178             "n.nnn       (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
179             "\nExamples:\n"
180             + HelpExampleCli("getdifficulty", "")
181             + HelpExampleRpc("getdifficulty", "")
182         );
183 
184     LOCK(cs_main);
185     return GetDifficulty();
186 }
187 
EntryDescriptionString()188 std::string EntryDescriptionString()
189 {
190     return "    \"size\" : n,             (numeric) transaction size in bytes\n"
191            "    \"fee\" : n,              (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
192            "    \"modifiedfee\" : n,      (numeric) transaction fee with fee deltas used for mining priority\n"
193            "    \"time\" : n,             (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
194            "    \"height\" : n,           (numeric) block height when transaction entered pool\n"
195            "    \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
196            "    \"currentpriority\" : n,  (numeric) transaction priority now\n"
197            "    \"descendantcount\" : n,  (numeric) number of in-mempool descendant transactions (including this one)\n"
198            "    \"descendantsize\" : n,   (numeric) size of in-mempool descendants (including this one)\n"
199            "    \"descendantfees\" : n,   (numeric) modified fees (see above) of in-mempool descendants (including this one)\n"
200            "    \"ancestorcount\" : n,    (numeric) number of in-mempool ancestor transactions (including this one)\n"
201            "    \"ancestorsize\" : n,     (numeric) size of in-mempool ancestors (including this one)\n"
202            "    \"ancestorfees\" : n,     (numeric) modified fees (see above) of in-mempool ancestors (including this one)\n"
203            "    \"depends\" : [           (array) unconfirmed transactions used as inputs for this transaction\n"
204            "        \"transactionid\",    (string) parent transaction id\n"
205            "       ... ]\n";
206 }
207 
entryToJSON(UniValue & info,const CTxMemPoolEntry & e)208 void entryToJSON(UniValue &info, const CTxMemPoolEntry &e)
209 {
210     AssertLockHeld(mempool.cs);
211 
212     info.push_back(Pair("size", (int)e.GetTxSize()));
213     info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
214     info.push_back(Pair("modifiedfee", ValueFromAmount(e.GetModifiedFee())));
215     info.push_back(Pair("time", e.GetTime()));
216     info.push_back(Pair("height", (int)e.GetHeight()));
217     info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight())));
218     info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height())));
219     info.push_back(Pair("descendantcount", e.GetCountWithDescendants()));
220     info.push_back(Pair("descendantsize", e.GetSizeWithDescendants()));
221     info.push_back(Pair("descendantfees", e.GetModFeesWithDescendants()));
222     info.push_back(Pair("ancestorcount", e.GetCountWithAncestors()));
223     info.push_back(Pair("ancestorsize", e.GetSizeWithAncestors()));
224     info.push_back(Pair("ancestorfees", e.GetModFeesWithAncestors()));
225     const CTransaction& tx = e.GetTx();
226     set<string> setDepends;
227     BOOST_FOREACH(const CTxIn& txin, tx.vin)
228     {
229         if (mempool.exists(txin.prevout.hash))
230             setDepends.insert(txin.prevout.hash.ToString());
231     }
232 
233     UniValue depends(UniValue::VARR);
234     BOOST_FOREACH(const string& dep, setDepends)
235     {
236         depends.push_back(dep);
237     }
238 
239     info.push_back(Pair("depends", depends));
240 }
241 
mempoolToJSON(bool fVerbose=false)242 UniValue mempoolToJSON(bool fVerbose = false)
243 {
244     if (fVerbose)
245     {
246         LOCK(mempool.cs);
247         UniValue o(UniValue::VOBJ);
248         BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx)
249         {
250             const uint256& hash = e.GetTx().GetHash();
251             UniValue info(UniValue::VOBJ);
252             entryToJSON(info, e);
253             o.push_back(Pair(hash.ToString(), info));
254         }
255         return o;
256     }
257     else
258     {
259         vector<uint256> vtxid;
260         mempool.queryHashes(vtxid);
261 
262         UniValue a(UniValue::VARR);
263         BOOST_FOREACH(const uint256& hash, vtxid)
264             a.push_back(hash.ToString());
265 
266         return a;
267     }
268 }
269 
getrawmempool(const UniValue & params,bool fHelp)270 UniValue getrawmempool(const UniValue& params, bool fHelp)
271 {
272     if (fHelp || params.size() > 1)
273         throw runtime_error(
274             "getrawmempool ( verbose )\n"
275             "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
276             "\nArguments:\n"
277             "1. verbose           (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
278             "\nResult: (for verbose = false):\n"
279             "[                     (json array of string)\n"
280             "  \"transactionid\"     (string) The transaction id\n"
281             "  ,...\n"
282             "]\n"
283             "\nResult: (for verbose = true):\n"
284             "{                           (json object)\n"
285             "  \"transactionid\" : {       (json object)\n"
286             + EntryDescriptionString()
287             + "  }, ...\n"
288             "}\n"
289             "\nExamples\n"
290             + HelpExampleCli("getrawmempool", "true")
291             + HelpExampleRpc("getrawmempool", "true")
292         );
293 
294     bool fVerbose = false;
295     if (params.size() > 0)
296         fVerbose = params[0].get_bool();
297 
298     return mempoolToJSON(fVerbose);
299 }
300 
getmempoolancestors(const UniValue & params,bool fHelp)301 UniValue getmempoolancestors(const UniValue& params, bool fHelp)
302 {
303     if (fHelp || params.size() < 1 || params.size() > 2) {
304         throw runtime_error(
305             "getmempoolancestors txid (verbose)\n"
306             "\nIf txid is in the mempool, returns all in-mempool ancestors.\n"
307             "\nArguments:\n"
308             "1. \"txid\"                   (string, required) The transaction id (must be in mempool)\n"
309             "2. verbose                  (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
310             "\nResult (for verbose=false):\n"
311             "[                       (json array of strings)\n"
312             "  \"transactionid\"           (string) The transaction id of an in-mempool ancestor transaction\n"
313             "  ,...\n"
314             "]\n"
315             "\nResult (for verbose=true):\n"
316             "{                           (json object)\n"
317             "  \"transactionid\" : {       (json object)\n"
318             + EntryDescriptionString()
319             + "  }, ...\n"
320             "}\n"
321             "\nExamples\n"
322             + HelpExampleCli("getmempoolancestors", "\"mytxid\"")
323             + HelpExampleRpc("getmempoolancestors", "\"mytxid\"")
324             );
325     }
326 
327     bool fVerbose = false;
328     if (params.size() > 1)
329         fVerbose = params[1].get_bool();
330 
331     uint256 hash = ParseHashV(params[0], "parameter 1");
332 
333     LOCK(mempool.cs);
334 
335     CTxMemPool::txiter it = mempool.mapTx.find(hash);
336     if (it == mempool.mapTx.end()) {
337         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
338     }
339 
340     CTxMemPool::setEntries setAncestors;
341     uint64_t noLimit = std::numeric_limits<uint64_t>::max();
342     std::string dummy;
343     mempool.CalculateMemPoolAncestors(*it, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
344 
345     if (!fVerbose) {
346         UniValue o(UniValue::VARR);
347         BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) {
348             o.push_back(ancestorIt->GetTx().GetHash().ToString());
349         }
350 
351         return o;
352     } else {
353         UniValue o(UniValue::VOBJ);
354         BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) {
355             const CTxMemPoolEntry &e = *ancestorIt;
356             const uint256& hash = e.GetTx().GetHash();
357             UniValue info(UniValue::VOBJ);
358             entryToJSON(info, e);
359             o.push_back(Pair(hash.ToString(), info));
360         }
361         return o;
362     }
363 }
364 
getmempooldescendants(const UniValue & params,bool fHelp)365 UniValue getmempooldescendants(const UniValue& params, bool fHelp)
366 {
367     if (fHelp || params.size() < 1 || params.size() > 2) {
368         throw runtime_error(
369             "getmempooldescendants txid (verbose)\n"
370             "\nIf txid is in the mempool, returns all in-mempool descendants.\n"
371             "\nArguments:\n"
372             "1. \"txid\"                   (string, required) The transaction id (must be in mempool)\n"
373             "2. verbose                  (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
374             "\nResult (for verbose=false):\n"
375             "[                       (json array of strings)\n"
376             "  \"transactionid\"           (string) The transaction id of an in-mempool descendant transaction\n"
377             "  ,...\n"
378             "]\n"
379             "\nResult (for verbose=true):\n"
380             "{                           (json object)\n"
381             "  \"transactionid\" : {       (json object)\n"
382             + EntryDescriptionString()
383             + "  }, ...\n"
384             "}\n"
385             "\nExamples\n"
386             + HelpExampleCli("getmempooldescendants", "\"mytxid\"")
387             + HelpExampleRpc("getmempooldescendants", "\"mytxid\"")
388             );
389     }
390 
391     bool fVerbose = false;
392     if (params.size() > 1)
393         fVerbose = params[1].get_bool();
394 
395     uint256 hash = ParseHashV(params[0], "parameter 1");
396 
397     LOCK(mempool.cs);
398 
399     CTxMemPool::txiter it = mempool.mapTx.find(hash);
400     if (it == mempool.mapTx.end()) {
401         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
402     }
403 
404     CTxMemPool::setEntries setDescendants;
405     mempool.CalculateDescendants(it, setDescendants);
406     // CTxMemPool::CalculateDescendants will include the given tx
407     setDescendants.erase(it);
408 
409     if (!fVerbose) {
410         UniValue o(UniValue::VARR);
411         BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) {
412             o.push_back(descendantIt->GetTx().GetHash().ToString());
413         }
414 
415         return o;
416     } else {
417         UniValue o(UniValue::VOBJ);
418         BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) {
419             const CTxMemPoolEntry &e = *descendantIt;
420             const uint256& hash = e.GetTx().GetHash();
421             UniValue info(UniValue::VOBJ);
422             entryToJSON(info, e);
423             o.push_back(Pair(hash.ToString(), info));
424         }
425         return o;
426     }
427 }
428 
getmempoolentry(const UniValue & params,bool fHelp)429 UniValue getmempoolentry(const UniValue& params, bool fHelp)
430 {
431     if (fHelp || params.size() != 1) {
432         throw runtime_error(
433             "getmempoolentry txid\n"
434             "\nReturns mempool data for given transaction\n"
435             "\nArguments:\n"
436             "1. \"txid\"                   (string, required) The transaction id (must be in mempool)\n"
437             "\nResult:\n"
438             "{                           (json object)\n"
439             + EntryDescriptionString()
440             + "}\n"
441             "\nExamples\n"
442             + HelpExampleCli("getmempoolentry", "\"mytxid\"")
443             + HelpExampleRpc("getmempoolentry", "\"mytxid\"")
444         );
445     }
446 
447     uint256 hash = ParseHashV(params[0], "parameter 1");
448 
449     LOCK(mempool.cs);
450 
451     CTxMemPool::txiter it = mempool.mapTx.find(hash);
452     if (it == mempool.mapTx.end()) {
453         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool");
454     }
455 
456     const CTxMemPoolEntry &e = *it;
457     UniValue info(UniValue::VOBJ);
458     entryToJSON(info, e);
459     return info;
460 }
461 
getblockhash(const UniValue & params,bool fHelp)462 UniValue getblockhash(const UniValue& params, bool fHelp)
463 {
464     if (fHelp || params.size() != 1)
465         throw runtime_error(
466             "getblockhash index\n"
467             "\nReturns hash of block in best-block-chain at index provided.\n"
468             "\nArguments:\n"
469             "1. index         (numeric, required) The block index\n"
470             "\nResult:\n"
471             "\"hash\"         (string) The block hash\n"
472             "\nExamples:\n"
473             + HelpExampleCli("getblockhash", "1000")
474             + HelpExampleRpc("getblockhash", "1000")
475         );
476 
477     LOCK(cs_main);
478 
479     int nHeight = params[0].get_int();
480     if (nHeight < 0 || nHeight > chainActive.Height())
481         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
482 
483     CBlockIndex* pblockindex = chainActive[nHeight];
484     return pblockindex->GetBlockHash().GetHex();
485 }
486 
getblockheader(const UniValue & params,bool fHelp)487 UniValue getblockheader(const UniValue& params, bool fHelp)
488 {
489     if (fHelp || params.size() < 1 || params.size() > 2)
490         throw runtime_error(
491             "getblockheader \"hash\" ( verbose )\n"
492             "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
493             "If verbose is true, returns an Object with information about blockheader <hash>.\n"
494             "\nArguments:\n"
495             "1. \"hash\"          (string, required) The block hash\n"
496             "2. verbose           (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
497             "\nResult (for verbose = true):\n"
498             "{\n"
499             "  \"hash\" : \"hash\",     (string) the block hash (same as provided)\n"
500             "  \"confirmations\" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
501             "  \"height\" : n,          (numeric) The block height or index\n"
502             "  \"version\" : n,         (numeric) The block version\n"
503             "  \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
504             "  \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
505             "  \"time\" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
506             "  \"mediantime\" : ttt,    (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
507             "  \"nonce\" : n,           (numeric) The nonce\n"
508             "  \"bits\" : \"1d00ffff\", (string) The bits\n"
509             "  \"difficulty\" : x.xxx,  (numeric) The difficulty\n"
510             "  \"previousblockhash\" : \"hash\",  (string) The hash of the previous block\n"
511             "  \"nextblockhash\" : \"hash\",      (string) The hash of the next block\n"
512             "  \"chainwork\" : \"0000...1f3\"     (string) Expected number of hashes required to produce the current chain (in hex)\n"
513             "}\n"
514             "\nResult (for verbose=false):\n"
515             "\"data\"             (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
516             "\nExamples:\n"
517             + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
518             + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
519         );
520 
521     LOCK(cs_main);
522 
523     std::string strHash = params[0].get_str();
524     uint256 hash(uint256S(strHash));
525 
526     bool fVerbose = true;
527     if (params.size() > 1)
528         fVerbose = params[1].get_bool();
529 
530     if (mapBlockIndex.count(hash) == 0)
531         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
532 
533     CBlockIndex* pblockindex = mapBlockIndex[hash];
534 
535     if (!fVerbose)
536     {
537         CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
538         ssBlock << pblockindex->GetBlockHeader();
539         std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
540         return strHex;
541     }
542 
543     return blockheaderToJSON(pblockindex);
544 }
545 
getblock(const UniValue & params,bool fHelp)546 UniValue getblock(const UniValue& params, bool fHelp)
547 {
548     if (fHelp || params.size() < 1 || params.size() > 2)
549         throw runtime_error(
550             "getblock \"hash\" ( verbose )\n"
551             "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
552             "If verbose is true, returns an Object with information about block <hash>.\n"
553             "\nArguments:\n"
554             "1. \"hash\"          (string, required) The block hash\n"
555             "2. verbose           (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
556             "\nResult (for verbose = true):\n"
557             "{\n"
558             "  \"hash\" : \"hash\",     (string) the block hash (same as provided)\n"
559             "  \"confirmations\" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
560             "  \"size\" : n,            (numeric) The block size\n"
561             "  \"strippedsize\" : n,    (numeric) The block size excluding witness data\n"
562             "  \"weight\" : n           (numeric) The block weight (BIP 141)\n"
563             "  \"height\" : n,          (numeric) The block height or index\n"
564             "  \"version\" : n,         (numeric) The block version\n"
565             "  \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
566             "  \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
567             "  \"tx\" : [               (array of string) The transaction ids\n"
568             "     \"transactionid\"     (string) The transaction id\n"
569             "     ,...\n"
570             "  ],\n"
571             "  \"time\" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
572             "  \"mediantime\" : ttt,    (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
573             "  \"nonce\" : n,           (numeric) The nonce\n"
574             "  \"bits\" : \"1d00ffff\", (string) The bits\n"
575             "  \"difficulty\" : x.xxx,  (numeric) The difficulty\n"
576             "  \"chainwork\" : \"xxxx\",  (string) Expected number of hashes required to produce the chain up to this block (in hex)\n"
577             "  \"previousblockhash\" : \"hash\",  (string) The hash of the previous block\n"
578             "  \"nextblockhash\" : \"hash\"       (string) The hash of the next block\n"
579             "}\n"
580             "\nResult (for verbose=false):\n"
581             "\"data\"             (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
582             "\nExamples:\n"
583             + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
584             + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
585         );
586 
587     LOCK(cs_main);
588 
589     std::string strHash = params[0].get_str();
590     uint256 hash(uint256S(strHash));
591 
592     bool fVerbose = true;
593     if (params.size() > 1)
594         fVerbose = params[1].get_bool();
595 
596     if (mapBlockIndex.count(hash) == 0)
597         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
598 
599     CBlock block;
600     CBlockIndex* pblockindex = mapBlockIndex[hash];
601 
602     if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
603         throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
604 
605     if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
606         throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
607 
608     if (!fVerbose)
609     {
610         CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
611         ssBlock << block;
612         std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
613         return strHex;
614     }
615 
616     return blockToJSON(block, pblockindex);
617 }
618 
619 struct CCoinsStats
620 {
621     int nHeight;
622     uint256 hashBlock;
623     uint64_t nTransactions;
624     uint64_t nTransactionOutputs;
625     uint64_t nSerializedSize;
626     uint256 hashSerialized;
627     CAmount nTotalAmount;
628 
CCoinsStatsCCoinsStats629     CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), nTotalAmount(0) {}
630 };
631 
632 //! Calculate statistics about the unspent transaction output set
GetUTXOStats(CCoinsView * view,CCoinsStats & stats)633 static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
634 {
635     boost::scoped_ptr<CCoinsViewCursor> pcursor(view->Cursor());
636 
637     CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
638     stats.hashBlock = pcursor->GetBestBlock();
639     {
640         LOCK(cs_main);
641         stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
642     }
643     ss << stats.hashBlock;
644     CAmount nTotalAmount = 0;
645     while (pcursor->Valid()) {
646         boost::this_thread::interruption_point();
647         uint256 key;
648         CCoins coins;
649         if (pcursor->GetKey(key) && pcursor->GetValue(coins)) {
650             stats.nTransactions++;
651             ss << key;
652             for (unsigned int i=0; i<coins.vout.size(); i++) {
653                 const CTxOut &out = coins.vout[i];
654                 if (!out.IsNull()) {
655                     stats.nTransactionOutputs++;
656                     ss << VARINT(i+1);
657                     ss << out;
658                     nTotalAmount += out.nValue;
659                 }
660             }
661             stats.nSerializedSize += 32 + pcursor->GetValueSize();
662             ss << VARINT(0);
663         } else {
664             return error("%s: unable to read value", __func__);
665         }
666         pcursor->Next();
667     }
668     stats.hashSerialized = ss.GetHash();
669     stats.nTotalAmount = nTotalAmount;
670     return true;
671 }
672 
gettxoutsetinfo(const UniValue & params,bool fHelp)673 UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
674 {
675     if (fHelp || params.size() != 0)
676         throw runtime_error(
677             "gettxoutsetinfo\n"
678             "\nReturns statistics about the unspent transaction output set.\n"
679             "Note this call may take some time.\n"
680             "\nResult:\n"
681             "{\n"
682             "  \"height\":n,     (numeric) The current block height (index)\n"
683             "  \"bestblock\": \"hex\",   (string) the best block hash hex\n"
684             "  \"transactions\": n,      (numeric) The number of transactions\n"
685             "  \"txouts\": n,            (numeric) The number of output transactions\n"
686             "  \"bytes_serialized\": n,  (numeric) The serialized size\n"
687             "  \"hash_serialized\": \"hash\",   (string) The serialized hash\n"
688             "  \"total_amount\": x.xxx          (numeric) The total amount\n"
689             "}\n"
690             "\nExamples:\n"
691             + HelpExampleCli("gettxoutsetinfo", "")
692             + HelpExampleRpc("gettxoutsetinfo", "")
693         );
694 
695     UniValue ret(UniValue::VOBJ);
696 
697     CCoinsStats stats;
698     FlushStateToDisk();
699     if (GetUTXOStats(pcoinsTip, stats)) {
700         ret.push_back(Pair("height", (int64_t)stats.nHeight));
701         ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
702         ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
703         ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
704         ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
705         ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
706         ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
707     } else {
708         throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
709     }
710     return ret;
711 }
712 
gettxout(const UniValue & params,bool fHelp)713 UniValue gettxout(const UniValue& params, bool fHelp)
714 {
715     if (fHelp || params.size() < 2 || params.size() > 3)
716         throw runtime_error(
717             "gettxout \"txid\" n ( includemempool )\n"
718             "\nReturns details about an unspent transaction output.\n"
719             "\nArguments:\n"
720             "1. \"txid\"       (string, required) The transaction id\n"
721             "2. n              (numeric, required) vout number\n"
722             "3. includemempool  (boolean, optional) Whether to include the mempool\n"
723             "\nResult:\n"
724             "{\n"
725             "  \"bestblock\" : \"hash\",    (string) the block hash\n"
726             "  \"confirmations\" : n,       (numeric) The number of confirmations\n"
727             "  \"value\" : x.xxx,           (numeric) The transaction value in " + CURRENCY_UNIT + "\n"
728             "  \"scriptPubKey\" : {         (json object)\n"
729             "     \"asm\" : \"code\",       (string) \n"
730             "     \"hex\" : \"hex\",        (string) \n"
731             "     \"reqSigs\" : n,          (numeric) Number of required signatures\n"
732             "     \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
733             "     \"addresses\" : [          (array of string) array of zetacoin addresses\n"
734             "        \"zetacoinaddress\"     (string) zetacoin address\n"
735             "        ,...\n"
736             "     ]\n"
737             "  },\n"
738             "  \"version\" : n,            (numeric) The version\n"
739             "  \"coinbase\" : true|false   (boolean) Coinbase or not\n"
740             "}\n"
741 
742             "\nExamples:\n"
743             "\nGet unspent transactions\n"
744             + HelpExampleCli("listunspent", "") +
745             "\nView the details\n"
746             + HelpExampleCli("gettxout", "\"txid\" 1") +
747             "\nAs a json rpc call\n"
748             + HelpExampleRpc("gettxout", "\"txid\", 1")
749         );
750 
751     LOCK(cs_main);
752 
753     UniValue ret(UniValue::VOBJ);
754 
755     std::string strHash = params[0].get_str();
756     uint256 hash(uint256S(strHash));
757     int n = params[1].get_int();
758     bool fMempool = true;
759     if (params.size() > 2)
760         fMempool = params[2].get_bool();
761 
762     CCoins coins;
763     if (fMempool) {
764         LOCK(mempool.cs);
765         CCoinsViewMemPool view(pcoinsTip, mempool);
766         if (!view.GetCoins(hash, coins))
767             return NullUniValue;
768         mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
769     } else {
770         if (!pcoinsTip->GetCoins(hash, coins))
771             return NullUniValue;
772     }
773     if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
774         return NullUniValue;
775 
776     BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
777     CBlockIndex *pindex = it->second;
778     ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
779     if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
780         ret.push_back(Pair("confirmations", 0));
781     else
782         ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
783     ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
784     UniValue o(UniValue::VOBJ);
785     ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
786     ret.push_back(Pair("scriptPubKey", o));
787     ret.push_back(Pair("version", coins.nVersion));
788     ret.push_back(Pair("coinbase", coins.fCoinBase));
789 
790     return ret;
791 }
792 
verifychain(const UniValue & params,bool fHelp)793 UniValue verifychain(const UniValue& params, bool fHelp)
794 {
795     int nCheckLevel = GetArg("-checklevel", DEFAULT_CHECKLEVEL);
796     int nCheckDepth = GetArg("-checkblocks", DEFAULT_CHECKBLOCKS);
797     if (fHelp || params.size() > 2)
798         throw runtime_error(
799             "verifychain ( checklevel numblocks )\n"
800             "\nVerifies blockchain database.\n"
801             "\nArguments:\n"
802             "1. checklevel   (numeric, optional, 0-4, default=" + strprintf("%d", nCheckLevel) + ") How thorough the block verification is.\n"
803             "2. numblocks    (numeric, optional, default=" + strprintf("%d", nCheckDepth) + ", 0=all) The number of blocks to check.\n"
804             "\nResult:\n"
805             "true|false       (boolean) Verified or not\n"
806             "\nExamples:\n"
807             + HelpExampleCli("verifychain", "")
808             + HelpExampleRpc("verifychain", "")
809         );
810 
811     LOCK(cs_main);
812 
813     if (params.size() > 0)
814         nCheckLevel = params[0].get_int();
815     if (params.size() > 1)
816         nCheckDepth = params[1].get_int();
817 
818     return CVerifyDB().VerifyDB(Params(), pcoinsTip, nCheckLevel, nCheckDepth);
819 }
820 
BIP9SoftForkDesc(const std::string & name,const Consensus::Params & consensusParams,Consensus::DeploymentPos id)821 static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
822 {
823     UniValue rv(UniValue::VOBJ);
824     rv.push_back(Pair("id", name));
825     switch (VersionBitsTipState(consensusParams, id)) {
826     case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break;
827     case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break;
828     case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break;
829     case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break;
830     case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break;
831     }
832     return rv;
833 }
834 
BIP9SoftForkDesc(const Consensus::Params & consensusParams,Consensus::DeploymentPos id)835 static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
836 {
837     UniValue rv(UniValue::VOBJ);
838     const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
839     switch (thresholdState) {
840     case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break;
841     case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break;
842     case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break;
843     case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break;
844     case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break;
845     }
846     if (THRESHOLD_STARTED == thresholdState)
847     {
848         rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit));
849     }
850     rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime));
851     rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout));
852     return rv;
853 }
854 
BIP9SoftForkDescPushBack(UniValue & bip9_softforks,const std::string & name,const Consensus::Params & consensusParams,Consensus::DeploymentPos id)855 void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
856 {
857     // Deployments with timeout value of 0 are hidden.
858     // A timeout value of 0 guarantees a softfork will never be activated.
859     // This is used when softfork codes are merged without specifying the deployment schedule.
860     if (consensusParams.vDeployments[id].nTimeout > 0)
861         bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id)));
862 }
863 
getblockchaininfo(const UniValue & params,bool fHelp)864 UniValue getblockchaininfo(const UniValue& params, bool fHelp)
865 {
866     if (fHelp || params.size() != 0)
867         throw runtime_error(
868             "getblockchaininfo\n"
869             "Returns an object containing various state info regarding block chain processing.\n"
870             "\nResult:\n"
871             "{\n"
872             "  \"chain\": \"xxxx\",        (string) current network name as defined in BIP70 (main, test, regtest)\n"
873             "  \"blocks\": xxxxxx,         (numeric) the current number of blocks processed in the server\n"
874             "  \"headers\": xxxxxx,        (numeric) the current number of headers we have validated\n"
875             "  \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
876             "  \"difficulty\": xxxxxx,     (numeric) the current difficulty\n"
877             "  \"mediantime\": xxxxxx,     (numeric) median time for the current best block\n"
878             "  \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
879             "  \"chainwork\": \"xxxx\"     (string) total amount of work in active chain, in hexadecimal\n"
880             "  \"pruned\": xx,             (boolean) if the blocks are subject to pruning\n"
881             "  \"pruneheight\": xxxxxx,    (numeric) lowest-height complete block stored\n"
882             "  \"softforks\": [            (array) status of softforks in progress\n"
883             "     {\n"
884             "        \"id\": \"xxxx\",        (string) name of softfork\n"
885             "        \"version\": xx,         (numeric) block version\n"
886             "        \"enforce\": {           (object) progress toward enforcing the softfork rules for new-version blocks\n"
887             "           \"status\": xx,       (boolean) true if threshold reached\n"
888             "           \"found\": xx,        (numeric) number of blocks with the new version found\n"
889             "           \"required\": xx,     (numeric) number of blocks required to trigger\n"
890             "           \"window\": xx,       (numeric) maximum size of examined window of recent blocks\n"
891             "        },\n"
892             "        \"reject\": { ... }      (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
893             "     }, ...\n"
894             "  ],\n"
895             "  \"bip9_softforks\": {          (object) status of BIP9 softforks in progress\n"
896             "     \"xxxx\" : {                (string) name of the softfork\n"
897             "        \"status\": \"xxxx\",    (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
898             "        \"bit\": xx,             (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n"
899             "        \"startTime\": xx,       (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
900             "        \"timeout\": xx          (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
901             "     }\n"
902             "  }\n"
903             "}\n"
904             "\nExamples:\n"
905             + HelpExampleCli("getblockchaininfo", "")
906             + HelpExampleRpc("getblockchaininfo", "")
907         );
908 
909     LOCK(cs_main);
910 
911     UniValue obj(UniValue::VOBJ);
912     obj.push_back(Pair("chain",                 Params().NetworkIDString()));
913     obj.push_back(Pair("blocks",                (int)chainActive.Height()));
914     obj.push_back(Pair("headers",               pindexBestHeader ? pindexBestHeader->nHeight : -1));
915     obj.push_back(Pair("bestblockhash",         chainActive.Tip()->GetBlockHash().GetHex()));
916     obj.push_back(Pair("difficulty",            (double)GetDifficulty()));
917     obj.push_back(Pair("mediantime",            (int64_t)chainActive.Tip()->GetMedianTimePast()));
918     obj.push_back(Pair("verificationprogress",  Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
919     obj.push_back(Pair("chainwork",             chainActive.Tip()->nChainWork.GetHex()));
920     obj.push_back(Pair("pruned",                fPruneMode));
921 
922     const Consensus::Params& consensusParams = Params().GetConsensus();
923     CBlockIndex* tip = chainActive.Tip();
924     UniValue softforks(UniValue::VARR);
925     UniValue bip9_softforks(UniValue::VOBJ);
926     BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV);
927     BIP9SoftForkDescPushBack(bip9_softforks, "segwit", consensusParams, Consensus::DEPLOYMENT_SEGWIT);
928     obj.push_back(Pair("softforks",             softforks));
929     obj.push_back(Pair("bip9_softforks", bip9_softforks));
930 
931     if (fPruneMode)
932     {
933         CBlockIndex *block = chainActive.Tip();
934         while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
935             block = block->pprev;
936 
937         obj.push_back(Pair("pruneheight",        block->nHeight));
938     }
939     return obj;
940 }
941 
942 /** Comparison function for sorting the getchaintips heads.  */
943 struct CompareBlocksByHeight
944 {
operator ()CompareBlocksByHeight945     bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
946     {
947         /* Make sure that unequal blocks with the same height do not compare
948            equal. Use the pointers themselves to make a distinction. */
949 
950         if (a->nHeight != b->nHeight)
951           return (a->nHeight > b->nHeight);
952 
953         return a < b;
954     }
955 };
956 
getchaintips(const UniValue & params,bool fHelp)957 UniValue getchaintips(const UniValue& params, bool fHelp)
958 {
959     if (fHelp || params.size() != 0)
960         throw runtime_error(
961             "getchaintips\n"
962             "Return information about all known tips in the block tree,"
963             " including the main chain as well as orphaned branches.\n"
964             "\nResult:\n"
965             "[\n"
966             "  {\n"
967             "    \"height\": xxxx,         (numeric) height of the chain tip\n"
968             "    \"hash\": \"xxxx\",         (string) block hash of the tip\n"
969             "    \"branchlen\": 0          (numeric) zero for main chain\n"
970             "    \"status\": \"active\"      (string) \"active\" for the main chain\n"
971             "  },\n"
972             "  {\n"
973             "    \"height\": xxxx,\n"
974             "    \"hash\": \"xxxx\",\n"
975             "    \"branchlen\": 1          (numeric) length of branch connecting the tip to the main chain\n"
976             "    \"status\": \"xxxx\"        (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
977             "  }\n"
978             "]\n"
979             "Possible values for status:\n"
980             "1.  \"invalid\"               This branch contains at least one invalid block\n"
981             "2.  \"headers-only\"          Not all blocks for this branch are available, but the headers are valid\n"
982             "3.  \"valid-headers\"         All blocks are available for this branch, but they were never fully validated\n"
983             "4.  \"valid-fork\"            This branch is not part of the active chain, but is fully validated\n"
984             "5.  \"active\"                This is the tip of the active main chain, which is certainly valid\n"
985             "\nExamples:\n"
986             + HelpExampleCli("getchaintips", "")
987             + HelpExampleRpc("getchaintips", "")
988         );
989 
990     LOCK(cs_main);
991 
992     /*
993      * Idea:  the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them.
994      * Algorithm:
995      *  - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
996      *  - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
997      *  - add chainActive.Tip()
998      */
999     std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
1000     std::set<const CBlockIndex*> setOrphans;
1001     std::set<const CBlockIndex*> setPrevs;
1002 
1003     BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
1004     {
1005         if (!chainActive.Contains(item.second)) {
1006             setOrphans.insert(item.second);
1007             setPrevs.insert(item.second->pprev);
1008         }
1009     }
1010 
1011     for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it)
1012     {
1013         if (setPrevs.erase(*it) == 0) {
1014             setTips.insert(*it);
1015         }
1016     }
1017 
1018     // Always report the currently active tip.
1019     setTips.insert(chainActive.Tip());
1020 
1021     /* Construct the output array.  */
1022     UniValue res(UniValue::VARR);
1023     BOOST_FOREACH(const CBlockIndex* block, setTips)
1024     {
1025         UniValue obj(UniValue::VOBJ);
1026         obj.push_back(Pair("height", block->nHeight));
1027         obj.push_back(Pair("hash", block->phashBlock->GetHex()));
1028 
1029         const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
1030         obj.push_back(Pair("branchlen", branchLen));
1031 
1032         string status;
1033         if (chainActive.Contains(block)) {
1034             // This block is part of the currently active chain.
1035             status = "active";
1036         } else if (block->nStatus & BLOCK_FAILED_MASK) {
1037             // This block or one of its ancestors is invalid.
1038             status = "invalid";
1039         } else if (block->nChainTx == 0) {
1040             // This block cannot be connected because full block data for it or one of its parents is missing.
1041             status = "headers-only";
1042         } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
1043             // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
1044             status = "valid-fork";
1045         } else if (block->IsValid(BLOCK_VALID_TREE)) {
1046             // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
1047             status = "valid-headers";
1048         } else {
1049             // No clue.
1050             status = "unknown";
1051         }
1052         obj.push_back(Pair("status", status));
1053 
1054         res.push_back(obj);
1055     }
1056 
1057     return res;
1058 }
1059 
mempoolInfoToJSON()1060 UniValue mempoolInfoToJSON()
1061 {
1062     UniValue ret(UniValue::VOBJ);
1063     ret.push_back(Pair("size", (int64_t) mempool.size()));
1064     ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
1065     ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
1066     size_t maxmempool = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
1067     ret.push_back(Pair("maxmempool", (int64_t) maxmempool));
1068     ret.push_back(Pair("mempoolminfee", ValueFromAmount(mempool.GetMinFee(maxmempool).GetFeePerK())));
1069 
1070     return ret;
1071 }
1072 
getmempoolinfo(const UniValue & params,bool fHelp)1073 UniValue getmempoolinfo(const UniValue& params, bool fHelp)
1074 {
1075     if (fHelp || params.size() != 0)
1076         throw runtime_error(
1077             "getmempoolinfo\n"
1078             "\nReturns details on the active state of the TX memory pool.\n"
1079             "\nResult:\n"
1080             "{\n"
1081             "  \"size\": xxxxx,               (numeric) Current tx count\n"
1082             "  \"bytes\": xxxxx,              (numeric) Sum of all tx sizes\n"
1083             "  \"usage\": xxxxx,              (numeric) Total memory usage for the mempool\n"
1084             "  \"maxmempool\": xxxxx,         (numeric) Maximum memory usage for the mempool\n"
1085             "  \"mempoolminfee\": xxxxx       (numeric) Minimum fee for tx to be accepted\n"
1086             "}\n"
1087             "\nExamples:\n"
1088             + HelpExampleCli("getmempoolinfo", "")
1089             + HelpExampleRpc("getmempoolinfo", "")
1090         );
1091 
1092     return mempoolInfoToJSON();
1093 }
1094 
invalidateblock(const UniValue & params,bool fHelp)1095 UniValue invalidateblock(const UniValue& params, bool fHelp)
1096 {
1097     if (fHelp || params.size() != 1)
1098         throw runtime_error(
1099             "invalidateblock \"hash\"\n"
1100             "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
1101             "\nArguments:\n"
1102             "1. hash   (string, required) the hash of the block to mark as invalid\n"
1103             "\nResult:\n"
1104             "\nExamples:\n"
1105             + HelpExampleCli("invalidateblock", "\"blockhash\"")
1106             + HelpExampleRpc("invalidateblock", "\"blockhash\"")
1107         );
1108 
1109     std::string strHash = params[0].get_str();
1110     uint256 hash(uint256S(strHash));
1111     CValidationState state;
1112 
1113     {
1114         LOCK(cs_main);
1115         if (mapBlockIndex.count(hash) == 0)
1116             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1117 
1118         CBlockIndex* pblockindex = mapBlockIndex[hash];
1119         InvalidateBlock(state, Params(), pblockindex);
1120     }
1121 
1122     if (state.IsValid()) {
1123         ActivateBestChain(state, Params());
1124     }
1125 
1126     if (!state.IsValid()) {
1127         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1128     }
1129 
1130     return NullUniValue;
1131 }
1132 
reconsiderblock(const UniValue & params,bool fHelp)1133 UniValue reconsiderblock(const UniValue& params, bool fHelp)
1134 {
1135     if (fHelp || params.size() != 1)
1136         throw runtime_error(
1137             "reconsiderblock \"hash\"\n"
1138             "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
1139             "This can be used to undo the effects of invalidateblock.\n"
1140             "\nArguments:\n"
1141             "1. hash   (string, required) the hash of the block to reconsider\n"
1142             "\nResult:\n"
1143             "\nExamples:\n"
1144             + HelpExampleCli("reconsiderblock", "\"blockhash\"")
1145             + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
1146         );
1147 
1148     std::string strHash = params[0].get_str();
1149     uint256 hash(uint256S(strHash));
1150 
1151     {
1152         LOCK(cs_main);
1153         if (mapBlockIndex.count(hash) == 0)
1154             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1155 
1156         CBlockIndex* pblockindex = mapBlockIndex[hash];
1157         ResetBlockFailureFlags(pblockindex);
1158     }
1159 
1160     CValidationState state;
1161     ActivateBestChain(state, Params());
1162 
1163     if (!state.IsValid()) {
1164         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1165     }
1166 
1167     return NullUniValue;
1168 }
1169 
1170 static const CRPCCommand commands[] =
1171 { //  category              name                      actor (function)         okSafeMode
1172   //  --------------------- ------------------------  -----------------------  ----------
1173     { "blockchain",         "getblockchaininfo",      &getblockchaininfo,      true  },
1174     { "blockchain",         "getbestblockhash",       &getbestblockhash,       true  },
1175     { "blockchain",         "getblockcount",          &getblockcount,          true  },
1176     { "blockchain",         "getblock",               &getblock,               true  },
1177     { "blockchain",         "getblockhash",           &getblockhash,           true  },
1178     { "blockchain",         "getblockheader",         &getblockheader,         true  },
1179     { "blockchain",         "getchaintips",           &getchaintips,           true  },
1180     { "blockchain",         "getdifficulty",          &getdifficulty,          true  },
1181     { "blockchain",         "getmempoolancestors",    &getmempoolancestors,    true  },
1182     { "blockchain",         "getmempooldescendants",  &getmempooldescendants,  true  },
1183     { "blockchain",         "getmempoolentry",        &getmempoolentry,        true  },
1184     { "blockchain",         "getmempoolinfo",         &getmempoolinfo,         true  },
1185     { "blockchain",         "getrawmempool",          &getrawmempool,          true  },
1186     { "blockchain",         "gettxout",               &gettxout,               true  },
1187     { "blockchain",         "gettxoutsetinfo",        &gettxoutsetinfo,        true  },
1188     { "blockchain",         "verifychain",            &verifychain,            true  },
1189 
1190     /* Not shown in help */
1191     { "hidden",             "invalidateblock",        &invalidateblock,        true  },
1192     { "hidden",             "reconsiderblock",        &reconsiderblock,        true  },
1193 };
1194 
RegisterBlockchainRPCCommands(CRPCTable & tableRPC)1195 void RegisterBlockchainRPCCommands(CRPCTable &tableRPC)
1196 {
1197     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
1198         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
1199 }
1200