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