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.
6 #include "checkpoints.h"
7 #include "consensus/validation.h"
9 #include "primitives/transaction.h"
10 #include "rpcserver.h"
16 #include "json/json_spirit_value.h"
18 using namespace json_spirit;
21 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
22 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
24 double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
26 // Floating point number that is a multiple of the minimum difficulty,
27 // minimum difficulty = 1.0.
28 if (blockindex == NULL)
30 if (chainActive.Tip() == NULL)
33 blockindex = chainActive.Tip();
37 if (networkDifficulty) {
38 bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus());
40 bits = blockindex->nBits;
44 UintToArith256(Params().GetConsensus().powLimit).GetCompact();
45 int nShift = (bits >> 24) & 0xff;
46 int nShiftAmount = (powLimit >> 24) & 0xff;
49 (double)(powLimit & 0x00ffffff) /
50 (double)(bits & 0x00ffffff);
52 while (nShift < nShiftAmount)
57 while (nShift > nShiftAmount)
66 double GetDifficulty(const CBlockIndex* blockindex)
68 return GetDifficultyINTERNAL(blockindex, false);
71 double GetNetworkDifficulty(const CBlockIndex* blockindex)
73 return GetDifficultyINTERNAL(blockindex, true);
77 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
80 result.push_back(Pair("hash", block.GetHash().GetHex()));
81 int confirmations = -1;
82 // Only report confirmations if the block is on the main chain
83 if (chainActive.Contains(blockindex))
84 confirmations = chainActive.Height() - blockindex->nHeight + 1;
85 result.push_back(Pair("confirmations", confirmations));
86 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
87 result.push_back(Pair("height", blockindex->nHeight));
88 result.push_back(Pair("version", block.nVersion));
89 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
91 BOOST_FOREACH(const CTransaction&tx, block.vtx)
96 TxToJSON(tx, uint256(), objTx);
100 txs.push_back(tx.GetHash().GetHex());
102 result.push_back(Pair("tx", txs));
103 result.push_back(Pair("time", block.GetBlockTime()));
104 result.push_back(Pair("nonce", block.nNonce.GetHex()));
105 result.push_back(Pair("solution", HexStr(block.nSolution)));
106 result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
107 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
108 result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
110 if (blockindex->pprev)
111 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
112 CBlockIndex *pnext = chainActive.Next(blockindex);
114 result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
119 Value getblockcount(const Array& params, bool fHelp)
121 if (fHelp || params.size() != 0)
124 "\nReturns the number of blocks in the longest block chain.\n"
126 "n (numeric) The current block count\n"
128 + HelpExampleCli("getblockcount", "")
129 + HelpExampleRpc("getblockcount", "")
133 return chainActive.Height();
136 Value getbestblockhash(const Array& params, bool fHelp)
138 if (fHelp || params.size() != 0)
141 "\nReturns the hash of the best (tip) block in the longest block chain.\n"
143 "\"hex\" (string) the block hash hex encoded\n"
145 + HelpExampleCli("getbestblockhash", "")
146 + HelpExampleRpc("getbestblockhash", "")
150 return chainActive.Tip()->GetBlockHash().GetHex();
153 Value getdifficulty(const Array& params, bool fHelp)
155 if (fHelp || params.size() != 0)
158 "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
160 "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
162 + HelpExampleCli("getdifficulty", "")
163 + HelpExampleRpc("getdifficulty", "")
167 return GetNetworkDifficulty();
171 Value getrawmempool(const Array& params, bool fHelp)
173 if (fHelp || params.size() > 1)
175 "getrawmempool ( verbose )\n"
176 "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
178 "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
179 "\nResult: (for verbose = false):\n"
180 "[ (json array of string)\n"
181 " \"transactionid\" (string) The transaction id\n"
184 "\nResult: (for verbose = true):\n"
186 " \"transactionid\" : { (json object)\n"
187 " \"size\" : n, (numeric) transaction size in bytes\n"
188 " \"fee\" : n, (numeric) transaction fee in bitcoins\n"
189 " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
190 " \"height\" : n, (numeric) block height when transaction entered pool\n"
191 " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
192 " \"currentpriority\" : n, (numeric) transaction priority now\n"
193 " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
194 " \"transactionid\", (string) parent transaction id\n"
199 + HelpExampleCli("getrawmempool", "true")
200 + HelpExampleRpc("getrawmempool", "true")
205 bool fVerbose = false;
206 if (params.size() > 0)
207 fVerbose = params[0].get_bool();
213 BOOST_FOREACH(const PAIRTYPE(uint256, CTxMemPoolEntry)& entry, mempool.mapTx)
215 const uint256& hash = entry.first;
216 const CTxMemPoolEntry& e = entry.second;
218 info.push_back(Pair("size", (int)e.GetTxSize()));
219 info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
220 info.push_back(Pair("time", e.GetTime()));
221 info.push_back(Pair("height", (int)e.GetHeight()));
222 info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight())));
223 info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height())));
224 const CTransaction& tx = e.GetTx();
225 set<string> setDepends;
226 BOOST_FOREACH(const CTxIn& txin, tx.vin)
228 if (mempool.exists(txin.prevout.hash))
229 setDepends.insert(txin.prevout.hash.ToString());
231 Array depends(setDepends.begin(), setDepends.end());
232 info.push_back(Pair("depends", depends));
233 o.push_back(Pair(hash.ToString(), info));
239 vector<uint256> vtxid;
240 mempool.queryHashes(vtxid);
243 BOOST_FOREACH(const uint256& hash, vtxid)
244 a.push_back(hash.ToString());
250 Value getblockhash(const Array& params, bool fHelp)
252 if (fHelp || params.size() != 1)
254 "getblockhash index\n"
255 "\nReturns hash of block in best-block-chain at index provided.\n"
257 "1. index (numeric, required) The block index\n"
259 "\"hash\" (string) The block hash\n"
261 + HelpExampleCli("getblockhash", "1000")
262 + HelpExampleRpc("getblockhash", "1000")
267 int nHeight = params[0].get_int();
268 if (nHeight < 0 || nHeight > chainActive.Height())
269 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
271 CBlockIndex* pblockindex = chainActive[nHeight];
272 return pblockindex->GetBlockHash().GetHex();
275 Value getblock(const Array& params, bool fHelp)
277 if (fHelp || params.size() < 1 || params.size() > 2)
279 "getblock \"hash\" ( verbose )\n"
280 "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
281 "If verbose is true, returns an Object with information about block <hash>.\n"
283 "1. \"hash\" (string, required) The block hash\n"
284 "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
285 "\nResult (for verbose = true):\n"
287 " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
288 " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
289 " \"size\" : n, (numeric) The block size\n"
290 " \"height\" : n, (numeric) The block height or index\n"
291 " \"version\" : n, (numeric) The block version\n"
292 " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
293 " \"tx\" : [ (array of string) The transaction ids\n"
294 " \"transactionid\" (string) The transaction id\n"
297 " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
298 " \"nonce\" : n, (numeric) The nonce\n"
299 " \"bits\" : \"1d00ffff\", (string) The bits\n"
300 " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
301 " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
302 " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
304 "\nResult (for verbose=false):\n"
305 "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
307 + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
308 + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
313 std::string strHash = params[0].get_str();
314 uint256 hash(uint256S(strHash));
316 bool fVerbose = true;
317 if (params.size() > 1)
318 fVerbose = params[1].get_bool();
320 if (mapBlockIndex.count(hash) == 0)
321 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
324 CBlockIndex* pblockindex = mapBlockIndex[hash];
326 if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
327 throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
329 if(!ReadBlockFromDisk(block, pblockindex))
330 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
334 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
336 std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
340 return blockToJSON(block, pblockindex);
343 Value gettxoutsetinfo(const Array& params, bool fHelp)
345 if (fHelp || params.size() != 0)
348 "\nReturns statistics about the unspent transaction output set.\n"
349 "Note this call may take some time.\n"
352 " \"height\":n, (numeric) The current block height (index)\n"
353 " \"bestblock\": \"hex\", (string) the best block hash hex\n"
354 " \"transactions\": n, (numeric) The number of transactions\n"
355 " \"txouts\": n, (numeric) The number of output transactions\n"
356 " \"bytes_serialized\": n, (numeric) The serialized size\n"
357 " \"hash_serialized\": \"hash\", (string) The serialized hash\n"
358 " \"total_amount\": x.xxx (numeric) The total amount\n"
361 + HelpExampleCli("gettxoutsetinfo", "")
362 + HelpExampleRpc("gettxoutsetinfo", "")
371 if (pcoinsTip->GetStats(stats)) {
372 ret.push_back(Pair("height", (int64_t)stats.nHeight));
373 ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
374 ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
375 ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
376 ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
377 ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
378 ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
383 uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
384 uint32_t komodo_txtime(uint256 hash);
385 uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume);
386 int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
387 int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height);
388 char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
389 uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n);
390 int32_t komodo_minerids(uint8_t *minerids,int32_t height);
392 Value minerids(const Array& params, bool fHelp)
394 Object ret; Array a; uint8_t minerids[1000],pubkeys[64][33]; int32_t i,j,n,numnotaries,tally[65];
395 if ( fHelp || params.size() != 1 )
396 throw runtime_error("minerids needs height\n");
398 int32_t height = atoi(params[0].get_str().c_str());
400 height = chainActive.Tip()->nHeight;
401 if ( (n= komodo_minerids(minerids,height)) > 0 )
403 memset(tally,0,sizeof(tally));
404 numnotaries = komodo_notaries(pubkeys,height);
405 if ( numnotaries > 0 )
409 if ( minerids[i] >= numnotaries )
411 else tally[minerids[i]]++;
415 Object item; std::string hex; char *hexstr;
417 hexstr = (char *)hex.data();
419 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
420 item.push_back(Pair("notaryid", i));
421 item.push_back(Pair("pubkey", hex));
422 item.push_back(Pair("blocks", tally[i]));
426 item.push_back(Pair("pubkey", (char *)"external miners"));
427 item.push_back(Pair("blocks", tally[64]));
430 ret.push_back(Pair("mined", a));
431 } else ret.push_back(Pair("error", (char *)"couldnt extract minerids"));
435 Value notaries(const Array& params, bool fHelp)
437 Array a; Object ret; int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr;
438 if ( fHelp || params.size() != 1 )
439 throw runtime_error("notaries height\n");
441 int32_t height = atoi(params[0].get_str().c_str());
444 //fprintf(stderr,"notaries as of height.%d\n",height);
445 //if ( height > chainActive.Height()+20000 )
446 // throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
449 if ( (n= komodo_notaries(pubkeys,height)) > 0 )
454 std::string btcaddress,kmdaddress,hex;
456 hexstr = (char *)hex.data();
458 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
459 item.push_back(Pair("pubkey", hex));
461 bitcoin_address(btcaddr,0,pubkeys[i],33);
462 m = (int32_t)strlen(btcaddr);
463 btcaddress.resize(m);
464 ptr = (char *)btcaddress.data();
465 memcpy(ptr,btcaddr,m);
466 item.push_back(Pair("BTCaddress", btcaddress));
468 bitcoin_address(kmdaddr,60,pubkeys[i],33);
469 m = (int32_t)strlen(kmdaddr);
470 kmdaddress.resize(m);
471 ptr = (char *)kmdaddress.data();
472 memcpy(ptr,kmdaddr,m);
473 item.push_back(Pair("KMDaddress", kmdaddress));
477 ret.push_back(Pair("notaries", a));
478 ret.push_back(Pair("numnotaries", n));
483 int32_t komodo_pending_withdraws(char *opretstr);
485 Value paxpending(const Array& params, bool fHelp)
487 Object ret; char opretbuf[10000*2]; int32_t opretlen;
488 if ( fHelp || params.size() != 0 )
489 throw runtime_error("paxpending needs no args\n");
491 if ( (opretlen= komodo_pending_withdraws(opretbuf)) > 0 )
492 ret.push_back(Pair("withdraws", opretbuf));
493 else ret.push_back(Pair("withdraws", (char *)""));
497 Value paxprice(const Array& params, bool fHelp)
499 if ( fHelp || params.size() < 3 || params.size() > 4 )
500 throw runtime_error("paxprice \"base\" \"rel\" height amount\n");
502 Object ret; uint64_t basevolume=0,relvolume,seed;
503 std::string base = params[0].get_str();
504 std::string rel = params[1].get_str();
505 int32_t height = atoi(params[2].get_str().c_str());
506 if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
508 relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume);
509 ret.push_back(Pair("base", base));
510 ret.push_back(Pair("rel", rel));
511 ret.push_back(Pair("height", height));
513 sprintf(seedstr,"%llu",(long long)seed);
514 ret.push_back(Pair("seed", seedstr));
515 if ( height < 0 || height > chainActive.Height() )
516 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
519 CBlockIndex *pblockindex = chainActive[height];
520 ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime));
521 if ( basevolume != 0 && relvolume != 0 )
523 ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
524 ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume)));
525 ret.push_back(Pair("basevolume", ValueFromAmount(basevolume)));
526 ret.push_back(Pair("relvolume", ValueFromAmount(relvolume)));
527 } else ret.push_back(Pair("error", "overflow or error in one or more of parameters"));
532 Value paxprices(const Array& params, bool fHelp)
534 if ( fHelp || params.size() != 3 )
535 throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
537 Object ret; uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
538 std::string base = params[0].get_str();
539 std::string rel = params[1].get_str();
540 int32_t maxsamples = atoi(params[2].get_str().c_str());
541 if ( maxsamples < 1 )
543 else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
544 maxsamples = sizeof(heights)/sizeof(*heights);
545 ret.push_back(Pair("base", base));
546 ret.push_back(Pair("rel", rel));
547 n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
552 if ( heights[i] < 0 || heights[i] > chainActive.Height() )
553 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
556 CBlockIndex *pblockindex = chainActive[heights[i]];
558 item.push_back(Pair("t", (int64_t)pblockindex->nTime));
559 item.push_back(Pair("p", (double)prices[i] / COIN));
563 ret.push_back(Pair("array", a));
567 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue);
569 Value gettxout(const Array& params, bool fHelp)
571 if (fHelp || params.size() < 2 || params.size() > 3)
573 "gettxout \"txid\" n ( includemempool )\n"
574 "\nReturns details about an unspent transaction output.\n"
576 "1. \"txid\" (string, required) The transaction id\n"
577 "2. n (numeric, required) vout value\n"
578 "3. includemempool (boolean, optional) Whether to included the mem pool\n"
581 " \"bestblock\" : \"hash\", (string) the block hash\n"
582 " \"confirmations\" : n, (numeric) The number of confirmations\n"
583 " \"value\" : x.xxx, (numeric) The transaction value in btc\n"
584 " \"scriptPubKey\" : { (json object)\n"
585 " \"asm\" : \"code\", (string) \n"
586 " \"hex\" : \"hex\", (string) \n"
587 " \"reqSigs\" : n, (numeric) Number of required signatures\n"
588 " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
589 " \"addresses\" : [ (array of string) array of bitcoin addresses\n"
590 " \"bitcoinaddress\" (string) bitcoin address\n"
594 " \"version\" : n, (numeric) The version\n"
595 " \"coinbase\" : true|false (boolean) Coinbase or not\n"
599 "\nGet unspent transactions\n"
600 + HelpExampleCli("listunspent", "") +
601 "\nView the details\n"
602 + HelpExampleCli("gettxout", "\"txid\" 1") +
603 "\nAs a json rpc call\n"
604 + HelpExampleRpc("gettxout", "\"txid\", 1")
611 std::string strHash = params[0].get_str();
612 uint256 hash(uint256S(strHash));
613 int n = params[1].get_int();
614 bool fMempool = true;
615 if (params.size() > 2)
616 fMempool = params[2].get_bool();
621 CCoinsViewMemPool view(pcoinsTip, mempool);
622 if (!view.GetCoins(hash, coins))
624 mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
626 if (!pcoinsTip->GetCoins(hash, coins))
629 if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
632 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
633 CBlockIndex *pindex = it->second;
634 ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
635 if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
636 ret.push_back(Pair("confirmations", 0));
637 else ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
638 ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
639 uint64_t interest; int32_t txheight; uint32_t locktime;
640 if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue)) != 0 )
641 ret.push_back(Pair("interest", ValueFromAmount(interest)));
643 ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
644 ret.push_back(Pair("scriptPubKey", o));
645 ret.push_back(Pair("version", coins.nVersion));
646 ret.push_back(Pair("coinbase", coins.fCoinBase));
651 int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid,int32_t n)
653 int32_t i,m; uint8_t *ptr;
659 CCoinsViewMemPool view(pcoinsTip,mempool);
660 if ( view.GetCoins(txid,coins) == 0 )
662 mempool.pruneSpent(txid, coins); // TODO: this should be done by the CCoinsViewMemPool
663 } else if ( pcoinsTip->GetCoins(txid,coins) == 0 )
665 if ( n < 0 || (unsigned int)n >= coins.vout.size() || coins.vout[n].IsNull() )
667 ptr = (uint8_t *)coins.vout[n].scriptPubKey.data();
668 m = coins.vout[n].scriptPubKey.size();
669 for (i=0; i<maxsize&&i<m; i++)
670 scriptPubKey[i] = ptr[i];
674 Value verifychain(const Array& params, bool fHelp)
676 if (fHelp || params.size() > 2)
678 "verifychain ( checklevel numblocks )\n"
679 "\nVerifies blockchain database.\n"
681 "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
682 "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
684 "true|false (boolean) Verified or not\n"
686 + HelpExampleCli("verifychain", "")
687 + HelpExampleRpc("verifychain", "")
692 int nCheckLevel = GetArg("-checklevel", 3);
693 int nCheckDepth = GetArg("-checkblocks", 288);
694 if (params.size() > 0)
695 nCheckLevel = params[0].get_int();
696 if (params.size() > 1)
697 nCheckDepth = params[1].get_int();
699 return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
702 /** Implementation of IsSuperMajority with better feedback */
703 Object SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
706 CBlockIndex* pstart = pindex;
707 for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
709 if (pstart->nVersion >= minVersion)
711 pstart = pstart->pprev;
715 rv.push_back(Pair("status", nFound >= nRequired));
716 rv.push_back(Pair("found", nFound));
717 rv.push_back(Pair("required", nRequired));
718 rv.push_back(Pair("window", consensusParams.nMajorityWindow));
722 Object SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
725 rv.push_back(Pair("id", name));
726 rv.push_back(Pair("version", version));
727 rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
728 rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
732 Value getblockchaininfo(const Array& params, bool fHelp)
734 if (fHelp || params.size() != 0)
736 "getblockchaininfo\n"
737 "Returns an object containing various state info regarding block chain processing.\n"
740 " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
741 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
742 " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
743 " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
744 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
745 " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
746 " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
747 " \"softforks\": [ (array) status of softforks in progress\n"
749 " \"id\": \"xxxx\", (string) name of softfork\n"
750 " \"version\": xx, (numeric) block version\n"
751 " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n"
752 " \"status\": xx, (boolean) true if threshold reached\n"
753 " \"found\": xx, (numeric) number of blocks with the new version found\n"
754 " \"required\": xx, (numeric) number of blocks required to trigger\n"
755 " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n"
757 " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
762 + HelpExampleCli("getblockchaininfo", "")
763 + HelpExampleRpc("getblockchaininfo", "")
769 obj.push_back(Pair("chain", Params().NetworkIDString()));
770 obj.push_back(Pair("blocks", (int)chainActive.Height()));
771 obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
772 obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
773 obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
774 obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
775 obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
776 obj.push_back(Pair("pruned", fPruneMode));
778 const Consensus::Params& consensusParams = Params().GetConsensus();
779 CBlockIndex* tip = chainActive.Tip();
781 softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
782 softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
783 softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
784 obj.push_back(Pair("softforks", softforks));
788 CBlockIndex *block = chainActive.Tip();
789 while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
790 block = block->pprev;
792 obj.push_back(Pair("pruneheight", block->nHeight));
797 /** Comparison function for sorting the getchaintips heads. */
798 struct CompareBlocksByHeight
800 bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
802 /* Make sure that unequal blocks with the same height do not compare
803 equal. Use the pointers themselves to make a distinction. */
805 if (a->nHeight != b->nHeight)
806 return (a->nHeight > b->nHeight);
812 Value getchaintips(const Array& params, bool fHelp)
814 if (fHelp || params.size() != 0)
817 "Return information about all known tips in the block tree,"
818 " including the main chain as well as orphaned branches.\n"
822 " \"height\": xxxx, (numeric) height of the chain tip\n"
823 " \"hash\": \"xxxx\", (string) block hash of the tip\n"
824 " \"branchlen\": 0 (numeric) zero for main chain\n"
825 " \"status\": \"active\" (string) \"active\" for the main chain\n"
828 " \"height\": xxxx,\n"
829 " \"hash\": \"xxxx\",\n"
830 " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
831 " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
834 "Possible values for status:\n"
835 "1. \"invalid\" This branch contains at least one invalid block\n"
836 "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
837 "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
838 "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
839 "5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
841 + HelpExampleCli("getchaintips", "")
842 + HelpExampleRpc("getchaintips", "")
847 /* Build up a list of chain tips. We start with the list of all
848 known blocks, and successively remove blocks that appear as pprev
850 std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
851 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
852 setTips.insert(item.second);
853 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
855 const CBlockIndex* pprev = item.second->pprev;
857 setTips.erase(pprev);
860 // Always report the currently active tip.
861 setTips.insert(chainActive.Tip());
863 /* Construct the output array. */
865 BOOST_FOREACH(const CBlockIndex* block, setTips)
868 obj.push_back(Pair("height", block->nHeight));
869 obj.push_back(Pair("hash", block->phashBlock->GetHex()));
871 const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
872 obj.push_back(Pair("branchlen", branchLen));
875 if (chainActive.Contains(block)) {
876 // This block is part of the currently active chain.
878 } else if (block->nStatus & BLOCK_FAILED_MASK) {
879 // This block or one of its ancestors is invalid.
881 } else if (block->nChainTx == 0) {
882 // This block cannot be connected because full block data for it or one of its parents is missing.
883 status = "headers-only";
884 } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
885 // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
886 status = "valid-fork";
887 } else if (block->IsValid(BLOCK_VALID_TREE)) {
888 // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
889 status = "valid-headers";
894 obj.push_back(Pair("status", status));
902 Value getmempoolinfo(const Array& params, bool fHelp)
904 if (fHelp || params.size() != 0)
907 "\nReturns details on the active state of the TX memory pool.\n"
910 " \"size\": xxxxx (numeric) Current tx count\n"
911 " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n"
914 + HelpExampleCli("getmempoolinfo", "")
915 + HelpExampleRpc("getmempoolinfo", "")
919 ret.push_back(Pair("size", (int64_t) mempool.size()));
920 ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
925 Value invalidateblock(const Array& params, bool fHelp)
927 if (fHelp || params.size() != 1)
929 "invalidateblock \"hash\"\n"
930 "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
932 "1. hash (string, required) the hash of the block to mark as invalid\n"
935 + HelpExampleCli("invalidateblock", "\"blockhash\"")
936 + HelpExampleRpc("invalidateblock", "\"blockhash\"")
939 std::string strHash = params[0].get_str();
940 uint256 hash(uint256S(strHash));
941 CValidationState state;
945 if (mapBlockIndex.count(hash) == 0)
946 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
948 CBlockIndex* pblockindex = mapBlockIndex[hash];
949 InvalidateBlock(state, pblockindex);
952 if (state.IsValid()) {
953 ActivateBestChain(state);
956 if (!state.IsValid()) {
957 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
963 Value reconsiderblock(const Array& params, bool fHelp)
965 if (fHelp || params.size() != 1)
967 "reconsiderblock \"hash\"\n"
968 "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
969 "This can be used to undo the effects of invalidateblock.\n"
971 "1. hash (string, required) the hash of the block to reconsider\n"
974 + HelpExampleCli("reconsiderblock", "\"blockhash\"")
975 + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
978 std::string strHash = params[0].get_str();
979 uint256 hash(uint256S(strHash));
980 CValidationState state;
984 if (mapBlockIndex.count(hash) == 0)
985 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
987 CBlockIndex* pblockindex = mapBlockIndex[hash];
988 ReconsiderBlock(state, pblockindex);
991 if (state.IsValid()) {
992 ActivateBestChain(state);
995 if (!state.IsValid()) {
996 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());