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.
8 #include "chainparams.h"
9 #include "checkpoints.h"
10 #include "consensus/validation.h"
11 #include "cc/betprotocol.h"
13 #include "primitives/transaction.h"
14 #include "rpcserver.h"
26 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
27 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
29 double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
31 // Floating point number that is a multiple of the minimum difficulty,
32 // minimum difficulty = 1.0.
33 if (blockindex == NULL)
35 if (chainActive.Tip() == NULL)
38 blockindex = chainActive.Tip();
42 if (networkDifficulty) {
43 bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus());
45 bits = blockindex->nBits;
49 UintToArith256(Params().GetConsensus().powLimit).GetCompact();
50 int nShift = (bits >> 24) & 0xff;
51 int nShiftAmount = (powLimit >> 24) & 0xff;
54 (double)(powLimit & 0x00ffffff) /
55 (double)(bits & 0x00ffffff);
57 while (nShift < nShiftAmount)
62 while (nShift > nShiftAmount)
71 double GetDifficulty(const CBlockIndex* blockindex)
73 return GetDifficultyINTERNAL(blockindex, false);
76 double GetNetworkDifficulty(const CBlockIndex* blockindex)
78 return GetDifficultyINTERNAL(blockindex, true);
81 static UniValue ValuePoolDesc(
82 const std::string &name,
83 const boost::optional<CAmount> chainValue,
84 const boost::optional<CAmount> valueDelta)
86 UniValue rv(UniValue::VOBJ);
87 rv.push_back(Pair("id", name));
88 rv.push_back(Pair("monitored", (bool)chainValue));
90 rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue)));
91 rv.push_back(Pair("chainValueZat", *chainValue));
94 rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta)));
95 rv.push_back(Pair("valueDeltaZat", *valueDelta));
100 UniValue blockheaderToJSON(const CBlockIndex* blockindex)
102 UniValue result(UniValue::VOBJ);
103 result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
104 int confirmations = -1;
105 // Only report confirmations if the block is on the main chain
106 if (chainActive.Contains(blockindex))
107 confirmations = chainActive.Height() - blockindex->nHeight + 1;
108 result.push_back(Pair("confirmations", confirmations));
109 result.push_back(Pair("height", blockindex->nHeight));
110 result.push_back(Pair("version", blockindex->nVersion));
111 result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
112 result.push_back(Pair("time", (int64_t)blockindex->nTime));
113 result.push_back(Pair("nonce", blockindex->nNonce.GetHex()));
114 result.push_back(Pair("solution", HexStr(blockindex->nSolution)));
115 result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
116 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
117 result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
119 if (blockindex->pprev)
120 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
121 CBlockIndex *pnext = chainActive.Next(blockindex);
123 result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
127 UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
129 UniValue result(UniValue::VOBJ);
130 result.push_back(Pair("hash", block.GetHash().GetHex()));
131 int confirmations = -1;
132 // Only report confirmations if the block is on the main chain
133 if (chainActive.Contains(blockindex))
134 confirmations = chainActive.Height() - blockindex->nHeight + 1;
135 result.push_back(Pair("confirmations", confirmations));
136 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
137 result.push_back(Pair("height", blockindex->nHeight));
138 result.push_back(Pair("version", block.nVersion));
139 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
140 UniValue txs(UniValue::VARR);
141 BOOST_FOREACH(const CTransaction&tx, block.vtx)
145 UniValue objTx(UniValue::VOBJ);
146 TxToJSON(tx, uint256(), objTx);
147 txs.push_back(objTx);
150 txs.push_back(tx.GetHash().GetHex());
152 result.push_back(Pair("tx", txs));
153 result.push_back(Pair("time", block.GetBlockTime()));
154 result.push_back(Pair("nonce", block.nNonce.GetHex()));
155 result.push_back(Pair("solution", HexStr(block.nSolution)));
156 result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
157 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
158 result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
159 result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex()));
161 UniValue valuePools(UniValue::VARR);
162 valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue));
163 result.push_back(Pair("valuePools", valuePools));
165 if (blockindex->pprev)
166 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
167 CBlockIndex *pnext = chainActive.Next(blockindex);
169 result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
173 UniValue getblockcount(const UniValue& params, bool fHelp)
175 if (fHelp || params.size() != 0)
178 "\nReturns the number of blocks in the best valid block chain.\n"
180 "n (numeric) The current block count\n"
182 + HelpExampleCli("getblockcount", "")
183 + HelpExampleRpc("getblockcount", "")
187 return chainActive.Height();
190 UniValue getbestblockhash(const UniValue& params, bool fHelp)
192 if (fHelp || params.size() != 0)
195 "\nReturns the hash of the best (tip) block in the longest block chain.\n"
197 "\"hex\" (string) the block hash hex encoded\n"
199 + HelpExampleCli("getbestblockhash", "")
200 + HelpExampleRpc("getbestblockhash", "")
204 return chainActive.Tip()->GetBlockHash().GetHex();
207 UniValue getdifficulty(const UniValue& params, bool fHelp)
209 if (fHelp || params.size() != 0)
212 "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
214 "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
216 + HelpExampleCli("getdifficulty", "")
217 + HelpExampleRpc("getdifficulty", "")
221 return GetNetworkDifficulty();
224 UniValue mempoolToJSON(bool fVerbose = false)
229 UniValue o(UniValue::VOBJ);
230 BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx)
232 const uint256& hash = e.GetTx().GetHash();
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)
244 if (mempool.exists(txin.prevout.hash))
245 setDepends.insert(txin.prevout.hash.ToString());
248 UniValue depends(UniValue::VARR);
249 BOOST_FOREACH(const string& dep, setDepends)
251 depends.push_back(dep);
254 info.push_back(Pair("depends", depends));
255 o.push_back(Pair(hash.ToString(), info));
261 vector<uint256> vtxid;
262 mempool.queryHashes(vtxid);
264 UniValue a(UniValue::VARR);
265 BOOST_FOREACH(const uint256& hash, vtxid)
266 a.push_back(hash.ToString());
272 UniValue getrawmempool(const UniValue& params, bool fHelp)
274 if (fHelp || params.size() > 1)
276 "getrawmempool ( verbose )\n"
277 "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\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"
285 "\nResult: (for verbose = true):\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"
300 + HelpExampleCli("getrawmempool", "true")
301 + HelpExampleRpc("getrawmempool", "true")
306 bool fVerbose = false;
307 if (params.size() > 0)
308 fVerbose = params[0].get_bool();
310 return mempoolToJSON(fVerbose);
313 UniValue getblockhash(const UniValue& params, bool fHelp)
315 if (fHelp || params.size() != 1)
317 "getblockhash index\n"
318 "\nReturns hash of block in best-block-chain at index provided.\n"
320 "1. index (numeric, required) The block index\n"
322 "\"hash\" (string) The block hash\n"
324 + HelpExampleCli("getblockhash", "1000")
325 + HelpExampleRpc("getblockhash", "1000")
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");
334 CBlockIndex* pblockindex = chainActive[nHeight];
335 return pblockindex->GetBlockHash().GetHex();
338 /*uint256 _komodo_getblockhash(int32_t nHeight)
342 if ( nHeight >= 0 && nHeight <= chainActive.Height() )
344 CBlockIndex* pblockindex = chainActive[nHeight];
345 hash = pblockindex->GetBlockHash();
348 printf("%02x",((uint8_t *)&hash)[i]);
349 printf(" blockhash.%d\n",nHeight);
350 } else memset(&hash,0,sizeof(hash));
354 UniValue getblockheader(const UniValue& params, bool fHelp)
356 if (fHelp || params.size() < 1 || params.size() > 2)
358 "getblockheader \"hash\" ( verbose )\n"
359 "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
360 "If verbose is true, returns an Object with information about blockheader <hash>.\n"
362 "1. \"hash\" (string, required) The block hash\n"
363 "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
364 "\nResult (for verbose = true):\n"
366 " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
367 " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
368 " \"height\" : n, (numeric) The block height or index\n"
369 " \"version\" : n, (numeric) The block version\n"
370 " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
371 " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
372 " \"nonce\" : n, (numeric) The nonce\n"
373 " \"bits\" : \"1d00ffff\", (string) The bits\n"
374 " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
375 " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
376 " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
378 "\nResult (for verbose=false):\n"
379 "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
381 + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
382 + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
387 std::string strHash = params[0].get_str();
388 uint256 hash(uint256S(strHash));
390 bool fVerbose = true;
391 if (params.size() > 1)
392 fVerbose = params[1].get_bool();
394 if (mapBlockIndex.count(hash) == 0)
395 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
397 CBlockIndex* pblockindex = mapBlockIndex[hash];
401 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
402 ssBlock << pblockindex->GetBlockHeader();
403 std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
407 return blockheaderToJSON(pblockindex);
410 UniValue getblock(const UniValue& params, bool fHelp)
412 if (fHelp || params.size() < 1 || params.size() > 2)
414 "getblock \"hash|height\" ( verbose )\n"
415 "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n"
416 "If verbose is true, returns an Object with information about block <hash|height>.\n"
418 "1. \"hash|height\" (string, required) The block hash or height\n"
419 "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
420 "\nResult (for verbose = true):\n"
422 " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n"
423 " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
424 " \"size\" : n, (numeric) The block size\n"
425 " \"height\" : n, (numeric) The block height or index (same as provided height)\n"
426 " \"version\" : n, (numeric) The block version\n"
427 " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
428 " \"tx\" : [ (array of string) The transaction ids\n"
429 " \"transactionid\" (string) The transaction id\n"
432 " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
433 " \"nonce\" : n, (numeric) The nonce\n"
434 " \"bits\" : \"1d00ffff\", (string) The bits\n"
435 " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
436 " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
437 " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
439 "\nResult (for verbose=false):\n"
440 "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
442 + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
443 + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
444 + HelpExampleCli("getblock", "12800")
445 + HelpExampleRpc("getblock", "12800")
450 std::string strHash = params[0].get_str();
452 // If height is supplied, find the hash
453 if (strHash.size() < (2 * sizeof(uint256))) {
454 // std::stoi allows characters, whereas we want to be strict
455 regex r("[[:digit:]]+");
456 if (!regex_match(strHash, r)) {
457 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
462 nHeight = std::stoi(strHash);
464 catch (const std::exception &e) {
465 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
468 if (nHeight < 0 || nHeight > chainActive.Height()) {
469 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
471 strHash = chainActive[nHeight]->GetBlockHash().GetHex();
474 uint256 hash(uint256S(strHash));
476 bool fVerbose = true;
477 if (params.size() > 1)
478 fVerbose = params[1].get_bool();
480 if (mapBlockIndex.count(hash) == 0)
481 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
484 CBlockIndex* pblockindex = mapBlockIndex[hash];
486 if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
487 throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
489 if(!ReadBlockFromDisk(block, pblockindex))
490 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
494 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
496 std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
500 return blockToJSON(block, pblockindex);
503 UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
505 if (fHelp || params.size() != 0)
508 "\nReturns statistics about the unspent transaction output set.\n"
509 "Note this call may take some time.\n"
512 " \"height\":n, (numeric) The current block height (index)\n"
513 " \"bestblock\": \"hex\", (string) the best block hash hex\n"
514 " \"transactions\": n, (numeric) The number of transactions\n"
515 " \"txouts\": n, (numeric) The number of output transactions\n"
516 " \"bytes_serialized\": n, (numeric) The serialized size\n"
517 " \"hash_serialized\": \"hash\", (string) The serialized hash\n"
518 " \"total_amount\": x.xxx (numeric) The total amount\n"
521 + HelpExampleCli("gettxoutsetinfo", "")
522 + HelpExampleRpc("gettxoutsetinfo", "")
525 UniValue ret(UniValue::VOBJ);
529 if (pcoinsTip->GetStats(stats)) {
530 ret.push_back(Pair("height", (int64_t)stats.nHeight));
531 ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
532 ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
533 ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
534 ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
535 ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
536 ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
541 #include "komodo_defs.h"
543 #define IGUANA_MAXSCRIPTSIZE 10001
544 #define KOMODO_KVDURATION 1440
545 #define KOMODO_KVBINARY 2
546 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
547 uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
548 uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume);
549 int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
550 int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
551 char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
552 //uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n);
553 int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width);
554 int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen);
555 int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip);
557 UniValue kvsearch(const UniValue& params, bool fHelp)
559 UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE],key[IGUANA_MAXSCRIPTSIZE]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes;
560 if (fHelp || params.size() != 1 )
561 throw runtime_error("kvsearch key");
563 if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 )
565 ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
566 ret.push_back(Pair("currentheight", (int64_t)chainActive.Tip()->nHeight));
567 ret.push_back(Pair("key",params[0].get_str()));
568 ret.push_back(Pair("keylen",keylen));
569 if ( keylen < sizeof(key) )
571 memcpy(key,params[0].get_str().c_str(),keylen);
572 if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&flags,&height,value,key,keylen)) >= 0 )
574 std::string val; char *valuestr;
575 val.resize(valuesize);
576 valuestr = (char *)val.data();
577 memcpy(valuestr,value,valuesize);
578 if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 )
579 ret.push_back(Pair("owner",refpubkey.GetHex()));
580 ret.push_back(Pair("height",height));
581 duration = ((flags >> 2) + 1) * KOMODO_KVDURATION;
582 ret.push_back(Pair("expiration", (int64_t)(height+duration)));
583 ret.push_back(Pair("flags",(int64_t)flags));
584 ret.push_back(Pair("value",val));
585 ret.push_back(Pair("valuesize",valuesize));
586 } else ret.push_back(Pair("error",(char *)"cant find key"));
587 } else ret.push_back(Pair("error",(char *)"key too big"));
588 } else ret.push_back(Pair("error",(char *)"null key"));
593 UniValue height_MoM(const UniValue& params, bool fHelp)
595 int32_t height,depth,notarized_height,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; uint256 MoM,MoMoM,kmdtxid; uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR);
596 if ( fHelp || params.size() != 1 )
597 throw runtime_error("height_MoM height\n");
599 height = atoi(params[0].get_str().c_str());
602 if ( chainActive.Tip() == 0 )
604 ret.push_back(Pair("error",(char *)"no active chain yet"));
607 height = chainActive.Tip()->nHeight;
609 //fprintf(stderr,"height_MoM height.%d\n",height);
610 depth = komodo_MoM(¬arized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi);
611 ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
612 ret.push_back(Pair("height",height));
613 ret.push_back(Pair("timestamp",(uint64_t)timestamp));
616 ret.push_back(Pair("depth",depth));
617 ret.push_back(Pair("notarized_height",notarized_height));
618 ret.push_back(Pair("MoM",MoM.GetHex()));
619 ret.push_back(Pair("kmdtxid",kmdtxid.GetHex()));
620 if ( ASSETCHAINS_SYMBOL[0] != 0 )
622 ret.push_back(Pair("MoMoM",MoMoM.GetHex()));
623 ret.push_back(Pair("MoMoMoffset",MoMoMoffset));
624 ret.push_back(Pair("MoMoMdepth",MoMoMdepth));
625 ret.push_back(Pair("kmdstarti",kmdstarti));
626 ret.push_back(Pair("kmdendi",kmdendi));
628 } else ret.push_back(Pair("error",(char *)"no MoM for height"));
633 UniValue txMoMproof(const UniValue& params, bool fHelp)
635 uint256 hash, notarisationHash, MoM,MoMoM; int32_t notarisedHeight, depth; CBlockIndex* blockIndex;
636 std::vector<uint256> branch;
637 int nIndex,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi;
639 // parse params and get notarisation data for tx
641 if ( fHelp || params.size() != 1)
642 throw runtime_error("txMoMproof needs a txid");
644 hash = uint256S(params[0].get_str());
648 if (!GetTransaction(hash, tx, blockHash, true))
649 throw runtime_error("cannot find transaction");
651 blockIndex = mapBlockIndex[blockHash];
653 depth = komodo_MoM(¬arisedHeight, &MoM, ¬arisationHash, blockIndex->nHeight,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi);
656 throw runtime_error("notarisation not found");
658 // index of block in MoM leaves
659 nIndex = notarisedHeight - blockIndex->nHeight;
662 // build merkle chain from blocks to MoM
664 // since the merkle branch code is tied up in a block class
665 // and we want to make a merkle branch for something that isnt transactions
667 for (int i=0; i<depth; i++) {
668 uint256 mRoot = chainActive[notarisedHeight - i]->hashMerkleRoot;
670 // first value in CTransaction memory is it's hash
671 memcpy((void*)&fakeTx, mRoot.begin(), 32);
672 fakeBlock.vtx.push_back(fakeTx);
674 branch = fakeBlock.GetMerkleBranch(nIndex);
677 if (MoM != CBlock::CheckMerkleBranch(blockIndex->hashMerkleRoot, branch, nIndex))
678 throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed merkle block->MoM");
681 // Now get the tx merkle branch
685 if (fHavePruned && !(blockIndex->nStatus & BLOCK_HAVE_DATA) && blockIndex->nTx > 0)
686 throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
688 if(!ReadBlockFromDisk(block, blockIndex))
689 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
691 // Locate the transaction in the block
693 for (nTxIndex = 0; nTxIndex < (int)block.vtx.size(); nTxIndex++)
694 if (block.vtx[nTxIndex].GetHash() == hash)
697 if (nTxIndex == (int)block.vtx.size())
698 throw JSONRPCError(RPC_INTERNAL_ERROR, "Error locating tx in block");
700 std::vector<uint256> txBranch = block.GetMerkleBranch(nTxIndex);
703 if (block.hashMerkleRoot != CBlock::CheckMerkleBranch(hash, txBranch, nTxIndex))
704 throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed merkle tx->block");
706 // concatenate branches
707 nIndex = (nIndex << txBranch.size()) + nTxIndex;
708 branch.insert(branch.begin(), txBranch.begin(), txBranch.end());
712 if (MoM != CBlock::CheckMerkleBranch(hash, branch, nIndex))
713 throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed validating MoM");
716 CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION);
717 ssProof << MoMProof(nIndex, branch, notarisationHash);
718 return HexStr(ssProof.begin(), ssProof.end());
722 UniValue minerids(const UniValue& params, bool fHelp)
724 uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129];
725 if ( fHelp || params.size() != 1 )
726 throw runtime_error("minerids needs height\n");
728 int32_t height = atoi(params[0].get_str().c_str());
730 height = chainActive.Tip()->nHeight;
733 CBlockIndex *pblockindex = chainActive[height];
734 if ( pblockindex != 0 )
735 timestamp = pblockindex->GetBlockTime();
737 if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 )
739 memset(tally,0,sizeof(tally));
740 numnotaries = komodo_notaries(pubkeys,height,timestamp);
741 if ( numnotaries > 0 )
745 if ( minerids[i] >= numnotaries )
747 else tally[minerids[i]]++;
751 UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m;
753 hexstr = (char *)hex.data();
755 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
756 item.push_back(Pair("notaryid", i));
758 bitcoin_address(kmdaddr,60,pubkeys[i],33);
759 m = (int32_t)strlen(kmdaddr);
760 kmdaddress.resize(m);
761 ptr = (char *)kmdaddress.data();
762 memcpy(ptr,kmdaddr,m);
763 item.push_back(Pair("KMDaddress", kmdaddress));
765 item.push_back(Pair("pubkey", hex));
766 item.push_back(Pair("blocks", tally[i]));
769 UniValue item(UniValue::VOBJ);
770 item.push_back(Pair("pubkey", (char *)"external miners"));
771 item.push_back(Pair("blocks", tally[128]));
774 ret.push_back(Pair("mined", a));
775 } else ret.push_back(Pair("error", (char *)"couldnt extract minerids"));
779 UniValue notaries(const UniValue& params, bool fHelp)
781 UniValue a(UniValue::VARR); uint32_t timestamp=0; UniValue ret(UniValue::VOBJ); int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr;
782 if ( fHelp || (params.size() != 1 && params.size() != 2) )
783 throw runtime_error("notaries height timestamp\n");
785 int32_t height = atoi(params[0].get_str().c_str());
786 if ( params.size() == 2 )
787 timestamp = (uint32_t)atol(params[1].get_str().c_str());
788 else timestamp = (uint32_t)time(NULL);
791 height = chainActive.Tip()->nHeight;
792 timestamp = chainActive.Tip()->GetBlockTime();
794 else if ( params.size() < 2 )
796 CBlockIndex *pblockindex = chainActive[height];
797 if ( pblockindex != 0 )
798 timestamp = pblockindex->GetBlockTime();
800 if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 )
804 UniValue item(UniValue::VOBJ);
805 std::string btcaddress,kmdaddress,hex;
807 hexstr = (char *)hex.data();
809 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
810 item.push_back(Pair("pubkey", hex));
812 bitcoin_address(btcaddr,0,pubkeys[i],33);
813 m = (int32_t)strlen(btcaddr);
814 btcaddress.resize(m);
815 ptr = (char *)btcaddress.data();
816 memcpy(ptr,btcaddr,m);
817 item.push_back(Pair("BTCaddress", btcaddress));
819 bitcoin_address(kmdaddr,60,pubkeys[i],33);
820 m = (int32_t)strlen(kmdaddr);
821 kmdaddress.resize(m);
822 ptr = (char *)kmdaddress.data();
823 memcpy(ptr,kmdaddr,m);
824 item.push_back(Pair("KMDaddress", kmdaddress));
828 ret.push_back(Pair("notaries", a));
829 ret.push_back(Pair("numnotaries", n));
830 ret.push_back(Pair("height", height));
831 ret.push_back(Pair("timestamp", (uint64_t)timestamp));
835 int32_t komodo_pending_withdraws(char *opretstr);
836 int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base);
837 extern char CURRENCIES[][8];
839 UniValue paxpending(const UniValue& params, bool fHelp)
841 UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); char opretbuf[10000*2]; int32_t opretlen,baseid; uint64_t available,deposited,issued,withdrawn,approved,redeemed;
842 if ( fHelp || params.size() != 0 )
843 throw runtime_error("paxpending needs no args\n");
845 if ( (opretlen= komodo_pending_withdraws(opretbuf)) > 0 )
846 ret.push_back(Pair("withdraws", opretbuf));
847 else ret.push_back(Pair("withdraws", (char *)""));
848 for (baseid=0; baseid<32; baseid++)
850 UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
851 if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 )
853 if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 )
855 item.push_back(Pair("available", ValueFromAmount(available)));
856 item.push_back(Pair("deposited", ValueFromAmount(deposited)));
857 item.push_back(Pair("issued", ValueFromAmount(issued)));
858 item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn)));
859 item.push_back(Pair("approved", ValueFromAmount(approved)));
860 item.push_back(Pair("redeemed", ValueFromAmount(redeemed)));
861 obj.push_back(Pair(CURRENCIES[baseid],item));
866 ret.push_back(Pair("fiatstatus", a));
870 UniValue paxprice(const UniValue& params, bool fHelp)
872 if ( fHelp || params.size() > 4 || params.size() < 2 )
873 throw runtime_error("paxprice \"base\" \"rel\" height\n");
875 UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed;
876 std::string base = params[0].get_str();
877 std::string rel = params[1].get_str();
879 if ( params.size() == 2 )
880 height = chainActive.Tip()->nHeight;
881 else height = atoi(params[2].get_str().c_str());
882 //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
884 relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume);
885 ret.push_back(Pair("base", base));
886 ret.push_back(Pair("rel", rel));
887 ret.push_back(Pair("height", height));
889 sprintf(seedstr,"%llu",(long long)seed);
890 ret.push_back(Pair("seed", seedstr));
891 if ( height < 0 || height > chainActive.Height() )
892 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
895 CBlockIndex *pblockindex = chainActive[height];
896 if ( pblockindex != 0 )
897 ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime));
898 if ( basevolume != 0 && relvolume != 0 )
900 ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
901 ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume)));
902 ret.push_back(Pair("basevolume",ValueFromAmount(basevolume)));
903 ret.push_back(Pair("relvolume",ValueFromAmount(relvolume)));
904 } else ret.push_back(Pair("error", "overflow or error in one or more of parameters"));
909 UniValue paxprices(const UniValue& params, bool fHelp)
911 if ( fHelp || params.size() != 3 )
912 throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
914 UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
915 std::string base = params[0].get_str();
916 std::string rel = params[1].get_str();
917 int32_t maxsamples = atoi(params[2].get_str().c_str());
918 if ( maxsamples < 1 )
920 else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
921 maxsamples = sizeof(heights)/sizeof(*heights);
922 ret.push_back(Pair("base", base));
923 ret.push_back(Pair("rel", rel));
924 n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
925 UniValue a(UniValue::VARR);
928 UniValue item(UniValue::VOBJ);
929 if ( heights[i] < 0 || heights[i] > chainActive.Height() )
930 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
933 CBlockIndex *pblockindex = chainActive[heights[i]];
935 item.push_back(Pair("t", (int64_t)pblockindex->nTime));
936 item.push_back(Pair("p", (double)prices[i] / COIN));
940 ret.push_back(Pair("array", a));
944 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
946 UniValue gettxout(const UniValue& params, bool fHelp)
948 if (fHelp || params.size() < 2 || params.size() > 3)
950 "gettxout \"txid\" n ( includemempool )\n"
951 "\nReturns details about an unspent transaction output.\n"
953 "1. \"txid\" (string, required) The transaction id\n"
954 "2. n (numeric, required) vout value\n"
955 "3. includemempool (boolean, optional) Whether to include the mempool\n"
958 " \"bestblock\" : \"hash\", (string) the block hash\n"
959 " \"confirmations\" : n, (numeric) The number of confirmations\n"
960 " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n"
961 " \"scriptPubKey\" : { (json object)\n"
962 " \"asm\" : \"code\", (string) \n"
963 " \"hex\" : \"hex\", (string) \n"
964 " \"reqSigs\" : n, (numeric) Number of required signatures\n"
965 " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
966 " \"addresses\" : [ (array of string) array of Zcash addresses\n"
967 " \"zcashaddress\" (string) Zcash address\n"
971 " \"version\" : n, (numeric) The version\n"
972 " \"coinbase\" : true|false (boolean) Coinbase or not\n"
976 "\nGet unspent transactions\n"
977 + HelpExampleCli("listunspent", "") +
978 "\nView the details\n"
979 + HelpExampleCli("gettxout", "\"txid\" 1") +
980 "\nAs a json rpc call\n"
981 + HelpExampleRpc("gettxout", "\"txid\", 1")
986 UniValue ret(UniValue::VOBJ);
988 std::string strHash = params[0].get_str();
989 uint256 hash(uint256S(strHash));
990 int n = params[1].get_int();
991 bool fMempool = true;
992 if (params.size() > 2)
993 fMempool = params[2].get_bool();
998 CCoinsViewMemPool view(pcoinsTip, mempool);
999 if (!view.GetCoins(hash, coins))
1000 return NullUniValue;
1001 mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
1003 if (!pcoinsTip->GetCoins(hash, coins))
1004 return NullUniValue;
1006 if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
1007 return NullUniValue;
1009 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
1010 CBlockIndex *pindex = it->second;
1011 ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
1012 if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
1013 ret.push_back(Pair("confirmations", 0));
1014 else ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
1015 ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
1016 uint64_t interest; int32_t txheight; uint32_t locktime;
1017 if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue,(int32_t)pindex->nHeight)) != 0 )
1018 ret.push_back(Pair("interest", ValueFromAmount(interest)));
1019 UniValue o(UniValue::VOBJ);
1020 ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
1021 ret.push_back(Pair("scriptPubKey", o));
1022 ret.push_back(Pair("version", coins.nVersion));
1023 ret.push_back(Pair("coinbase", coins.fCoinBase));
1028 UniValue verifychain(const UniValue& params, bool fHelp)
1030 if (fHelp || params.size() > 2)
1031 throw runtime_error(
1032 "verifychain ( checklevel numblocks )\n"
1033 "\nVerifies blockchain database.\n"
1035 "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
1036 "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
1038 "true|false (boolean) Verified or not\n"
1040 + HelpExampleCli("verifychain", "")
1041 + HelpExampleRpc("verifychain", "")
1046 int nCheckLevel = GetArg("-checklevel", 3);
1047 int nCheckDepth = GetArg("-checkblocks", 288);
1048 if (params.size() > 0)
1049 nCheckLevel = params[0].get_int();
1050 if (params.size() > 1)
1051 nCheckDepth = params[1].get_int();
1053 return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
1056 /** Implementation of IsSuperMajority with better feedback */
1057 static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
1060 CBlockIndex* pstart = pindex;
1061 for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
1063 if (pstart->nVersion >= minVersion)
1065 pstart = pstart->pprev;
1068 UniValue rv(UniValue::VOBJ);
1069 rv.push_back(Pair("status", nFound >= nRequired));
1070 rv.push_back(Pair("found", nFound));
1071 rv.push_back(Pair("required", nRequired));
1072 rv.push_back(Pair("window", consensusParams.nMajorityWindow));
1076 static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
1078 UniValue rv(UniValue::VOBJ);
1079 rv.push_back(Pair("id", name));
1080 rv.push_back(Pair("version", version));
1081 rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
1082 rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
1086 static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height)
1088 UniValue rv(UniValue::VOBJ);
1089 auto upgrade = NetworkUpgradeInfo[idx];
1090 rv.push_back(Pair("name", upgrade.strName));
1091 rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight));
1092 switch (NetworkUpgradeState(height, consensusParams, idx)) {
1093 case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break;
1094 case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break;
1095 case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break;
1097 rv.push_back(Pair("info", upgrade.strInfo));
1101 void NetworkUpgradeDescPushBack(
1102 UniValue& networkUpgrades,
1103 const Consensus::Params& consensusParams,
1104 Consensus::UpgradeIndex idx,
1107 // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are
1108 // hidden. This is used when network upgrade implementations are merged
1109 // without specifying the activation height.
1110 if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) {
1111 networkUpgrades.push_back(Pair(
1112 HexInt(NetworkUpgradeInfo[idx].nBranchId),
1113 NetworkUpgradeDesc(consensusParams, idx, height)));
1117 UniValue getblockchaininfo(const UniValue& params, bool fHelp)
1119 if (fHelp || params.size() != 0)
1120 throw runtime_error(
1121 "getblockchaininfo\n"
1122 "Returns an object containing various state info regarding block chain processing.\n"
1123 "\nNote that when the chain tip is at the last block before a network upgrade activation,\n"
1124 "consensus.chaintip != consensus.nextblock.\n"
1127 " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
1128 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
1129 " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
1130 " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
1131 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
1132 " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
1133 " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
1134 " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n"
1135 " \"softforks\": [ (array) status of softforks in progress\n"
1137 " \"id\": \"xxxx\", (string) name of softfork\n"
1138 " \"version\": xx, (numeric) block version\n"
1139 " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n"
1140 " \"status\": xx, (boolean) true if threshold reached\n"
1141 " \"found\": xx, (numeric) number of blocks with the new version found\n"
1142 " \"required\": xx, (numeric) number of blocks required to trigger\n"
1143 " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n"
1145 " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
1148 " \"upgrades\": { (object) status of network upgrades\n"
1149 " \"xxxx\" : { (string) branch ID of the upgrade\n"
1150 " \"name\": \"xxxx\", (string) name of upgrade\n"
1151 " \"activationheight\": xxxxxx, (numeric) block height of activation\n"
1152 " \"status\": \"xxxx\", (string) status of upgrade\n"
1153 " \"info\": \"xxxx\", (string) additional information about upgrade\n"
1156 " \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n"
1157 " \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n"
1158 " \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n"
1162 + HelpExampleCli("getblockchaininfo", "")
1163 + HelpExampleRpc("getblockchaininfo", "")
1168 UniValue obj(UniValue::VOBJ);
1169 obj.push_back(Pair("chain", Params().NetworkIDString()));
1170 obj.push_back(Pair("blocks", (int)chainActive.Height()));
1171 obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
1172 obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
1173 obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
1174 obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
1175 obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
1176 obj.push_back(Pair("pruned", fPruneMode));
1178 ZCIncrementalMerkleTree tree;
1179 pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree);
1181 obj.push_back(Pair("commitments", (uint64_t)tree.size()));
1183 obj.push_back(Pair("commitments", tree.size()));
1186 CBlockIndex* tip = chainActive.Tip();
1187 UniValue valuePools(UniValue::VARR);
1188 valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none));
1189 obj.push_back(Pair("valuePools", valuePools));
1191 const Consensus::Params& consensusParams = Params().GetConsensus();
1192 UniValue softforks(UniValue::VARR);
1193 softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
1194 softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
1195 softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
1196 obj.push_back(Pair("softforks", softforks));
1198 UniValue upgrades(UniValue::VOBJ);
1199 for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) {
1200 NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight);
1202 obj.push_back(Pair("upgrades", upgrades));
1204 UniValue consensus(UniValue::VOBJ);
1205 consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams))));
1206 consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams))));
1207 obj.push_back(Pair("consensus", consensus));
1211 CBlockIndex *block = chainActive.Tip();
1212 while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
1213 block = block->pprev;
1215 obj.push_back(Pair("pruneheight", block->nHeight));
1220 /** Comparison function for sorting the getchaintips heads. */
1221 struct CompareBlocksByHeight
1223 bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
1225 /* Make sure that unequal blocks with the same height do not compare
1226 equal. Use the pointers themselves to make a distinction. */
1228 if (a->nHeight != b->nHeight)
1229 return (a->nHeight > b->nHeight);
1235 UniValue getchaintips(const UniValue& params, bool fHelp)
1237 if (fHelp || params.size() != 0)
1238 throw runtime_error(
1240 "Return information about all known tips in the block tree,"
1241 " including the main chain as well as orphaned branches.\n"
1245 " \"height\": xxxx, (numeric) height of the chain tip\n"
1246 " \"hash\": \"xxxx\", (string) block hash of the tip\n"
1247 " \"branchlen\": 0 (numeric) zero for main chain\n"
1248 " \"status\": \"active\" (string) \"active\" for the main chain\n"
1251 " \"height\": xxxx,\n"
1252 " \"hash\": \"xxxx\",\n"
1253 " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
1254 " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
1257 "Possible values for status:\n"
1258 "1. \"invalid\" This branch contains at least one invalid block\n"
1259 "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
1260 "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
1261 "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
1262 "5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
1264 + HelpExampleCli("getchaintips", "")
1265 + HelpExampleRpc("getchaintips", "")
1270 /* Build up a list of chain tips. We start with the list of all
1271 known blocks, and successively remove blocks that appear as pprev
1272 of another block. */
1273 std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
1274 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
1275 setTips.insert(item.second);
1276 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
1278 const CBlockIndex* pprev=0;
1279 if ( item.second != 0 )
1280 pprev = item.second->pprev;
1282 setTips.erase(pprev);
1285 // Always report the currently active tip.
1286 setTips.insert(chainActive.Tip());
1288 /* Construct the output array. */
1289 UniValue res(UniValue::VARR); const CBlockIndex *forked;
1290 BOOST_FOREACH(const CBlockIndex* block, setTips)
1291 BOOST_FOREACH(const CBlockIndex* block, setTips)
1293 UniValue obj(UniValue::VOBJ);
1294 obj.push_back(Pair("height", block->nHeight));
1295 obj.push_back(Pair("hash", block->phashBlock->GetHex()));
1296 forked = chainActive.FindFork(block);
1299 const int branchLen = block->nHeight - forked->nHeight;
1300 obj.push_back(Pair("branchlen", branchLen));
1303 if (chainActive.Contains(block)) {
1304 // This block is part of the currently active chain.
1306 } else if (block->nStatus & BLOCK_FAILED_MASK) {
1307 // This block or one of its ancestors is invalid.
1309 } else if (block->nChainTx == 0) {
1310 // This block cannot be connected because full block data for it or one of its parents is missing.
1311 status = "headers-only";
1312 } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
1313 // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
1314 status = "valid-fork";
1315 } else if (block->IsValid(BLOCK_VALID_TREE)) {
1316 // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
1317 status = "valid-headers";
1322 obj.push_back(Pair("status", status));
1330 UniValue mempoolInfoToJSON()
1332 UniValue ret(UniValue::VOBJ);
1333 ret.push_back(Pair("size", (int64_t) mempool.size()));
1334 ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
1335 ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
1340 UniValue getmempoolinfo(const UniValue& params, bool fHelp)
1342 if (fHelp || params.size() != 0)
1343 throw runtime_error(
1345 "\nReturns details on the active state of the TX memory pool.\n"
1348 " \"size\": xxxxx (numeric) Current tx count\n"
1349 " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n"
1350 " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n"
1353 + HelpExampleCli("getmempoolinfo", "")
1354 + HelpExampleRpc("getmempoolinfo", "")
1357 return mempoolInfoToJSON();
1360 UniValue invalidateblock(const UniValue& params, bool fHelp)
1362 if (fHelp || params.size() != 1)
1363 throw runtime_error(
1364 "invalidateblock \"hash\"\n"
1365 "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
1367 "1. hash (string, required) the hash of the block to mark as invalid\n"
1370 + HelpExampleCli("invalidateblock", "\"blockhash\"")
1371 + HelpExampleRpc("invalidateblock", "\"blockhash\"")
1374 std::string strHash = params[0].get_str();
1375 uint256 hash(uint256S(strHash));
1376 CValidationState state;
1380 if (mapBlockIndex.count(hash) == 0)
1381 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1383 CBlockIndex* pblockindex = mapBlockIndex[hash];
1384 InvalidateBlock(state, pblockindex);
1387 if (state.IsValid()) {
1388 ActivateBestChain(state);
1391 if (!state.IsValid()) {
1392 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1395 return NullUniValue;
1398 UniValue reconsiderblock(const UniValue& params, bool fHelp)
1400 if (fHelp || params.size() != 1)
1401 throw runtime_error(
1402 "reconsiderblock \"hash\"\n"
1403 "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
1404 "This can be used to undo the effects of invalidateblock.\n"
1406 "1. hash (string, required) the hash of the block to reconsider\n"
1409 + HelpExampleCli("reconsiderblock", "\"blockhash\"")
1410 + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
1413 std::string strHash = params[0].get_str();
1414 uint256 hash(uint256S(strHash));
1415 CValidationState state;
1419 if (mapBlockIndex.count(hash) == 0)
1420 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1422 CBlockIndex* pblockindex = mapBlockIndex[hash];
1423 ReconsiderBlock(state, pblockindex);
1426 if (state.IsValid()) {
1427 ActivateBestChain(state);
1430 if (!state.IsValid()) {
1431 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1434 return NullUniValue;