]> Git Repo - VerusCoin.git/blob - src/rpcblockchain.cpp
Merge branch 'beta' into dev
[VerusCoin.git] / src / rpcblockchain.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "checkpoints.h"
7 #include "consensus/validation.h"
8 #include "main.h"
9 #include "primitives/transaction.h"
10 #include "rpcserver.h"
11 #include "sync.h"
12 #include "util.h"
13
14 #include <stdint.h>
15
16 #include <univalue.h>
17
18 #include <regex>
19
20 using namespace std;
21
22 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
23 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
24
25 double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
26 {
27     // Floating point number that is a multiple of the minimum difficulty,
28     // minimum difficulty = 1.0.
29     if (blockindex == NULL)
30     {
31         if (chainActive.Tip() == NULL)
32             return 1.0;
33         else
34             blockindex = chainActive.Tip();
35     }
36
37     uint32_t bits;
38     if (networkDifficulty) {
39         bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus());
40     } else {
41         bits = blockindex->nBits;
42     }
43
44     uint32_t powLimit =
45         UintToArith256(Params().GetConsensus().powLimit).GetCompact();
46     int nShift = (bits >> 24) & 0xff;
47     int nShiftAmount = (powLimit >> 24) & 0xff;
48
49     double dDiff =
50         (double)(powLimit & 0x00ffffff) /
51         (double)(bits & 0x00ffffff);
52
53     while (nShift < nShiftAmount)
54     {
55         dDiff *= 256.0;
56         nShift++;
57     }
58     while (nShift > nShiftAmount)
59     {
60         dDiff /= 256.0;
61         nShift--;
62     }
63
64     return dDiff;
65 }
66
67 double GetDifficulty(const CBlockIndex* blockindex)
68 {
69     return GetDifficultyINTERNAL(blockindex, false);
70 }
71
72 double GetNetworkDifficulty(const CBlockIndex* blockindex)
73 {
74     return GetDifficultyINTERNAL(blockindex, true);
75 }
76
77 UniValue blockheaderToJSON(const CBlockIndex* blockindex)
78 {
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()));
95
96     if (blockindex->pprev)
97         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
98     CBlockIndex *pnext = chainActive.Next(blockindex);
99     if (pnext)
100         result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
101     return result;
102 }
103
104 UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
105 {
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)
119     {
120         if(txDetails)
121         {
122             UniValue objTx(UniValue::VOBJ);
123             TxToJSON(tx, uint256(), objTx);
124             txs.push_back(objTx);
125         }
126         else
127             txs.push_back(tx.GetHash().GetHex());
128     }
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()));
137
138     if (blockindex->pprev)
139         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
140     CBlockIndex *pnext = chainActive.Next(blockindex);
141     if (pnext)
142         result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
143     return result;
144 }
145
146 UniValue getblockcount(const UniValue& params, bool fHelp)
147 {
148     if (fHelp || params.size() != 0)
149         throw runtime_error(
150             "getblockcount\n"
151             "\nReturns the number of blocks in the longest block chain.\n"
152             "\nResult:\n"
153             "n    (numeric) The current block count\n"
154             "\nExamples:\n"
155             + HelpExampleCli("getblockcount", "")
156             + HelpExampleRpc("getblockcount", "")
157         );
158
159     LOCK(cs_main);
160     return chainActive.Height();
161 }
162
163 UniValue getbestblockhash(const UniValue& params, bool fHelp)
164 {
165     if (fHelp || params.size() != 0)
166         throw runtime_error(
167             "getbestblockhash\n"
168             "\nReturns the hash of the best (tip) block in the longest block chain.\n"
169             "\nResult\n"
170             "\"hex\"      (string) the block hash hex encoded\n"
171             "\nExamples\n"
172             + HelpExampleCli("getbestblockhash", "")
173             + HelpExampleRpc("getbestblockhash", "")
174         );
175
176     LOCK(cs_main);
177     return chainActive.Tip()->GetBlockHash().GetHex();
178 }
179
180 UniValue getdifficulty(const UniValue& params, bool fHelp)
181 {
182     if (fHelp || params.size() != 0)
183         throw runtime_error(
184             "getdifficulty\n"
185             "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
186             "\nResult:\n"
187             "n.nnn       (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
188             "\nExamples:\n"
189             + HelpExampleCli("getdifficulty", "")
190             + HelpExampleRpc("getdifficulty", "")
191         );
192
193     LOCK(cs_main);
194     return GetNetworkDifficulty();
195 }
196
197 UniValue mempoolToJSON(bool fVerbose = false)
198 {
199     if (fVerbose)
200     {
201         LOCK(mempool.cs);
202         UniValue o(UniValue::VOBJ);
203         BOOST_FOREACH(const PAIRTYPE(uint256, CTxMemPoolEntry)& entry, mempool.mapTx)
204         {
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)
217             {
218                 if (mempool.exists(txin.prevout.hash))
219                     setDepends.insert(txin.prevout.hash.ToString());
220             }
221
222             UniValue depends(UniValue::VARR);
223             BOOST_FOREACH(const string& dep, setDepends)
224             {
225                 depends.push_back(dep);
226             }
227
228             info.push_back(Pair("depends", depends));
229             o.push_back(Pair(hash.ToString(), info));
230         }
231         return o;
232     }
233     else
234     {
235         vector<uint256> vtxid;
236         mempool.queryHashes(vtxid);
237
238         UniValue a(UniValue::VARR);
239         BOOST_FOREACH(const uint256& hash, vtxid)
240             a.push_back(hash.ToString());
241
242         return a;
243     }
244 }
245
246 UniValue getrawmempool(const UniValue& params, bool fHelp)
247 {
248     if (fHelp || params.size() > 1)
249         throw runtime_error(
250             "getrawmempool ( verbose )\n"
251             "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
252             "\nArguments:\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"
257             "  ,...\n"
258             "]\n"
259             "\nResult: (for verbose = true):\n"
260             "{                           (json object)\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"
270             "       ... ]\n"
271             "  }, ...\n"
272             "}\n"
273             "\nExamples\n"
274             + HelpExampleCli("getrawmempool", "true")
275             + HelpExampleRpc("getrawmempool", "true")
276         );
277
278     LOCK(cs_main);
279
280     bool fVerbose = false;
281     if (params.size() > 0)
282         fVerbose = params[0].get_bool();
283
284     return mempoolToJSON(fVerbose);
285 }
286
287 UniValue getblockhash(const UniValue& params, bool fHelp)
288 {
289     if (fHelp || params.size() != 1)
290         throw runtime_error(
291             "getblockhash index\n"
292             "\nReturns hash of block in best-block-chain at index provided.\n"
293             "\nArguments:\n"
294             "1. index         (numeric, required) The block index\n"
295             "\nResult:\n"
296             "\"hash\"         (string) The block hash\n"
297             "\nExamples:\n"
298             + HelpExampleCli("getblockhash", "1000")
299             + HelpExampleRpc("getblockhash", "1000")
300         );
301
302     LOCK(cs_main);
303
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");
307
308     CBlockIndex* pblockindex = chainActive[nHeight];
309     return pblockindex->GetBlockHash().GetHex();
310 }
311
312 /*uint256 _komodo_getblockhash(int32_t nHeight)
313 {
314     uint256 hash;
315     LOCK(cs_main);
316     if ( nHeight >= 0 && nHeight <= chainActive.Height() )
317     {
318         CBlockIndex* pblockindex = chainActive[nHeight];
319         hash = pblockindex->GetBlockHash();
320         int32_t i;
321         for (i=0; i<32; i++)
322             printf("%02x",((uint8_t *)&hash)[i]);
323         printf(" blockhash.%d\n",nHeight);
324     } else memset(&hash,0,sizeof(hash));
325     return(hash);
326 }*/
327
328 UniValue getblockheader(const UniValue& params, bool fHelp)
329 {
330     if (fHelp || params.size() < 1 || params.size() > 2)
331         throw runtime_error(
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"
335             "\nArguments:\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"
339             "{\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"
351             "}\n"
352             "\nResult (for verbose=false):\n"
353             "\"data\"             (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
354             "\nExamples:\n"
355             + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
356             + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
357         );
358
359     LOCK(cs_main);
360
361     std::string strHash = params[0].get_str();
362     uint256 hash(uint256S(strHash));
363
364     bool fVerbose = true;
365     if (params.size() > 1)
366         fVerbose = params[1].get_bool();
367
368     if (mapBlockIndex.count(hash) == 0)
369         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
370
371     CBlockIndex* pblockindex = mapBlockIndex[hash];
372
373     if (!fVerbose)
374     {
375         CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
376         ssBlock << pblockindex->GetBlockHeader();
377         std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
378         return strHex;
379     }
380
381     return blockheaderToJSON(pblockindex);
382 }
383
384 UniValue getblock(const UniValue& params, bool fHelp)
385 {
386     if (fHelp || params.size() < 1 || params.size() > 2)
387         throw runtime_error(
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"
391             "\nArguments:\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"
395             "{\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"
404             "     ,...\n"
405             "  ],\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"
412             "}\n"
413             "\nResult (for verbose=false):\n"
414             "\"data\"             (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
415             "\nExamples:\n"
416             + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
417             + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
418             + HelpExampleCli("getblock", "12800")
419             + HelpExampleRpc("getblock", "12800")
420         );
421
422     LOCK(cs_main);
423
424     std::string strHash = params[0].get_str();
425
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");
432         }
433
434         int nHeight = -1;
435         try {
436             nHeight = std::stoi(strHash);
437         }
438         catch (const std::exception &e) {
439             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
440         }
441
442         if (nHeight < 0 || nHeight > chainActive.Height()) {
443             throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
444         }
445         strHash = chainActive[nHeight]->GetBlockHash().GetHex();
446     }
447
448     uint256 hash(uint256S(strHash));
449
450     bool fVerbose = true;
451     if (params.size() > 1)
452         fVerbose = params[1].get_bool();
453
454     if (mapBlockIndex.count(hash) == 0)
455         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
456
457     CBlock block;
458     CBlockIndex* pblockindex = mapBlockIndex[hash];
459
460     if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
461         throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
462
463     if(!ReadBlockFromDisk(block, pblockindex))
464         throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
465
466     if (!fVerbose)
467     {
468         CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
469         ssBlock << block;
470         std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
471         return strHex;
472     }
473
474     return blockToJSON(block, pblockindex);
475 }
476
477 UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
478 {
479     if (fHelp || params.size() != 0)
480         throw runtime_error(
481             "gettxoutsetinfo\n"
482             "\nReturns statistics about the unspent transaction output set.\n"
483             "Note this call may take some time.\n"
484             "\nResult:\n"
485             "{\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"
493             "}\n"
494             "\nExamples:\n"
495             + HelpExampleCli("gettxoutsetinfo", "")
496             + HelpExampleRpc("gettxoutsetinfo", "")
497         );
498
499     UniValue ret(UniValue::VOBJ);
500
501     CCoinsStats stats;
502     FlushStateToDisk();
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)));
511     }
512     return ret;
513 }
514
515 #include "komodo_defs.h"
516
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);
531
532
533 UniValue passphrasewif(const UniValue& params, bool fHelp)
534 {
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));
538     ctx = bitcoin_ctx();
539     bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,0,60);
540     bitcoin_priv2wif(0,wifstr,privkey,188);
541     free(ctx);
542     ret.push_back(Pair("address",coinaddr));
543     ret.push_back(Pair("wif",wifstr));
544     return ret;
545 }*/
546
547 UniValue kvsearch(const UniValue& params, bool fHelp)
548 {
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");
552     LOCK(cs_main);
553     if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 )
554     {
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) )
560         {
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 )
563             {
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"));
579     return ret;
580 }
581
582 UniValue minerids(const UniValue& params, bool fHelp)
583 {
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");
587     LOCK(cs_main);
588     int32_t height = atoi(params[0].get_str().c_str());
589     if ( height <= 0 )
590         height = chainActive.Tip()->nHeight;
591     else
592     {
593         CBlockIndex *pblockindex = chainActive[height];
594         if ( pblockindex != 0 )
595             timestamp = pblockindex->GetBlockTime();
596     }
597     if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 )
598     {
599         memset(tally,0,sizeof(tally));
600         numnotaries = komodo_notaries(pubkeys,height,timestamp);
601         if ( numnotaries > 0 )
602         {
603             for (i=0; i<n; i++)
604             {
605                 if ( minerids[i] >= numnotaries )
606                     tally[128]++;
607                 else tally[minerids[i]]++;
608             }
609             for (i=0; i<64; i++)
610             {
611                 UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m;
612                 hex.resize(66);
613                 hexstr = (char *)hex.data();
614                 for (j=0; j<33; j++)
615                     sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
616                 item.push_back(Pair("notaryid", i));
617
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));
624
625                 item.push_back(Pair("pubkey", hex));
626                 item.push_back(Pair("blocks", tally[i]));
627                 a.push_back(item);
628             }
629             UniValue item(UniValue::VOBJ);
630             item.push_back(Pair("pubkey", (char *)"external miners"));
631             item.push_back(Pair("blocks", tally[128]));
632             a.push_back(item);
633         }
634         ret.push_back(Pair("mined", a));
635     } else ret.push_back(Pair("error", (char *)"couldnt extract minerids"));
636     return ret;
637 }
638
639 UniValue notaries(const UniValue& params, bool fHelp)
640 {
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");
644     LOCK(cs_main);
645     int32_t height = atoi(params[0].get_str().c_str());
646     if ( height < 0 )
647     {
648         height = chainActive.Tip()->nHeight;
649         timestamp = chainActive.Tip()->GetBlockTime();
650     }
651     else
652     {
653         CBlockIndex *pblockindex = chainActive[height];
654         if ( pblockindex != 0 )
655             timestamp = pblockindex->GetBlockTime();
656     }
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");
660     //else
661     {
662         if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 )
663         {
664             for (i=0; i<n; i++)
665             {
666                 UniValue item(UniValue::VOBJ);
667                 std::string btcaddress,kmdaddress,hex;
668                 hex.resize(66);
669                 hexstr = (char *)hex.data();
670                 for (j=0; j<33; j++)
671                     sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
672                 item.push_back(Pair("pubkey", hex));
673
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));
680
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));
687                 a.push_back(item);
688             }
689         }
690         ret.push_back(Pair("notaries", a));
691         ret.push_back(Pair("numnotaries", n));
692     }
693     return ret;
694 }
695
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];
699
700 UniValue paxpending(const UniValue& params, bool fHelp)
701 {
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");
705     LOCK(cs_main);
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++)
710     {
711         UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
712         if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 )
713         {
714             if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 )
715             {
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));
723                 a.push_back(obj);
724             }
725         }
726     }
727     ret.push_back(Pair("fiatstatus", a));
728     return ret;
729 }
730
731 UniValue paxprice(const UniValue& params, bool fHelp)
732 {
733     if ( fHelp || params.size() > 4 || params.size() < 2 )
734         throw runtime_error("paxprice \"base\" \"rel\" height\n");
735     LOCK(cs_main);
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();
739     int32_t height;
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 )
744         basevolume = 100000;
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));
749     char seedstr[32];
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");
754     else
755     {
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 )
760         {
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"));
766     }
767     return ret;
768 }
769
770 UniValue paxprices(const UniValue& params, bool fHelp)
771 {
772     if ( fHelp || params.size() != 3 )
773         throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
774     LOCK(cs_main);
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 )
780         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);
787     for (i=0; i<n; i++)
788     {
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");
792         else
793         {
794             CBlockIndex *pblockindex = chainActive[heights[i]];
795
796             item.push_back(Pair("t", (int64_t)pblockindex->nTime));
797             item.push_back(Pair("p", (double)prices[i] / COIN));
798             a.push_back(item);
799         }
800     }
801     ret.push_back(Pair("array", a));
802     return ret;
803 }
804
805 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue);
806
807 UniValue gettxout(const UniValue& params, bool fHelp)
808 {
809     if (fHelp || params.size() < 2 || params.size() > 3)
810         throw runtime_error(
811             "gettxout \"txid\" n ( includemempool )\n"
812             "\nReturns details about an unspent transaction output.\n"
813             "\nArguments:\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"
817             "\nResult:\n"
818             "{\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"
829             "        ,...\n"
830             "     ]\n"
831             "  },\n"
832             "  \"version\" : n,            (numeric) The version\n"
833             "  \"coinbase\" : true|false   (boolean) Coinbase or not\n"
834             "}\n"
835
836             "\nExamples:\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")
843         );
844
845     LOCK(cs_main);
846
847     UniValue ret(UniValue::VOBJ);
848
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();
855
856     CCoins coins;
857     if (fMempool) {
858         LOCK(mempool.cs);
859         CCoinsViewMemPool view(pcoinsTip, mempool);
860         if (!view.GetCoins(hash, coins))
861             return NullUniValue;
862         mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
863     } else {
864         if (!pcoinsTip->GetCoins(hash, coins))
865             return NullUniValue;
866     }
867     if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
868         return NullUniValue;
869
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));
885
886     return ret;
887 }
888
889 UniValue verifychain(const UniValue& params, bool fHelp)
890 {
891     if (fHelp || params.size() > 2)
892         throw runtime_error(
893             "verifychain ( checklevel numblocks )\n"
894             "\nVerifies blockchain database.\n"
895             "\nArguments:\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"
898             "\nResult:\n"
899             "true|false       (boolean) Verified or not\n"
900             "\nExamples:\n"
901             + HelpExampleCli("verifychain", "")
902             + HelpExampleRpc("verifychain", "")
903         );
904
905     LOCK(cs_main);
906
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();
913
914     return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
915 }
916
917 /** Implementation of IsSuperMajority with better feedback */
918 static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
919 {
920     int nFound = 0;
921     CBlockIndex* pstart = pindex;
922     for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
923     {
924         if (pstart->nVersion >= minVersion)
925             ++nFound;
926         pstart = pstart->pprev;
927     }
928
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));
934     return rv;
935 }
936
937 static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
938 {
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)));
944     return rv;
945 }
946
947 UniValue getblockchaininfo(const UniValue& params, bool fHelp)
948 {
949     if (fHelp || params.size() != 0)
950         throw runtime_error(
951             "getblockchaininfo\n"
952             "Returns an object containing various state info regarding block chain processing.\n"
953             "\nResult:\n"
954             "{\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"
964             "     {\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"
972             "        },\n"
973             "        \"reject\": { ... }      (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
974             "     }, ...\n"
975             "  ]\n"
976             "}\n"
977             "\nExamples:\n"
978             + HelpExampleCli("getblockchaininfo", "")
979             + HelpExampleRpc("getblockchaininfo", "")
980         );
981
982     LOCK(cs_main);
983
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));
993
994     ZCIncrementalMerkleTree tree;
995     pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree);
996     #ifdef __APPLE__
997     obj.push_back(Pair("commitments",           (uint64_t)tree.size()));
998     #else
999     obj.push_back(Pair("commitments",           tree.size()));
1000     #endif
1001
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));
1009
1010     if (fPruneMode)
1011     {
1012         CBlockIndex *block = chainActive.Tip();
1013         while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
1014             block = block->pprev;
1015
1016         obj.push_back(Pair("pruneheight",        block->nHeight));
1017     }
1018     return obj;
1019 }
1020
1021 /** Comparison function for sorting the getchaintips heads.  */
1022 struct CompareBlocksByHeight
1023 {
1024     bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
1025     {
1026         /* Make sure that unequal blocks with the same height do not compare
1027            equal. Use the pointers themselves to make a distinction. */
1028
1029         if (a->nHeight != b->nHeight)
1030           return (a->nHeight > b->nHeight);
1031
1032         return a < b;
1033     }
1034 };
1035
1036 UniValue getchaintips(const UniValue& params, bool fHelp)
1037 {
1038     if (fHelp || params.size() != 0)
1039         throw runtime_error(
1040             "getchaintips\n"
1041             "Return information about all known tips in the block tree,"
1042             " including the main chain as well as orphaned branches.\n"
1043             "\nResult:\n"
1044             "[\n"
1045             "  {\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"
1050             "  },\n"
1051             "  {\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"
1056             "  }\n"
1057             "]\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"
1064             "\nExamples:\n"
1065             + HelpExampleCli("getchaintips", "")
1066             + HelpExampleRpc("getchaintips", "")
1067         );
1068
1069     LOCK(cs_main);
1070
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)
1078     {
1079         const CBlockIndex* pprev=0;
1080         if ( item.second != 0 )
1081             pprev = item.second->pprev;
1082         if (pprev)
1083             setTips.erase(pprev);
1084     }
1085
1086     // Always report the currently active tip.
1087     setTips.insert(chainActive.Tip());
1088
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)
1093         {
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);
1098             if ( forked != 0 )
1099             {
1100                 const int branchLen = block->nHeight - forked->nHeight;
1101                 obj.push_back(Pair("branchlen", branchLen));
1102
1103                 string status;
1104                 if (chainActive.Contains(block)) {
1105                     // This block is part of the currently active chain.
1106                     status = "active";
1107                 } else if (block->nStatus & BLOCK_FAILED_MASK) {
1108                     // This block or one of its ancestors is invalid.
1109                     status = "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";
1119                 } else {
1120                     // No clue.
1121                     status = "unknown";
1122                 }
1123                 obj.push_back(Pair("status", status));
1124             }
1125             res.push_back(obj);
1126         }
1127
1128     return res;
1129 }
1130
1131 UniValue mempoolInfoToJSON()
1132 {
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()));
1137
1138     return ret;
1139 }
1140
1141 UniValue getmempoolinfo(const UniValue& params, bool fHelp)
1142 {
1143     if (fHelp || params.size() != 0)
1144         throw runtime_error(
1145             "getmempoolinfo\n"
1146             "\nReturns details on the active state of the TX memory pool.\n"
1147             "\nResult:\n"
1148             "{\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"
1152             "}\n"
1153             "\nExamples:\n"
1154             + HelpExampleCli("getmempoolinfo", "")
1155             + HelpExampleRpc("getmempoolinfo", "")
1156         );
1157
1158     return mempoolInfoToJSON();
1159 }
1160
1161 UniValue invalidateblock(const UniValue& params, bool fHelp)
1162 {
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"
1167             "\nArguments:\n"
1168             "1. hash   (string, required) the hash of the block to mark as invalid\n"
1169             "\nResult:\n"
1170             "\nExamples:\n"
1171             + HelpExampleCli("invalidateblock", "\"blockhash\"")
1172             + HelpExampleRpc("invalidateblock", "\"blockhash\"")
1173         );
1174
1175     std::string strHash = params[0].get_str();
1176     uint256 hash(uint256S(strHash));
1177     CValidationState state;
1178
1179     {
1180         LOCK(cs_main);
1181         if (mapBlockIndex.count(hash) == 0)
1182             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1183
1184         CBlockIndex* pblockindex = mapBlockIndex[hash];
1185         InvalidateBlock(state, pblockindex);
1186     }
1187
1188     if (state.IsValid()) {
1189         ActivateBestChain(state);
1190     }
1191
1192     if (!state.IsValid()) {
1193         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1194     }
1195
1196     return NullUniValue;
1197 }
1198
1199 UniValue reconsiderblock(const UniValue& params, bool fHelp)
1200 {
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"
1206             "\nArguments:\n"
1207             "1. hash   (string, required) the hash of the block to reconsider\n"
1208             "\nResult:\n"
1209             "\nExamples:\n"
1210             + HelpExampleCli("reconsiderblock", "\"blockhash\"")
1211             + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
1212         );
1213
1214     std::string strHash = params[0].get_str();
1215     uint256 hash(uint256S(strHash));
1216     CValidationState state;
1217
1218     {
1219         LOCK(cs_main);
1220         if (mapBlockIndex.count(hash) == 0)
1221             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1222
1223         CBlockIndex* pblockindex = mapBlockIndex[hash];
1224         ReconsiderBlock(state, pblockindex);
1225     }
1226
1227     if (state.IsValid()) {
1228         ActivateBestChain(state);
1229     }
1230
1231     if (!state.IsValid()) {
1232         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1233     }
1234
1235     return NullUniValue;
1236 }
This page took 0.094851 seconds and 4 git commands to generate.