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