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