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"
22 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
23 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
25 double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
27 // Floating point number that is a multiple of the minimum difficulty,
28 // minimum difficulty = 1.0.
29 if (blockindex == NULL)
31 if (chainActive.Tip() == NULL)
34 blockindex = chainActive.Tip();
38 if (networkDifficulty) {
39 bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus());
41 bits = blockindex->nBits;
45 UintToArith256(Params().GetConsensus().powLimit).GetCompact();
46 int nShift = (bits >> 24) & 0xff;
47 int nShiftAmount = (powLimit >> 24) & 0xff;
50 (double)(powLimit & 0x00ffffff) /
51 (double)(bits & 0x00ffffff);
53 while (nShift < nShiftAmount)
58 while (nShift > nShiftAmount)
67 double GetDifficulty(const CBlockIndex* blockindex)
69 return GetDifficultyINTERNAL(blockindex, false);
72 double GetNetworkDifficulty(const CBlockIndex* blockindex)
74 return GetDifficultyINTERNAL(blockindex, true);
77 UniValue blockheaderToJSON(const CBlockIndex* blockindex)
79 UniValue result(UniValue::VOBJ);
80 result.push_back(Pair("hash", blockindex->GetBlockHash().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("height", blockindex->nHeight));
87 result.push_back(Pair("version", blockindex->nVersion));
88 result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
89 result.push_back(Pair("time", (int64_t)blockindex->nTime));
90 result.push_back(Pair("nonce", blockindex->nNonce.GetHex()));
91 result.push_back(Pair("solution", HexStr(blockindex->nSolution)));
92 result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
93 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
94 result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
96 if (blockindex->pprev)
97 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
98 CBlockIndex *pnext = chainActive.Next(blockindex);
100 result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
104 UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
106 UniValue result(UniValue::VOBJ);
107 result.push_back(Pair("hash", block.GetHash().GetHex()));
108 int confirmations = -1;
109 // Only report confirmations if the block is on the main chain
110 if (chainActive.Contains(blockindex))
111 confirmations = chainActive.Height() - blockindex->nHeight + 1;
112 result.push_back(Pair("confirmations", confirmations));
113 result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
114 result.push_back(Pair("height", blockindex->nHeight));
115 result.push_back(Pair("version", block.nVersion));
116 result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
117 UniValue txs(UniValue::VARR);
118 BOOST_FOREACH(const CTransaction&tx, block.vtx)
122 UniValue objTx(UniValue::VOBJ);
123 TxToJSON(tx, uint256(), objTx);
124 txs.push_back(objTx);
127 txs.push_back(tx.GetHash().GetHex());
129 result.push_back(Pair("tx", txs));
130 result.push_back(Pair("time", block.GetBlockTime()));
131 result.push_back(Pair("nonce", block.nNonce.GetHex()));
132 result.push_back(Pair("solution", HexStr(block.nSolution)));
133 result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
134 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
135 result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
136 result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex()));
138 if (blockindex->pprev)
139 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
140 CBlockIndex *pnext = chainActive.Next(blockindex);
142 result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
146 UniValue getblockcount(const UniValue& params, bool fHelp)
148 if (fHelp || params.size() != 0)
151 "\nReturns the number of blocks in the longest block chain.\n"
153 "n (numeric) The current block count\n"
155 + HelpExampleCli("getblockcount", "")
156 + HelpExampleRpc("getblockcount", "")
160 return chainActive.Height();
163 UniValue getbestblockhash(const UniValue& params, bool fHelp)
165 if (fHelp || params.size() != 0)
168 "\nReturns the hash of the best (tip) block in the longest block chain.\n"
170 "\"hex\" (string) the block hash hex encoded\n"
172 + HelpExampleCli("getbestblockhash", "")
173 + HelpExampleRpc("getbestblockhash", "")
177 return chainActive.Tip()->GetBlockHash().GetHex();
180 UniValue getdifficulty(const UniValue& params, bool fHelp)
182 if (fHelp || params.size() != 0)
185 "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
187 "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
189 + HelpExampleCli("getdifficulty", "")
190 + HelpExampleRpc("getdifficulty", "")
194 return GetNetworkDifficulty();
197 UniValue mempoolToJSON(bool fVerbose = false)
202 UniValue o(UniValue::VOBJ);
203 BOOST_FOREACH(const PAIRTYPE(uint256, CTxMemPoolEntry)& entry, mempool.mapTx)
205 const uint256& hash = entry.first;
206 const CTxMemPoolEntry& e = entry.second;
207 UniValue info(UniValue::VOBJ);
208 info.push_back(Pair("size", (int)e.GetTxSize()));
209 info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
210 info.push_back(Pair("time", e.GetTime()));
211 info.push_back(Pair("height", (int)e.GetHeight()));
212 info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight())));
213 info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height())));
214 const CTransaction& tx = e.GetTx();
215 set<string> setDepends;
216 BOOST_FOREACH(const CTxIn& txin, tx.vin)
218 if (mempool.exists(txin.prevout.hash))
219 setDepends.insert(txin.prevout.hash.ToString());
222 UniValue depends(UniValue::VARR);
223 BOOST_FOREACH(const string& dep, setDepends)
225 depends.push_back(dep);
228 info.push_back(Pair("depends", depends));
229 o.push_back(Pair(hash.ToString(), info));
235 vector<uint256> vtxid;
236 mempool.queryHashes(vtxid);
238 UniValue a(UniValue::VARR);
239 BOOST_FOREACH(const uint256& hash, vtxid)
240 a.push_back(hash.ToString());
246 UniValue getrawmempool(const UniValue& params, bool fHelp)
248 if (fHelp || params.size() > 1)
250 "getrawmempool ( verbose )\n"
251 "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
253 "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
254 "\nResult: (for verbose = false):\n"
255 "[ (json array of string)\n"
256 " \"transactionid\" (string) The transaction id\n"
259 "\nResult: (for verbose = true):\n"
261 " \"transactionid\" : { (json object)\n"
262 " \"size\" : n, (numeric) transaction size in bytes\n"
263 " \"fee\" : n, (numeric) transaction fee in bitcoins\n"
264 " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
265 " \"height\" : n, (numeric) block height when transaction entered pool\n"
266 " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
267 " \"currentpriority\" : n, (numeric) transaction priority now\n"
268 " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
269 " \"transactionid\", (string) parent transaction id\n"
274 + HelpExampleCli("getrawmempool", "true")
275 + HelpExampleRpc("getrawmempool", "true")
280 bool fVerbose = false;
281 if (params.size() > 0)
282 fVerbose = params[0].get_bool();
284 return mempoolToJSON(fVerbose);
287 UniValue getblockhash(const UniValue& params, bool fHelp)
289 if (fHelp || params.size() != 1)
291 "getblockhash index\n"
292 "\nReturns hash of block in best-block-chain at index provided.\n"
294 "1. index (numeric, required) The block index\n"
296 "\"hash\" (string) The block hash\n"
298 + HelpExampleCli("getblockhash", "1000")
299 + HelpExampleRpc("getblockhash", "1000")
304 int nHeight = params[0].get_int();
305 if (nHeight < 0 || nHeight > chainActive.Height())
306 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
308 CBlockIndex* pblockindex = chainActive[nHeight];
309 return pblockindex->GetBlockHash().GetHex();
312 /*uint256 _komodo_getblockhash(int32_t nHeight)
316 if ( nHeight >= 0 && nHeight <= chainActive.Height() )
318 CBlockIndex* pblockindex = chainActive[nHeight];
319 hash = pblockindex->GetBlockHash();
322 printf("%02x",((uint8_t *)&hash)[i]);
323 printf(" blockhash.%d\n",nHeight);
324 } else memset(&hash,0,sizeof(hash));
328 UniValue getblockheader(const UniValue& params, bool fHelp)
330 if (fHelp || params.size() < 1 || params.size() > 2)
332 "getblockheader \"hash\" ( verbose )\n"
333 "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
334 "If verbose is true, returns an Object with information about blockheader <hash>.\n"
336 "1. \"hash\" (string, required) The block hash\n"
337 "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
338 "\nResult (for verbose = true):\n"
340 " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
341 " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
342 " \"height\" : n, (numeric) The block height or index\n"
343 " \"version\" : n, (numeric) The block version\n"
344 " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
345 " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
346 " \"nonce\" : n, (numeric) The nonce\n"
347 " \"bits\" : \"1d00ffff\", (string) The bits\n"
348 " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
349 " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
350 " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
352 "\nResult (for verbose=false):\n"
353 "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
355 + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
356 + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
361 std::string strHash = params[0].get_str();
362 uint256 hash(uint256S(strHash));
364 bool fVerbose = true;
365 if (params.size() > 1)
366 fVerbose = params[1].get_bool();
368 if (mapBlockIndex.count(hash) == 0)
369 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
371 CBlockIndex* pblockindex = mapBlockIndex[hash];
375 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
376 ssBlock << pblockindex->GetBlockHeader();
377 std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
381 return blockheaderToJSON(pblockindex);
384 UniValue getblock(const UniValue& params, bool fHelp)
386 if (fHelp || params.size() < 1 || params.size() > 2)
388 "getblock \"hash|height\" ( verbose )\n"
389 "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n"
390 "If verbose is true, returns an Object with information about block <hash|height>.\n"
392 "1. \"hash|height\" (string, required) The block hash or height\n"
393 "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
394 "\nResult (for verbose = true):\n"
396 " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n"
397 " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
398 " \"size\" : n, (numeric) The block size\n"
399 " \"height\" : n, (numeric) The block height or index (same as provided height)\n"
400 " \"version\" : n, (numeric) The block version\n"
401 " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
402 " \"tx\" : [ (array of string) The transaction ids\n"
403 " \"transactionid\" (string) The transaction id\n"
406 " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
407 " \"nonce\" : n, (numeric) The nonce\n"
408 " \"bits\" : \"1d00ffff\", (string) The bits\n"
409 " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
410 " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
411 " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
413 "\nResult (for verbose=false):\n"
414 "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
416 + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
417 + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
418 + HelpExampleCli("getblock", "12800")
419 + HelpExampleRpc("getblock", "12800")
424 std::string strHash = params[0].get_str();
426 // If height is supplied, find the hash
427 if (strHash.size() < (2 * sizeof(uint256))) {
428 // std::stoi allows characters, whereas we want to be strict
429 regex r("[[:digit:]]+");
430 if (!regex_match(strHash, r)) {
431 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
436 nHeight = std::stoi(strHash);
438 catch (const std::exception &e) {
439 throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
442 if (nHeight < 0 || nHeight > chainActive.Height()) {
443 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
445 strHash = chainActive[nHeight]->GetBlockHash().GetHex();
448 uint256 hash(uint256S(strHash));
450 bool fVerbose = true;
451 if (params.size() > 1)
452 fVerbose = params[1].get_bool();
454 if (mapBlockIndex.count(hash) == 0)
455 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
458 CBlockIndex* pblockindex = mapBlockIndex[hash];
460 if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
461 throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
463 if(!ReadBlockFromDisk(block, pblockindex))
464 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
468 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
470 std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
474 return blockToJSON(block, pblockindex);
477 UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
479 if (fHelp || params.size() != 0)
482 "\nReturns statistics about the unspent transaction output set.\n"
483 "Note this call may take some time.\n"
486 " \"height\":n, (numeric) The current block height (index)\n"
487 " \"bestblock\": \"hex\", (string) the best block hash hex\n"
488 " \"transactions\": n, (numeric) The number of transactions\n"
489 " \"txouts\": n, (numeric) The number of output transactions\n"
490 " \"bytes_serialized\": n, (numeric) The serialized size\n"
491 " \"hash_serialized\": \"hash\", (string) The serialized hash\n"
492 " \"total_amount\": x.xxx (numeric) The total amount\n"
495 + HelpExampleCli("gettxoutsetinfo", "")
496 + HelpExampleRpc("gettxoutsetinfo", "")
499 UniValue ret(UniValue::VOBJ);
503 if (pcoinsTip->GetStats(stats)) {
504 ret.push_back(Pair("height", (int64_t)stats.nHeight));
505 ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
506 ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
507 ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
508 ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
509 ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
510 ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
515 #include "komodo_defs.h"
517 #define IGUANA_MAXSCRIPTSIZE 10001
518 #define KOMODO_KVDURATION 1440
519 #define KOMODO_KVBINARY 2
520 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
521 uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
522 uint32_t komodo_txtime(uint256 hash);
523 uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume);
524 int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
525 int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
526 char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
527 //uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n);
528 int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width);
529 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);
530 /*uint64_t conv_NXTpassword(unsigned char *mysecret,unsigned char *mypublic,uint8_t *pass,int32_t passlen);
533 UniValue passphrasewif(const UniValue& params, bool fHelp)
535 UniValue ret(UniValue::VOBJ); char *passphrase,wifstr[64],coinaddr[64]; uint8_t tmptype,pubkey33[33]; void *ctx; uint256 privkey,pubkey;
536 passphrase = params[0].get_str().c_str();
537 conv_NXTpassword((void *)&privkey,(void *)&pubkey,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
539 bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,0,60);
540 bitcoin_priv2wif(0,wifstr,privkey,188);
542 ret.push_back(Pair("address",coinaddr));
543 ret.push_back(Pair("wif",wifstr));
547 UniValue kvsearch(const UniValue& params, bool fHelp)
549 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;
550 if (fHelp || params.size() != 1 )
551 throw runtime_error("kvsearch key");
553 if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 )
555 ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
556 ret.push_back(Pair("currentheight", (int64_t)chainActive.Tip()->nHeight));
557 ret.push_back(Pair("key",params[0].get_str()));
558 ret.push_back(Pair("keylen",keylen));
559 if ( keylen < sizeof(key) )
561 memcpy(key,params[0].get_str().c_str(),keylen);
562 if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&flags,&height,value,key,keylen)) >= 0 )
564 std::string val; char *valuestr;
565 val.resize(valuesize);
566 valuestr = (char *)val.data();
567 memcpy(valuestr,value,valuesize);
568 if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 )
569 ret.push_back(Pair("owner",refpubkey.GetHex()));
570 ret.push_back(Pair("height",height));
571 duration = ((flags >> 2) + 1) * KOMODO_KVDURATION;
572 ret.push_back(Pair("expiration", (int64_t)(height+duration)));
573 ret.push_back(Pair("flags",(int64_t)flags));
574 ret.push_back(Pair("value",val));
575 ret.push_back(Pair("valuesize",valuesize));
576 } else ret.push_back(Pair("error",(char *)"cant find key"));
577 } else ret.push_back(Pair("error",(char *)"key too big"));
578 } else ret.push_back(Pair("error",(char *)"null key"));
582 UniValue minerids(const UniValue& params, bool fHelp)
584 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];
585 if ( fHelp || params.size() != 1 )
586 throw runtime_error("minerids needs height\n");
588 int32_t height = atoi(params[0].get_str().c_str());
590 height = chainActive.Tip()->nHeight;
593 CBlockIndex *pblockindex = chainActive[height];
594 if ( pblockindex != 0 )
595 timestamp = pblockindex->GetBlockTime();
597 if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 )
599 memset(tally,0,sizeof(tally));
600 numnotaries = komodo_notaries(pubkeys,height,timestamp);
601 if ( numnotaries > 0 )
605 if ( minerids[i] >= numnotaries )
607 else tally[minerids[i]]++;
611 UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m;
613 hexstr = (char *)hex.data();
615 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
616 item.push_back(Pair("notaryid", i));
618 bitcoin_address(kmdaddr,60,pubkeys[i],33);
619 m = (int32_t)strlen(kmdaddr);
620 kmdaddress.resize(m);
621 ptr = (char *)kmdaddress.data();
622 memcpy(ptr,kmdaddr,m);
623 item.push_back(Pair("KMDaddress", kmdaddress));
625 item.push_back(Pair("pubkey", hex));
626 item.push_back(Pair("blocks", tally[i]));
629 UniValue item(UniValue::VOBJ);
630 item.push_back(Pair("pubkey", (char *)"external miners"));
631 item.push_back(Pair("blocks", tally[128]));
634 ret.push_back(Pair("mined", a));
635 } else ret.push_back(Pair("error", (char *)"couldnt extract minerids"));
639 UniValue notaries(const UniValue& params, bool fHelp)
641 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;
642 if ( fHelp || params.size() != 1 )
643 throw runtime_error("notaries height\n");
645 int32_t height = atoi(params[0].get_str().c_str());
648 height = chainActive.Tip()->nHeight;
649 timestamp = chainActive.Tip()->GetBlockTime();
653 CBlockIndex *pblockindex = chainActive[height];
654 if ( pblockindex != 0 )
655 timestamp = pblockindex->GetBlockTime();
657 //fprintf(stderr,"notaries as of height.%d\n",height);
658 //if ( height > chainActive.Height()+20000 )
659 // throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
662 if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 )
666 UniValue item(UniValue::VOBJ);
667 std::string btcaddress,kmdaddress,hex;
669 hexstr = (char *)hex.data();
671 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
672 item.push_back(Pair("pubkey", hex));
674 bitcoin_address(btcaddr,0,pubkeys[i],33);
675 m = (int32_t)strlen(btcaddr);
676 btcaddress.resize(m);
677 ptr = (char *)btcaddress.data();
678 memcpy(ptr,btcaddr,m);
679 item.push_back(Pair("BTCaddress", btcaddress));
681 bitcoin_address(kmdaddr,60,pubkeys[i],33);
682 m = (int32_t)strlen(kmdaddr);
683 kmdaddress.resize(m);
684 ptr = (char *)kmdaddress.data();
685 memcpy(ptr,kmdaddr,m);
686 item.push_back(Pair("KMDaddress", kmdaddress));
690 ret.push_back(Pair("notaries", a));
691 ret.push_back(Pair("numnotaries", n));
696 int32_t komodo_pending_withdraws(char *opretstr);
697 int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base);
698 extern char CURRENCIES[][8];
700 UniValue paxpending(const UniValue& params, bool fHelp)
702 UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); char opretbuf[10000*2]; int32_t opretlen,baseid; uint64_t available,deposited,issued,withdrawn,approved,redeemed;
703 if ( fHelp || params.size() != 0 )
704 throw runtime_error("paxpending needs no args\n");
706 if ( (opretlen= komodo_pending_withdraws(opretbuf)) > 0 )
707 ret.push_back(Pair("withdraws", opretbuf));
708 else ret.push_back(Pair("withdraws", (char *)""));
709 for (baseid=0; baseid<32; baseid++)
711 UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
712 if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 )
714 if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 )
716 item.push_back(Pair("available", ValueFromAmount(available)));
717 item.push_back(Pair("deposited", ValueFromAmount(deposited)));
718 item.push_back(Pair("issued", ValueFromAmount(issued)));
719 item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn)));
720 item.push_back(Pair("approved", ValueFromAmount(approved)));
721 item.push_back(Pair("redeemed", ValueFromAmount(redeemed)));
722 obj.push_back(Pair(CURRENCIES[baseid],item));
727 ret.push_back(Pair("fiatstatus", a));
731 UniValue paxprice(const UniValue& params, bool fHelp)
733 if ( fHelp || params.size() > 4 || params.size() < 2 )
734 throw runtime_error("paxprice \"base\" \"rel\" height\n");
736 UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed;
737 std::string base = params[0].get_str();
738 std::string rel = params[1].get_str();
740 if ( params.size() == 2 )
741 height = chainActive.Tip()->nHeight;
742 else height = atoi(params[2].get_str().c_str());
743 //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
745 relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume);
746 ret.push_back(Pair("base", base));
747 ret.push_back(Pair("rel", rel));
748 ret.push_back(Pair("height", height));
750 sprintf(seedstr,"%llu",(long long)seed);
751 ret.push_back(Pair("seed", seedstr));
752 if ( height < 0 || height > chainActive.Height() )
753 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
756 CBlockIndex *pblockindex = chainActive[height];
757 if ( pblockindex != 0 )
758 ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime));
759 if ( basevolume != 0 && relvolume != 0 )
761 ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
762 ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume)));
763 ret.push_back(Pair("basevolume",ValueFromAmount(basevolume)));
764 ret.push_back(Pair("relvolume",ValueFromAmount(relvolume)));
765 } else ret.push_back(Pair("error", "overflow or error in one or more of parameters"));
770 UniValue paxprices(const UniValue& params, bool fHelp)
772 if ( fHelp || params.size() != 3 )
773 throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
775 UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
776 std::string base = params[0].get_str();
777 std::string rel = params[1].get_str();
778 int32_t maxsamples = atoi(params[2].get_str().c_str());
779 if ( maxsamples < 1 )
781 else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
782 maxsamples = sizeof(heights)/sizeof(*heights);
783 ret.push_back(Pair("base", base));
784 ret.push_back(Pair("rel", rel));
785 n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
786 UniValue a(UniValue::VARR);
789 UniValue item(UniValue::VOBJ);
790 if ( heights[i] < 0 || heights[i] > chainActive.Height() )
791 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
794 CBlockIndex *pblockindex = chainActive[heights[i]];
796 item.push_back(Pair("t", (int64_t)pblockindex->nTime));
797 item.push_back(Pair("p", (double)prices[i] / COIN));
801 ret.push_back(Pair("array", a));
805 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue);
807 UniValue gettxout(const UniValue& params, bool fHelp)
809 if (fHelp || params.size() < 2 || params.size() > 3)
811 "gettxout \"txid\" n ( includemempool )\n"
812 "\nReturns details about an unspent transaction output.\n"
814 "1. \"txid\" (string, required) The transaction id\n"
815 "2. n (numeric, required) vout value\n"
816 "3. includemempool (boolean, optional) Whether to included the mem pool\n"
819 " \"bestblock\" : \"hash\", (string) the block hash\n"
820 " \"confirmations\" : n, (numeric) The number of confirmations\n"
821 " \"value\" : x.xxx, (numeric) The transaction value in btc\n"
822 " \"scriptPubKey\" : { (json object)\n"
823 " \"asm\" : \"code\", (string) \n"
824 " \"hex\" : \"hex\", (string) \n"
825 " \"reqSigs\" : n, (numeric) Number of required signatures\n"
826 " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
827 " \"addresses\" : [ (array of string) array of bitcoin addresses\n"
828 " \"bitcoinaddress\" (string) bitcoin address\n"
832 " \"version\" : n, (numeric) The version\n"
833 " \"coinbase\" : true|false (boolean) Coinbase or not\n"
837 "\nGet unspent transactions\n"
838 + HelpExampleCli("listunspent", "") +
839 "\nView the details\n"
840 + HelpExampleCli("gettxout", "\"txid\" 1") +
841 "\nAs a json rpc call\n"
842 + HelpExampleRpc("gettxout", "\"txid\", 1")
847 UniValue ret(UniValue::VOBJ);
849 std::string strHash = params[0].get_str();
850 uint256 hash(uint256S(strHash));
851 int n = params[1].get_int();
852 bool fMempool = true;
853 if (params.size() > 2)
854 fMempool = params[2].get_bool();
859 CCoinsViewMemPool view(pcoinsTip, mempool);
860 if (!view.GetCoins(hash, coins))
862 mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
864 if (!pcoinsTip->GetCoins(hash, coins))
867 if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
870 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
871 CBlockIndex *pindex = it->second;
872 ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
873 if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
874 ret.push_back(Pair("confirmations", 0));
875 else ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
876 ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
877 uint64_t interest; int32_t txheight; uint32_t locktime;
878 if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue)) != 0 )
879 ret.push_back(Pair("interest", ValueFromAmount(interest)));
880 UniValue o(UniValue::VOBJ);
881 ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
882 ret.push_back(Pair("scriptPubKey", o));
883 ret.push_back(Pair("version", coins.nVersion));
884 ret.push_back(Pair("coinbase", coins.fCoinBase));
889 UniValue verifychain(const UniValue& params, bool fHelp)
891 if (fHelp || params.size() > 2)
893 "verifychain ( checklevel numblocks )\n"
894 "\nVerifies blockchain database.\n"
896 "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
897 "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
899 "true|false (boolean) Verified or not\n"
901 + HelpExampleCli("verifychain", "")
902 + HelpExampleRpc("verifychain", "")
907 int nCheckLevel = GetArg("-checklevel", 3);
908 int nCheckDepth = GetArg("-checkblocks", 288);
909 if (params.size() > 0)
910 nCheckLevel = params[0].get_int();
911 if (params.size() > 1)
912 nCheckDepth = params[1].get_int();
914 return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
917 /** Implementation of IsSuperMajority with better feedback */
918 static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
921 CBlockIndex* pstart = pindex;
922 for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
924 if (pstart->nVersion >= minVersion)
926 pstart = pstart->pprev;
929 UniValue rv(UniValue::VOBJ);
930 rv.push_back(Pair("status", nFound >= nRequired));
931 rv.push_back(Pair("found", nFound));
932 rv.push_back(Pair("required", nRequired));
933 rv.push_back(Pair("window", consensusParams.nMajorityWindow));
937 static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
939 UniValue rv(UniValue::VOBJ);
940 rv.push_back(Pair("id", name));
941 rv.push_back(Pair("version", version));
942 rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
943 rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
947 UniValue getblockchaininfo(const UniValue& params, bool fHelp)
949 if (fHelp || params.size() != 0)
951 "getblockchaininfo\n"
952 "Returns an object containing various state info regarding block chain processing.\n"
955 " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
956 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
957 " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
958 " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
959 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
960 " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
961 " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
962 " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n"
963 " \"softforks\": [ (array) status of softforks in progress\n"
965 " \"id\": \"xxxx\", (string) name of softfork\n"
966 " \"version\": xx, (numeric) block version\n"
967 " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n"
968 " \"status\": xx, (boolean) true if threshold reached\n"
969 " \"found\": xx, (numeric) number of blocks with the new version found\n"
970 " \"required\": xx, (numeric) number of blocks required to trigger\n"
971 " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n"
973 " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
978 + HelpExampleCli("getblockchaininfo", "")
979 + HelpExampleRpc("getblockchaininfo", "")
984 UniValue obj(UniValue::VOBJ);
985 obj.push_back(Pair("chain", Params().NetworkIDString()));
986 obj.push_back(Pair("blocks", (int)chainActive.Height()));
987 obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
988 obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
989 obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
990 obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
991 obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
992 obj.push_back(Pair("pruned", fPruneMode));
994 ZCIncrementalMerkleTree tree;
995 pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree);
997 obj.push_back(Pair("commitments", (uint64_t)tree.size()));
999 obj.push_back(Pair("commitments", tree.size()));
1002 const Consensus::Params& consensusParams = Params().GetConsensus();
1003 CBlockIndex* tip = chainActive.Tip();
1004 UniValue softforks(UniValue::VARR);
1005 softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
1006 softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
1007 softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
1008 obj.push_back(Pair("softforks", softforks));
1012 CBlockIndex *block = chainActive.Tip();
1013 while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
1014 block = block->pprev;
1016 obj.push_back(Pair("pruneheight", block->nHeight));
1021 /** Comparison function for sorting the getchaintips heads. */
1022 struct CompareBlocksByHeight
1024 bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
1026 /* Make sure that unequal blocks with the same height do not compare
1027 equal. Use the pointers themselves to make a distinction. */
1029 if (a->nHeight != b->nHeight)
1030 return (a->nHeight > b->nHeight);
1036 UniValue getchaintips(const UniValue& params, bool fHelp)
1038 if (fHelp || params.size() != 0)
1039 throw runtime_error(
1041 "Return information about all known tips in the block tree,"
1042 " including the main chain as well as orphaned branches.\n"
1046 " \"height\": xxxx, (numeric) height of the chain tip\n"
1047 " \"hash\": \"xxxx\", (string) block hash of the tip\n"
1048 " \"branchlen\": 0 (numeric) zero for main chain\n"
1049 " \"status\": \"active\" (string) \"active\" for the main chain\n"
1052 " \"height\": xxxx,\n"
1053 " \"hash\": \"xxxx\",\n"
1054 " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
1055 " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
1058 "Possible values for status:\n"
1059 "1. \"invalid\" This branch contains at least one invalid block\n"
1060 "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
1061 "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
1062 "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
1063 "5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
1065 + HelpExampleCli("getchaintips", "")
1066 + HelpExampleRpc("getchaintips", "")
1071 /* Build up a list of chain tips. We start with the list of all
1072 known blocks, and successively remove blocks that appear as pprev
1073 of another block. */
1074 std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
1075 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
1076 setTips.insert(item.second);
1077 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
1079 const CBlockIndex* pprev=0;
1080 if ( item.second != 0 )
1081 pprev = item.second->pprev;
1083 setTips.erase(pprev);
1086 // Always report the currently active tip.
1087 setTips.insert(chainActive.Tip());
1089 /* Construct the output array. */
1090 UniValue res(UniValue::VARR); const CBlockIndex *forked;
1091 BOOST_FOREACH(const CBlockIndex* block, setTips)
1092 BOOST_FOREACH(const CBlockIndex* block, setTips)
1094 UniValue obj(UniValue::VOBJ);
1095 obj.push_back(Pair("height", block->nHeight));
1096 obj.push_back(Pair("hash", block->phashBlock->GetHex()));
1097 forked = chainActive.FindFork(block);
1100 const int branchLen = block->nHeight - forked->nHeight;
1101 obj.push_back(Pair("branchlen", branchLen));
1104 if (chainActive.Contains(block)) {
1105 // This block is part of the currently active chain.
1107 } else if (block->nStatus & BLOCK_FAILED_MASK) {
1108 // This block or one of its ancestors is invalid.
1110 } else if (block->nChainTx == 0) {
1111 // This block cannot be connected because full block data for it or one of its parents is missing.
1112 status = "headers-only";
1113 } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
1114 // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
1115 status = "valid-fork";
1116 } else if (block->IsValid(BLOCK_VALID_TREE)) {
1117 // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
1118 status = "valid-headers";
1123 obj.push_back(Pair("status", status));
1131 UniValue mempoolInfoToJSON()
1133 UniValue ret(UniValue::VOBJ);
1134 ret.push_back(Pair("size", (int64_t) mempool.size()));
1135 ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
1136 ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
1141 UniValue getmempoolinfo(const UniValue& params, bool fHelp)
1143 if (fHelp || params.size() != 0)
1144 throw runtime_error(
1146 "\nReturns details on the active state of the TX memory pool.\n"
1149 " \"size\": xxxxx (numeric) Current tx count\n"
1150 " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n"
1151 " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n"
1154 + HelpExampleCli("getmempoolinfo", "")
1155 + HelpExampleRpc("getmempoolinfo", "")
1158 return mempoolInfoToJSON();
1161 UniValue invalidateblock(const UniValue& params, bool fHelp)
1163 if (fHelp || params.size() != 1)
1164 throw runtime_error(
1165 "invalidateblock \"hash\"\n"
1166 "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
1168 "1. hash (string, required) the hash of the block to mark as invalid\n"
1171 + HelpExampleCli("invalidateblock", "\"blockhash\"")
1172 + HelpExampleRpc("invalidateblock", "\"blockhash\"")
1175 std::string strHash = params[0].get_str();
1176 uint256 hash(uint256S(strHash));
1177 CValidationState state;
1181 if (mapBlockIndex.count(hash) == 0)
1182 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1184 CBlockIndex* pblockindex = mapBlockIndex[hash];
1185 InvalidateBlock(state, pblockindex);
1188 if (state.IsValid()) {
1189 ActivateBestChain(state);
1192 if (!state.IsValid()) {
1193 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1196 return NullUniValue;
1199 UniValue reconsiderblock(const UniValue& params, bool fHelp)
1201 if (fHelp || params.size() != 1)
1202 throw runtime_error(
1203 "reconsiderblock \"hash\"\n"
1204 "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
1205 "This can be used to undo the effects of invalidateblock.\n"
1207 "1. hash (string, required) the hash of the block to reconsider\n"
1210 + HelpExampleCli("reconsiderblock", "\"blockhash\"")
1211 + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
1214 std::string strHash = params[0].get_str();
1215 uint256 hash(uint256S(strHash));
1216 CValidationState state;
1220 if (mapBlockIndex.count(hash) == 0)
1221 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1223 CBlockIndex* pblockindex = mapBlockIndex[hash];
1224 ReconsiderBlock(state, pblockindex);
1227 if (state.IsValid()) {
1228 ActivateBestChain(state);
1231 if (!state.IsValid()) {
1232 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1235 return NullUniValue;