]> Git Repo - VerusCoin.git/blob - src/rpcblockchain.cpp
Blockader
[VerusCoin.git] / src / rpcblockchain.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "amount.h"
7 #include "chain.h"
8 #include "chainparams.h"
9 #include "checkpoints.h"
10 #include "consensus/validation.h"
11 #include "cc/betprotocol.h"
12 #include "main.h"
13 #include "primitives/transaction.h"
14 #include "rpcserver.h"
15 #include "sync.h"
16 #include "util.h"
17
18 #include <stdint.h>
19
20 #include <univalue.h>
21
22 #include <regex>
23
24 using namespace std;
25
26 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
27 void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
28
29 double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
30 {
31     // Floating point number that is a multiple of the minimum difficulty,
32     // minimum difficulty = 1.0.
33     if (blockindex == NULL)
34     {
35         if (chainActive.Tip() == NULL)
36             return 1.0;
37         else
38             blockindex = chainActive.Tip();
39     }
40
41     uint32_t bits;
42     if (networkDifficulty) {
43         bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus());
44     } else {
45         bits = blockindex->nBits;
46     }
47
48     uint32_t powLimit =
49         UintToArith256(Params().GetConsensus().powLimit).GetCompact();
50     int nShift = (bits >> 24) & 0xff;
51     int nShiftAmount = (powLimit >> 24) & 0xff;
52
53     double dDiff =
54         (double)(powLimit & 0x00ffffff) /
55         (double)(bits & 0x00ffffff);
56
57     while (nShift < nShiftAmount)
58     {
59         dDiff *= 256.0;
60         nShift++;
61     }
62     while (nShift > nShiftAmount)
63     {
64         dDiff /= 256.0;
65         nShift--;
66     }
67
68     return dDiff;
69 }
70
71 double GetDifficulty(const CBlockIndex* blockindex)
72 {
73     return GetDifficultyINTERNAL(blockindex, false);
74 }
75
76 double GetNetworkDifficulty(const CBlockIndex* blockindex)
77 {
78     return GetDifficultyINTERNAL(blockindex, true);
79 }
80
81 static UniValue ValuePoolDesc(
82     const std::string &name,
83     const boost::optional<CAmount> chainValue,
84     const boost::optional<CAmount> valueDelta)
85 {
86     UniValue rv(UniValue::VOBJ);
87     rv.push_back(Pair("id", name));
88     rv.push_back(Pair("monitored", (bool)chainValue));
89     if (chainValue) {
90         rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue)));
91         rv.push_back(Pair("chainValueZat", *chainValue));
92     }
93     if (valueDelta) {
94         rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta)));
95         rv.push_back(Pair("valueDeltaZat", *valueDelta));
96     }
97     return rv;
98 }
99
100 UniValue blockheaderToJSON(const CBlockIndex* blockindex)
101 {
102     UniValue result(UniValue::VOBJ);
103     result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
104     int confirmations = -1;
105     // Only report confirmations if the block is on the main chain
106     if (chainActive.Contains(blockindex))
107         confirmations = chainActive.Height() - blockindex->nHeight + 1;
108     result.push_back(Pair("confirmations", confirmations));
109     result.push_back(Pair("height", blockindex->nHeight));
110     result.push_back(Pair("version", blockindex->nVersion));
111     result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
112     result.push_back(Pair("time", (int64_t)blockindex->nTime));
113     result.push_back(Pair("nonce", blockindex->nNonce.GetHex()));
114     result.push_back(Pair("solution", HexStr(blockindex->nSolution)));
115     result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
116     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
117     result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
118
119     if (blockindex->pprev)
120         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
121     CBlockIndex *pnext = chainActive.Next(blockindex);
122     if (pnext)
123         result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
124     return result;
125 }
126
127 UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
128 {
129     UniValue result(UniValue::VOBJ);
130     result.push_back(Pair("hash", block.GetHash().GetHex()));
131     int confirmations = -1;
132     // Only report confirmations if the block is on the main chain
133     if (chainActive.Contains(blockindex))
134         confirmations = chainActive.Height() - blockindex->nHeight + 1;
135     result.push_back(Pair("confirmations", confirmations));
136     result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
137     result.push_back(Pair("height", blockindex->nHeight));
138     result.push_back(Pair("version", block.nVersion));
139     result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
140     UniValue txs(UniValue::VARR);
141     BOOST_FOREACH(const CTransaction&tx, block.vtx)
142     {
143         if(txDetails)
144         {
145             UniValue objTx(UniValue::VOBJ);
146             TxToJSON(tx, uint256(), objTx);
147             txs.push_back(objTx);
148         }
149         else
150             txs.push_back(tx.GetHash().GetHex());
151     }
152     result.push_back(Pair("tx", txs));
153     result.push_back(Pair("time", block.GetBlockTime()));
154     result.push_back(Pair("nonce", block.nNonce.GetHex()));
155     result.push_back(Pair("solution", HexStr(block.nSolution)));
156     result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
157     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
158     result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
159     result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex()));
160
161     UniValue valuePools(UniValue::VARR);
162     valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue));
163     result.push_back(Pair("valuePools", valuePools));
164
165     if (blockindex->pprev)
166         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
167     CBlockIndex *pnext = chainActive.Next(blockindex);
168     if (pnext)
169         result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
170     return result;
171 }
172
173 UniValue getblockcount(const UniValue& params, bool fHelp)
174 {
175     if (fHelp || params.size() != 0)
176         throw runtime_error(
177             "getblockcount\n"
178             "\nReturns the number of blocks in the best valid block chain.\n"
179             "\nResult:\n"
180             "n    (numeric) The current block count\n"
181             "\nExamples:\n"
182             + HelpExampleCli("getblockcount", "")
183             + HelpExampleRpc("getblockcount", "")
184         );
185
186     LOCK(cs_main);
187     return chainActive.Height();
188 }
189
190 UniValue getbestblockhash(const UniValue& params, bool fHelp)
191 {
192     if (fHelp || params.size() != 0)
193         throw runtime_error(
194             "getbestblockhash\n"
195             "\nReturns the hash of the best (tip) block in the longest block chain.\n"
196             "\nResult\n"
197             "\"hex\"      (string) the block hash hex encoded\n"
198             "\nExamples\n"
199             + HelpExampleCli("getbestblockhash", "")
200             + HelpExampleRpc("getbestblockhash", "")
201         );
202
203     LOCK(cs_main);
204     return chainActive.Tip()->GetBlockHash().GetHex();
205 }
206
207 UniValue getdifficulty(const UniValue& params, bool fHelp)
208 {
209     if (fHelp || params.size() != 0)
210         throw runtime_error(
211             "getdifficulty\n"
212             "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
213             "\nResult:\n"
214             "n.nnn       (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
215             "\nExamples:\n"
216             + HelpExampleCli("getdifficulty", "")
217             + HelpExampleRpc("getdifficulty", "")
218         );
219
220     LOCK(cs_main);
221     return GetNetworkDifficulty();
222 }
223
224 UniValue mempoolToJSON(bool fVerbose = false)
225 {
226     if (fVerbose)
227     {
228         LOCK(mempool.cs);
229         UniValue o(UniValue::VOBJ);
230         BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx)
231         {
232             const uint256& hash = e.GetTx().GetHash();
233             UniValue info(UniValue::VOBJ);
234             info.push_back(Pair("size", (int)e.GetTxSize()));
235             info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
236             info.push_back(Pair("time", e.GetTime()));
237             info.push_back(Pair("height", (int)e.GetHeight()));
238             info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight())));
239             info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height())));
240             const CTransaction& tx = e.GetTx();
241             set<string> setDepends;
242             BOOST_FOREACH(const CTxIn& txin, tx.vin)
243             {
244                 if (mempool.exists(txin.prevout.hash))
245                     setDepends.insert(txin.prevout.hash.ToString());
246             }
247
248             UniValue depends(UniValue::VARR);
249             BOOST_FOREACH(const string& dep, setDepends)
250             {
251                 depends.push_back(dep);
252             }
253
254             info.push_back(Pair("depends", depends));
255             o.push_back(Pair(hash.ToString(), info));
256         }
257         return o;
258     }
259     else
260     {
261         vector<uint256> vtxid;
262         mempool.queryHashes(vtxid);
263
264         UniValue a(UniValue::VARR);
265         BOOST_FOREACH(const uint256& hash, vtxid)
266             a.push_back(hash.ToString());
267
268         return a;
269     }
270 }
271
272 UniValue getrawmempool(const UniValue& params, bool fHelp)
273 {
274     if (fHelp || params.size() > 1)
275         throw runtime_error(
276             "getrawmempool ( verbose )\n"
277             "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
278             "\nArguments:\n"
279             "1. verbose           (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
280             "\nResult: (for verbose = false):\n"
281             "[                     (json array of string)\n"
282             "  \"transactionid\"     (string) The transaction id\n"
283             "  ,...\n"
284             "]\n"
285             "\nResult: (for verbose = true):\n"
286             "{                           (json object)\n"
287             "  \"transactionid\" : {       (json object)\n"
288             "    \"size\" : n,             (numeric) transaction size in bytes\n"
289             "    \"fee\" : n,              (numeric) transaction fee in " + CURRENCY_UNIT + "\n"
290             "    \"time\" : n,             (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
291             "    \"height\" : n,           (numeric) block height when transaction entered pool\n"
292             "    \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
293             "    \"currentpriority\" : n,  (numeric) transaction priority now\n"
294             "    \"depends\" : [           (array) unconfirmed transactions used as inputs for this transaction\n"
295             "        \"transactionid\",    (string) parent transaction id\n"
296             "       ... ]\n"
297             "  }, ...\n"
298             "}\n"
299             "\nExamples\n"
300             + HelpExampleCli("getrawmempool", "true")
301             + HelpExampleRpc("getrawmempool", "true")
302         );
303
304     LOCK(cs_main);
305
306     bool fVerbose = false;
307     if (params.size() > 0)
308         fVerbose = params[0].get_bool();
309
310     return mempoolToJSON(fVerbose);
311 }
312
313 UniValue getblockhash(const UniValue& params, bool fHelp)
314 {
315     if (fHelp || params.size() != 1)
316         throw runtime_error(
317             "getblockhash index\n"
318             "\nReturns hash of block in best-block-chain at index provided.\n"
319             "\nArguments:\n"
320             "1. index         (numeric, required) The block index\n"
321             "\nResult:\n"
322             "\"hash\"         (string) The block hash\n"
323             "\nExamples:\n"
324             + HelpExampleCli("getblockhash", "1000")
325             + HelpExampleRpc("getblockhash", "1000")
326         );
327
328     LOCK(cs_main);
329
330     int nHeight = params[0].get_int();
331     if (nHeight < 0 || nHeight > chainActive.Height())
332         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
333
334     CBlockIndex* pblockindex = chainActive[nHeight];
335     return pblockindex->GetBlockHash().GetHex();
336 }
337
338 /*uint256 _komodo_getblockhash(int32_t nHeight)
339 {
340     uint256 hash;
341     LOCK(cs_main);
342     if ( nHeight >= 0 && nHeight <= chainActive.Height() )
343     {
344         CBlockIndex* pblockindex = chainActive[nHeight];
345         hash = pblockindex->GetBlockHash();
346         int32_t i;
347         for (i=0; i<32; i++)
348             printf("%02x",((uint8_t *)&hash)[i]);
349         printf(" blockhash.%d\n",nHeight);
350     } else memset(&hash,0,sizeof(hash));
351     return(hash);
352 }*/
353
354 UniValue getblockheader(const UniValue& params, bool fHelp)
355 {
356     if (fHelp || params.size() < 1 || params.size() > 2)
357         throw runtime_error(
358             "getblockheader \"hash\" ( verbose )\n"
359             "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n"
360             "If verbose is true, returns an Object with information about blockheader <hash>.\n"
361             "\nArguments:\n"
362             "1. \"hash\"          (string, required) The block hash\n"
363             "2. verbose           (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
364             "\nResult (for verbose = true):\n"
365             "{\n"
366             "  \"hash\" : \"hash\",     (string) the block hash (same as provided)\n"
367             "  \"confirmations\" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
368             "  \"height\" : n,          (numeric) The block height or index\n"
369             "  \"version\" : n,         (numeric) The block version\n"
370             "  \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
371             "  \"time\" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
372             "  \"nonce\" : n,           (numeric) The nonce\n"
373             "  \"bits\" : \"1d00ffff\", (string) The bits\n"
374             "  \"difficulty\" : x.xxx,  (numeric) The difficulty\n"
375             "  \"previousblockhash\" : \"hash\",  (string) The hash of the previous block\n"
376             "  \"nextblockhash\" : \"hash\"       (string) The hash of the next block\n"
377             "}\n"
378             "\nResult (for verbose=false):\n"
379             "\"data\"             (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
380             "\nExamples:\n"
381             + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
382             + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
383         );
384
385     LOCK(cs_main);
386
387     std::string strHash = params[0].get_str();
388     uint256 hash(uint256S(strHash));
389
390     bool fVerbose = true;
391     if (params.size() > 1)
392         fVerbose = params[1].get_bool();
393
394     if (mapBlockIndex.count(hash) == 0)
395         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
396
397     CBlockIndex* pblockindex = mapBlockIndex[hash];
398
399     if (!fVerbose)
400     {
401         CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
402         ssBlock << pblockindex->GetBlockHeader();
403         std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
404         return strHex;
405     }
406
407     return blockheaderToJSON(pblockindex);
408 }
409
410 UniValue getblock(const UniValue& params, bool fHelp)
411 {
412     if (fHelp || params.size() < 1 || params.size() > 2)
413         throw runtime_error(
414             "getblock \"hash|height\" ( verbose )\n"
415             "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n"
416             "If verbose is true, returns an Object with information about block <hash|height>.\n"
417             "\nArguments:\n"
418             "1. \"hash|height\"     (string, required) The block hash or height\n"
419             "2. verbose           (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
420             "\nResult (for verbose = true):\n"
421             "{\n"
422             "  \"hash\" : \"hash\",       (string) the block hash (same as provided hash)\n"
423             "  \"confirmations\" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
424             "  \"size\" : n,            (numeric) The block size\n"
425             "  \"height\" : n,          (numeric) The block height or index (same as provided height)\n"
426             "  \"version\" : n,         (numeric) The block version\n"
427             "  \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
428             "  \"tx\" : [               (array of string) The transaction ids\n"
429             "     \"transactionid\"     (string) The transaction id\n"
430             "     ,...\n"
431             "  ],\n"
432             "  \"time\" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
433             "  \"nonce\" : n,           (numeric) The nonce\n"
434             "  \"bits\" : \"1d00ffff\",   (string) The bits\n"
435             "  \"difficulty\" : x.xxx,  (numeric) The difficulty\n"
436             "  \"previousblockhash\" : \"hash\",  (string) The hash of the previous block\n"
437             "  \"nextblockhash\" : \"hash\"       (string) The hash of the next block\n"
438             "}\n"
439             "\nResult (for verbose=false):\n"
440             "\"data\"             (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
441             "\nExamples:\n"
442             + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
443             + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
444             + HelpExampleCli("getblock", "12800")
445             + HelpExampleRpc("getblock", "12800")
446         );
447
448     LOCK(cs_main);
449
450     std::string strHash = params[0].get_str();
451
452     // If height is supplied, find the hash
453     if (strHash.size() < (2 * sizeof(uint256))) {
454         // std::stoi allows characters, whereas we want to be strict
455         regex r("[[:digit:]]+");
456         if (!regex_match(strHash, r)) {
457             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
458         }
459
460         int nHeight = -1;
461         try {
462             nHeight = std::stoi(strHash);
463         }
464         catch (const std::exception &e) {
465             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
466         }
467
468         if (nHeight < 0 || nHeight > chainActive.Height()) {
469             throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
470         }
471         strHash = chainActive[nHeight]->GetBlockHash().GetHex();
472     }
473
474     uint256 hash(uint256S(strHash));
475
476     bool fVerbose = true;
477     if (params.size() > 1)
478         fVerbose = params[1].get_bool();
479
480     if (mapBlockIndex.count(hash) == 0)
481         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
482
483     CBlock block;
484     CBlockIndex* pblockindex = mapBlockIndex[hash];
485
486     if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
487         throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
488
489     if(!ReadBlockFromDisk(block, pblockindex))
490         throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
491
492     if (!fVerbose)
493     {
494         CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
495         ssBlock << block;
496         std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
497         return strHex;
498     }
499
500     return blockToJSON(block, pblockindex);
501 }
502
503 UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
504 {
505     if (fHelp || params.size() != 0)
506         throw runtime_error(
507             "gettxoutsetinfo\n"
508             "\nReturns statistics about the unspent transaction output set.\n"
509             "Note this call may take some time.\n"
510             "\nResult:\n"
511             "{\n"
512             "  \"height\":n,     (numeric) The current block height (index)\n"
513             "  \"bestblock\": \"hex\",   (string) the best block hash hex\n"
514             "  \"transactions\": n,      (numeric) The number of transactions\n"
515             "  \"txouts\": n,            (numeric) The number of output transactions\n"
516             "  \"bytes_serialized\": n,  (numeric) The serialized size\n"
517             "  \"hash_serialized\": \"hash\",   (string) The serialized hash\n"
518             "  \"total_amount\": x.xxx          (numeric) The total amount\n"
519             "}\n"
520             "\nExamples:\n"
521             + HelpExampleCli("gettxoutsetinfo", "")
522             + HelpExampleRpc("gettxoutsetinfo", "")
523         );
524
525     UniValue ret(UniValue::VOBJ);
526
527     CCoinsStats stats;
528     FlushStateToDisk();
529     if (pcoinsTip->GetStats(stats)) {
530         ret.push_back(Pair("height", (int64_t)stats.nHeight));
531         ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
532         ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
533         ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
534         ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
535         ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
536         ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
537     }
538     return ret;
539 }
540
541 #include "komodo_defs.h"
542
543 #define IGUANA_MAXSCRIPTSIZE 10001
544 #define KOMODO_KVDURATION 1440
545 #define KOMODO_KVBINARY 2
546 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
547 uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
548 uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume);
549 int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
550 int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
551 char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
552 //uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n);
553 int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width);
554 int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen);
555 int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip);
556
557 UniValue kvsearch(const UniValue& params, bool fHelp)
558 {
559     UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE],key[IGUANA_MAXSCRIPTSIZE]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes;
560     if (fHelp || params.size() != 1 )
561         throw runtime_error("kvsearch key");
562     LOCK(cs_main);
563     if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 )
564     {
565         ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
566         ret.push_back(Pair("currentheight", (int64_t)chainActive.Tip()->nHeight));
567         ret.push_back(Pair("key",params[0].get_str()));
568         ret.push_back(Pair("keylen",keylen));
569         if ( keylen < sizeof(key) )
570         {
571             memcpy(key,params[0].get_str().c_str(),keylen);
572             if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.Tip()->nHeight,&flags,&height,value,key,keylen)) >= 0 )
573             {
574                 std::string val; char *valuestr;
575                 val.resize(valuesize);
576                 valuestr = (char *)val.data();
577                 memcpy(valuestr,value,valuesize);
578                 if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 )
579                     ret.push_back(Pair("owner",refpubkey.GetHex()));
580                 ret.push_back(Pair("height",height));
581                 duration = ((flags >> 2) + 1) * KOMODO_KVDURATION;
582                 ret.push_back(Pair("expiration", (int64_t)(height+duration)));
583                 ret.push_back(Pair("flags",(int64_t)flags));
584                 ret.push_back(Pair("value",val));
585                 ret.push_back(Pair("valuesize",valuesize));
586             } else ret.push_back(Pair("error",(char *)"cant find key"));
587         } else ret.push_back(Pair("error",(char *)"key too big"));
588     } else ret.push_back(Pair("error",(char *)"null key"));
589     return ret;
590 }
591
592 /*
593 UniValue height_MoM(const UniValue& params, bool fHelp)
594 {
595     int32_t height,depth,notarized_height,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi; uint256 MoM,MoMoM,kmdtxid; uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR);
596     if ( fHelp || params.size() != 1 )
597         throw runtime_error("height_MoM height\n");
598     LOCK(cs_main);
599     height = atoi(params[0].get_str().c_str());
600     if ( height <= 0 )
601     {
602         if ( chainActive.Tip() == 0 )
603         {
604             ret.push_back(Pair("error",(char *)"no active chain yet"));
605             return(ret);
606         }
607         height = chainActive.Tip()->nHeight;
608     }
609     //fprintf(stderr,"height_MoM height.%d\n",height);
610     depth = komodo_MoM(&notarized_height,&MoM,&kmdtxid,height,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi);
611     ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)));
612     ret.push_back(Pair("height",height));
613     ret.push_back(Pair("timestamp",(uint64_t)timestamp));
614     if ( depth > 0 )
615     {
616         ret.push_back(Pair("depth",depth));
617         ret.push_back(Pair("notarized_height",notarized_height));
618         ret.push_back(Pair("MoM",MoM.GetHex()));
619         ret.push_back(Pair("kmdtxid",kmdtxid.GetHex()));
620         if ( ASSETCHAINS_SYMBOL[0] != 0 )
621         {
622             ret.push_back(Pair("MoMoM",MoMoM.GetHex()));
623             ret.push_back(Pair("MoMoMoffset",MoMoMoffset));
624             ret.push_back(Pair("MoMoMdepth",MoMoMdepth));
625             ret.push_back(Pair("kmdstarti",kmdstarti));
626             ret.push_back(Pair("kmdendi",kmdendi));
627         }
628     } else ret.push_back(Pair("error",(char *)"no MoM for height"));
629     
630     return ret;
631 }
632
633 UniValue txMoMproof(const UniValue& params, bool fHelp)
634 {
635     uint256 hash, notarisationHash, MoM,MoMoM; int32_t notarisedHeight, depth; CBlockIndex* blockIndex;
636     std::vector<uint256> branch;
637     int nIndex,MoMoMdepth,MoMoMoffset,kmdstarti,kmdendi;
638
639     // parse params and get notarisation data for tx
640     {
641         if ( fHelp || params.size() != 1)
642             throw runtime_error("txMoMproof needs a txid");
643
644         hash = uint256S(params[0].get_str());
645
646         uint256 blockHash;
647         CTransaction tx;
648         if (!GetTransaction(hash, tx, blockHash, true))
649             throw runtime_error("cannot find transaction");
650
651         blockIndex = mapBlockIndex[blockHash];
652
653         depth = komodo_MoM(&notarisedHeight, &MoM, &notarisationHash, blockIndex->nHeight,&MoMoM,&MoMoMoffset,&MoMoMdepth,&kmdstarti,&kmdendi);
654
655         if (!depth)
656             throw runtime_error("notarisation not found");
657         
658         // index of block in MoM leaves
659         nIndex = notarisedHeight - blockIndex->nHeight;
660     }
661
662     // build merkle chain from blocks to MoM
663     {
664         // since the merkle branch code is tied up in a block class
665         // and we want to make a merkle branch for something that isnt transactions
666         CBlock fakeBlock;
667         for (int i=0; i<depth; i++) {
668             uint256 mRoot = chainActive[notarisedHeight - i]->hashMerkleRoot;
669             CTransaction fakeTx;
670             // first value in CTransaction memory is it's hash
671             memcpy((void*)&fakeTx, mRoot.begin(), 32);
672             fakeBlock.vtx.push_back(fakeTx);
673         }
674         branch = fakeBlock.GetMerkleBranch(nIndex);
675
676         // Check branch
677         if (MoM != CBlock::CheckMerkleBranch(blockIndex->hashMerkleRoot, branch, nIndex))
678             throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed merkle block->MoM");
679     }
680
681     // Now get the tx merkle branch
682     {
683         CBlock block;
684
685         if (fHavePruned && !(blockIndex->nStatus & BLOCK_HAVE_DATA) && blockIndex->nTx > 0)
686             throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
687
688         if(!ReadBlockFromDisk(block, blockIndex))
689             throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
690
691         // Locate the transaction in the block
692         int nTxIndex;
693         for (nTxIndex = 0; nTxIndex < (int)block.vtx.size(); nTxIndex++)
694             if (block.vtx[nTxIndex].GetHash() == hash)
695                 break;
696
697         if (nTxIndex == (int)block.vtx.size())
698             throw JSONRPCError(RPC_INTERNAL_ERROR, "Error locating tx in block");
699
700         std::vector<uint256> txBranch = block.GetMerkleBranch(nTxIndex);
701
702         // Check branch
703         if (block.hashMerkleRoot != CBlock::CheckMerkleBranch(hash, txBranch, nTxIndex))
704             throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed merkle tx->block");
705
706         // concatenate branches
707         nIndex = (nIndex << txBranch.size()) + nTxIndex;
708         branch.insert(branch.begin(), txBranch.begin(), txBranch.end());
709     }
710
711     // Check the proof
712     if (MoM != CBlock::CheckMerkleBranch(hash, branch, nIndex)) 
713         throw JSONRPCError(RPC_INTERNAL_ERROR, "Failed validating MoM");
714
715     // Encode and return
716     CDataStream ssProof(SER_NETWORK, PROTOCOL_VERSION);
717     ssProof << MoMProof(nIndex, branch, notarisationHash);
718     return HexStr(ssProof.begin(), ssProof.end());
719 }
720 */
721
722 UniValue minerids(const UniValue& params, bool fHelp)
723 {
724     uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129];
725     if ( fHelp || params.size() != 1 )
726         throw runtime_error("minerids needs height\n");
727     LOCK(cs_main);
728     int32_t height = atoi(params[0].get_str().c_str());
729     if ( height <= 0 )
730         height = chainActive.Tip()->nHeight;
731     else
732     {
733         CBlockIndex *pblockindex = chainActive[height];
734         if ( pblockindex != 0 )
735             timestamp = pblockindex->GetBlockTime();
736     }
737     if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 )
738     {
739         memset(tally,0,sizeof(tally));
740         numnotaries = komodo_notaries(pubkeys,height,timestamp);
741         if ( numnotaries > 0 )
742         {
743             for (i=0; i<n; i++)
744             {
745                 if ( minerids[i] >= numnotaries )
746                     tally[128]++;
747                 else tally[minerids[i]]++;
748             }
749             for (i=0; i<64; i++)
750             {
751                 UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m;
752                 hex.resize(66);
753                 hexstr = (char *)hex.data();
754                 for (j=0; j<33; j++)
755                     sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
756                 item.push_back(Pair("notaryid", i));
757
758                 bitcoin_address(kmdaddr,60,pubkeys[i],33);
759                 m = (int32_t)strlen(kmdaddr);
760                 kmdaddress.resize(m);
761                 ptr = (char *)kmdaddress.data();
762                 memcpy(ptr,kmdaddr,m);
763                 item.push_back(Pair("KMDaddress", kmdaddress));
764
765                 item.push_back(Pair("pubkey", hex));
766                 item.push_back(Pair("blocks", tally[i]));
767                 a.push_back(item);
768             }
769             UniValue item(UniValue::VOBJ);
770             item.push_back(Pair("pubkey", (char *)"external miners"));
771             item.push_back(Pair("blocks", tally[128]));
772             a.push_back(item);
773         }
774         ret.push_back(Pair("mined", a));
775     } else ret.push_back(Pair("error", (char *)"couldnt extract minerids"));
776     return ret;
777 }
778
779 UniValue notaries(const UniValue& params, bool fHelp)
780 {
781     UniValue a(UniValue::VARR); uint32_t timestamp=0; UniValue ret(UniValue::VOBJ); int32_t i,j,n,m; char *hexstr;  uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr;
782     if ( fHelp || (params.size() != 1 && params.size() != 2) )
783         throw runtime_error("notaries height timestamp\n");
784     LOCK(cs_main);
785     int32_t height = atoi(params[0].get_str().c_str());
786     if ( params.size() == 2 )
787         timestamp = (uint32_t)atol(params[1].get_str().c_str());
788     else timestamp = (uint32_t)time(NULL);
789     if ( height < 0 )
790     {
791         height = chainActive.Tip()->nHeight;
792         timestamp = chainActive.Tip()->GetBlockTime();
793     }
794     else if ( params.size() < 2 )
795     {
796         CBlockIndex *pblockindex = chainActive[height];
797         if ( pblockindex != 0 )
798             timestamp = pblockindex->GetBlockTime();
799     }
800     if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 )
801     {
802         for (i=0; i<n; i++)
803         {
804             UniValue item(UniValue::VOBJ);
805             std::string btcaddress,kmdaddress,hex;
806             hex.resize(66);
807             hexstr = (char *)hex.data();
808             for (j=0; j<33; j++)
809                 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
810             item.push_back(Pair("pubkey", hex));
811             
812             bitcoin_address(btcaddr,0,pubkeys[i],33);
813             m = (int32_t)strlen(btcaddr);
814             btcaddress.resize(m);
815             ptr = (char *)btcaddress.data();
816             memcpy(ptr,btcaddr,m);
817             item.push_back(Pair("BTCaddress", btcaddress));
818             
819             bitcoin_address(kmdaddr,60,pubkeys[i],33);
820             m = (int32_t)strlen(kmdaddr);
821             kmdaddress.resize(m);
822             ptr = (char *)kmdaddress.data();
823             memcpy(ptr,kmdaddr,m);
824             item.push_back(Pair("KMDaddress", kmdaddress));
825             a.push_back(item);
826         }
827     }
828     ret.push_back(Pair("notaries", a));
829     ret.push_back(Pair("numnotaries", n));
830     ret.push_back(Pair("height", height));
831     ret.push_back(Pair("timestamp", (uint64_t)timestamp));
832     return ret;
833 }
834
835 int32_t komodo_pending_withdraws(char *opretstr);
836 int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base);
837 extern char CURRENCIES[][8];
838
839 UniValue paxpending(const UniValue& params, bool fHelp)
840 {
841     UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); char opretbuf[10000*2]; int32_t opretlen,baseid; uint64_t available,deposited,issued,withdrawn,approved,redeemed;
842     if ( fHelp || params.size() != 0 )
843         throw runtime_error("paxpending needs no args\n");
844     LOCK(cs_main);
845     if ( (opretlen= komodo_pending_withdraws(opretbuf)) > 0 )
846         ret.push_back(Pair("withdraws", opretbuf));
847     else ret.push_back(Pair("withdraws", (char *)""));
848     for (baseid=0; baseid<32; baseid++)
849     {
850         UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
851         if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 )
852         {
853             if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 )
854             {
855                 item.push_back(Pair("available", ValueFromAmount(available)));
856                 item.push_back(Pair("deposited", ValueFromAmount(deposited)));
857                 item.push_back(Pair("issued", ValueFromAmount(issued)));
858                 item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn)));
859                 item.push_back(Pair("approved", ValueFromAmount(approved)));
860                 item.push_back(Pair("redeemed", ValueFromAmount(redeemed)));
861                 obj.push_back(Pair(CURRENCIES[baseid],item));
862                 a.push_back(obj);
863             }
864         }
865     }
866     ret.push_back(Pair("fiatstatus", a));
867     return ret;
868 }
869
870 UniValue paxprice(const UniValue& params, bool fHelp)
871 {
872     if ( fHelp || params.size() > 4 || params.size() < 2 )
873         throw runtime_error("paxprice \"base\" \"rel\" height\n");
874     LOCK(cs_main);
875     UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed;
876     std::string base = params[0].get_str();
877     std::string rel = params[1].get_str();
878     int32_t height;
879     if ( params.size() == 2 )
880         height = chainActive.Tip()->nHeight;
881     else height = atoi(params[2].get_str().c_str());
882     //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
883         basevolume = 100000;
884     relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume);
885     ret.push_back(Pair("base", base));
886     ret.push_back(Pair("rel", rel));
887     ret.push_back(Pair("height", height));
888     char seedstr[32];
889     sprintf(seedstr,"%llu",(long long)seed);
890     ret.push_back(Pair("seed", seedstr));
891     if ( height < 0 || height > chainActive.Height() )
892         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
893     else
894     {
895         CBlockIndex *pblockindex = chainActive[height];
896         if ( pblockindex != 0 )
897             ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime));
898         if ( basevolume != 0 && relvolume != 0 )
899         {
900             ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
901             ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume)));
902             ret.push_back(Pair("basevolume",ValueFromAmount(basevolume)));
903             ret.push_back(Pair("relvolume",ValueFromAmount(relvolume)));
904         } else ret.push_back(Pair("error", "overflow or error in one or more of parameters"));
905     }
906     return ret;
907 }
908
909 UniValue paxprices(const UniValue& params, bool fHelp)
910 {
911     if ( fHelp || params.size() != 3 )
912         throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
913     LOCK(cs_main);
914     UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
915     std::string base = params[0].get_str();
916     std::string rel = params[1].get_str();
917     int32_t maxsamples = atoi(params[2].get_str().c_str());
918     if ( maxsamples < 1 )
919         maxsamples = 1;
920     else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
921         maxsamples = sizeof(heights)/sizeof(*heights);
922     ret.push_back(Pair("base", base));
923     ret.push_back(Pair("rel", rel));
924     n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
925     UniValue a(UniValue::VARR);
926     for (i=0; i<n; i++)
927     {
928         UniValue item(UniValue::VOBJ);
929         if ( heights[i] < 0 || heights[i] > chainActive.Height() )
930             throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
931         else
932         {
933             CBlockIndex *pblockindex = chainActive[heights[i]];
934
935             item.push_back(Pair("t", (int64_t)pblockindex->nTime));
936             item.push_back(Pair("p", (double)prices[i] / COIN));
937             a.push_back(item);
938         }
939     }
940     ret.push_back(Pair("array", a));
941     return ret;
942 }
943
944 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight);
945
946 UniValue gettxout(const UniValue& params, bool fHelp)
947 {
948     if (fHelp || params.size() < 2 || params.size() > 3)
949         throw runtime_error(
950             "gettxout \"txid\" n ( includemempool )\n"
951             "\nReturns details about an unspent transaction output.\n"
952             "\nArguments:\n"
953             "1. \"txid\"       (string, required) The transaction id\n"
954             "2. n              (numeric, required) vout value\n"
955             "3. includemempool  (boolean, optional) Whether to include the mempool\n"
956             "\nResult:\n"
957             "{\n"
958             "  \"bestblock\" : \"hash\",    (string) the block hash\n"
959             "  \"confirmations\" : n,       (numeric) The number of confirmations\n"
960             "  \"value\" : x.xxx,           (numeric) The transaction value in " + CURRENCY_UNIT + "\n"
961             "  \"scriptPubKey\" : {         (json object)\n"
962             "     \"asm\" : \"code\",       (string) \n"
963             "     \"hex\" : \"hex\",        (string) \n"
964             "     \"reqSigs\" : n,          (numeric) Number of required signatures\n"
965             "     \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
966             "     \"addresses\" : [          (array of string) array of Zcash addresses\n"
967             "        \"zcashaddress\"        (string) Zcash address\n"
968             "        ,...\n"
969             "     ]\n"
970             "  },\n"
971             "  \"version\" : n,              (numeric) The version\n"
972             "  \"coinbase\" : true|false     (boolean) Coinbase or not\n"
973             "}\n"
974
975             "\nExamples:\n"
976             "\nGet unspent transactions\n"
977             + HelpExampleCli("listunspent", "") +
978             "\nView the details\n"
979             + HelpExampleCli("gettxout", "\"txid\" 1") +
980             "\nAs a json rpc call\n"
981             + HelpExampleRpc("gettxout", "\"txid\", 1")
982         );
983
984     LOCK(cs_main);
985
986     UniValue ret(UniValue::VOBJ);
987
988     std::string strHash = params[0].get_str();
989     uint256 hash(uint256S(strHash));
990     int n = params[1].get_int();
991     bool fMempool = true;
992     if (params.size() > 2)
993         fMempool = params[2].get_bool();
994
995     CCoins coins;
996     if (fMempool) {
997         LOCK(mempool.cs);
998         CCoinsViewMemPool view(pcoinsTip, mempool);
999         if (!view.GetCoins(hash, coins))
1000             return NullUniValue;
1001         mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
1002     } else {
1003         if (!pcoinsTip->GetCoins(hash, coins))
1004             return NullUniValue;
1005     }
1006     if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
1007         return NullUniValue;
1008
1009     BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
1010     CBlockIndex *pindex = it->second;
1011     ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
1012     if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
1013         ret.push_back(Pair("confirmations", 0));
1014     else ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
1015     ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
1016     uint64_t interest; int32_t txheight; uint32_t locktime;
1017     if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue,(int32_t)pindex->nHeight)) != 0 )
1018         ret.push_back(Pair("interest", ValueFromAmount(interest)));
1019     UniValue o(UniValue::VOBJ);
1020     ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
1021     ret.push_back(Pair("scriptPubKey", o));
1022     ret.push_back(Pair("version", coins.nVersion));
1023     ret.push_back(Pair("coinbase", coins.fCoinBase));
1024
1025     return ret;
1026 }
1027
1028 UniValue verifychain(const UniValue& params, bool fHelp)
1029 {
1030     if (fHelp || params.size() > 2)
1031         throw runtime_error(
1032             "verifychain ( checklevel numblocks )\n"
1033             "\nVerifies blockchain database.\n"
1034             "\nArguments:\n"
1035             "1. checklevel   (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
1036             "2. numblocks    (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
1037             "\nResult:\n"
1038             "true|false       (boolean) Verified or not\n"
1039             "\nExamples:\n"
1040             + HelpExampleCli("verifychain", "")
1041             + HelpExampleRpc("verifychain", "")
1042         );
1043
1044     LOCK(cs_main);
1045
1046     int nCheckLevel = GetArg("-checklevel", 3);
1047     int nCheckDepth = GetArg("-checkblocks", 288);
1048     if (params.size() > 0)
1049         nCheckLevel = params[0].get_int();
1050     if (params.size() > 1)
1051         nCheckDepth = params[1].get_int();
1052
1053     return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
1054 }
1055
1056 /** Implementation of IsSuperMajority with better feedback */
1057 static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
1058 {
1059     int nFound = 0;
1060     CBlockIndex* pstart = pindex;
1061     for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
1062     {
1063         if (pstart->nVersion >= minVersion)
1064             ++nFound;
1065         pstart = pstart->pprev;
1066     }
1067
1068     UniValue rv(UniValue::VOBJ);
1069     rv.push_back(Pair("status", nFound >= nRequired));
1070     rv.push_back(Pair("found", nFound));
1071     rv.push_back(Pair("required", nRequired));
1072     rv.push_back(Pair("window", consensusParams.nMajorityWindow));
1073     return rv;
1074 }
1075
1076 static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
1077 {
1078     UniValue rv(UniValue::VOBJ);
1079     rv.push_back(Pair("id", name));
1080     rv.push_back(Pair("version", version));
1081     rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
1082     rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
1083     return rv;
1084 }
1085
1086 static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height)
1087 {
1088     UniValue rv(UniValue::VOBJ);
1089     auto upgrade = NetworkUpgradeInfo[idx];
1090     rv.push_back(Pair("name", upgrade.strName));
1091     rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight));
1092     switch (NetworkUpgradeState(height, consensusParams, idx)) {
1093         case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break;
1094         case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break;
1095         case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break;
1096     }
1097     rv.push_back(Pair("info", upgrade.strInfo));
1098     return rv;
1099 }
1100
1101 void NetworkUpgradeDescPushBack(
1102     UniValue& networkUpgrades,
1103     const Consensus::Params& consensusParams,
1104     Consensus::UpgradeIndex idx,
1105     int height)
1106 {
1107     // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are
1108     // hidden. This is used when network upgrade implementations are merged
1109     // without specifying the activation height.
1110     if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) {
1111         networkUpgrades.push_back(Pair(
1112             HexInt(NetworkUpgradeInfo[idx].nBranchId),
1113             NetworkUpgradeDesc(consensusParams, idx, height)));
1114     }
1115 }
1116
1117 UniValue getblockchaininfo(const UniValue& params, bool fHelp)
1118 {
1119     if (fHelp || params.size() != 0)
1120         throw runtime_error(
1121             "getblockchaininfo\n"
1122             "Returns an object containing various state info regarding block chain processing.\n"
1123             "\nNote that when the chain tip is at the last block before a network upgrade activation,\n"
1124             "consensus.chaintip != consensus.nextblock.\n"
1125             "\nResult:\n"
1126             "{\n"
1127             "  \"chain\": \"xxxx\",        (string) current network name as defined in BIP70 (main, test, regtest)\n"
1128             "  \"blocks\": xxxxxx,         (numeric) the current number of blocks processed in the server\n"
1129             "  \"headers\": xxxxxx,        (numeric) the current number of headers we have validated\n"
1130             "  \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
1131             "  \"difficulty\": xxxxxx,     (numeric) the current difficulty\n"
1132             "  \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
1133             "  \"chainwork\": \"xxxx\"     (string) total amount of work in active chain, in hexadecimal\n"
1134             "  \"commitments\": xxxxxx,    (numeric) the current number of note commitments in the commitment tree\n"
1135             "  \"softforks\": [            (array) status of softforks in progress\n"
1136             "     {\n"
1137             "        \"id\": \"xxxx\",        (string) name of softfork\n"
1138             "        \"version\": xx,         (numeric) block version\n"
1139             "        \"enforce\": {           (object) progress toward enforcing the softfork rules for new-version blocks\n"
1140             "           \"status\": xx,       (boolean) true if threshold reached\n"
1141             "           \"found\": xx,        (numeric) number of blocks with the new version found\n"
1142             "           \"required\": xx,     (numeric) number of blocks required to trigger\n"
1143             "           \"window\": xx,       (numeric) maximum size of examined window of recent blocks\n"
1144             "        },\n"
1145             "        \"reject\": { ... }      (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
1146             "     }, ...\n"
1147             "  ],\n"
1148             "  \"upgrades\": {                (object) status of network upgrades\n"
1149             "     \"xxxx\" : {                (string) branch ID of the upgrade\n"
1150             "        \"name\": \"xxxx\",        (string) name of upgrade\n"
1151             "        \"activationheight\": xxxxxx,  (numeric) block height of activation\n"
1152             "        \"status\": \"xxxx\",      (string) status of upgrade\n"
1153             "        \"info\": \"xxxx\",        (string) additional information about upgrade\n"
1154             "     }, ...\n"
1155             "  },\n"
1156             "  \"consensus\": {               (object) branch IDs of the current and upcoming consensus rules\n"
1157             "     \"chaintip\": \"xxxxxxxx\",   (string) branch ID used to validate the current chain tip\n"
1158             "     \"nextblock\": \"xxxxxxxx\"   (string) branch ID that the next block will be validated under\n"
1159             "  }\n"
1160             "}\n"
1161             "\nExamples:\n"
1162             + HelpExampleCli("getblockchaininfo", "")
1163             + HelpExampleRpc("getblockchaininfo", "")
1164         );
1165
1166     LOCK(cs_main);
1167
1168     UniValue obj(UniValue::VOBJ);
1169     obj.push_back(Pair("chain",                 Params().NetworkIDString()));
1170     obj.push_back(Pair("blocks",                (int)chainActive.Height()));
1171     obj.push_back(Pair("headers",               pindexBestHeader ? pindexBestHeader->nHeight : -1));
1172     obj.push_back(Pair("bestblockhash",         chainActive.Tip()->GetBlockHash().GetHex()));
1173     obj.push_back(Pair("difficulty",            (double)GetNetworkDifficulty()));
1174     obj.push_back(Pair("verificationprogress",  Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
1175     obj.push_back(Pair("chainwork",             chainActive.Tip()->nChainWork.GetHex()));
1176     obj.push_back(Pair("pruned",                fPruneMode));
1177
1178     ZCIncrementalMerkleTree tree;
1179     pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree);
1180     #ifdef __APPLE__
1181     obj.push_back(Pair("commitments",           (uint64_t)tree.size()));
1182     #else
1183     obj.push_back(Pair("commitments",           tree.size()));
1184     #endif
1185
1186     CBlockIndex* tip = chainActive.Tip();
1187     UniValue valuePools(UniValue::VARR);
1188     valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none));
1189     obj.push_back(Pair("valuePools",            valuePools));
1190
1191     const Consensus::Params& consensusParams = Params().GetConsensus();
1192     UniValue softforks(UniValue::VARR);
1193     softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
1194     softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
1195     softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
1196     obj.push_back(Pair("softforks",             softforks));
1197
1198     UniValue upgrades(UniValue::VOBJ);
1199     for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) {
1200         NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight);
1201     }
1202     obj.push_back(Pair("upgrades", upgrades));
1203
1204     UniValue consensus(UniValue::VOBJ);
1205     consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams))));
1206     consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams))));
1207     obj.push_back(Pair("consensus", consensus));
1208
1209     if (fPruneMode)
1210     {
1211         CBlockIndex *block = chainActive.Tip();
1212         while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
1213             block = block->pprev;
1214
1215         obj.push_back(Pair("pruneheight",        block->nHeight));
1216     }
1217     return obj;
1218 }
1219
1220 /** Comparison function for sorting the getchaintips heads.  */
1221 struct CompareBlocksByHeight
1222 {
1223     bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
1224     {
1225         /* Make sure that unequal blocks with the same height do not compare
1226            equal. Use the pointers themselves to make a distinction. */
1227
1228         if (a->nHeight != b->nHeight)
1229           return (a->nHeight > b->nHeight);
1230
1231         return a < b;
1232     }
1233 };
1234
1235 UniValue getchaintips(const UniValue& params, bool fHelp)
1236 {
1237     if (fHelp || params.size() != 0)
1238         throw runtime_error(
1239             "getchaintips\n"
1240             "Return information about all known tips in the block tree,"
1241             " including the main chain as well as orphaned branches.\n"
1242             "\nResult:\n"
1243             "[\n"
1244             "  {\n"
1245             "    \"height\": xxxx,         (numeric) height of the chain tip\n"
1246             "    \"hash\": \"xxxx\",         (string) block hash of the tip\n"
1247             "    \"branchlen\": 0          (numeric) zero for main chain\n"
1248             "    \"status\": \"active\"      (string) \"active\" for the main chain\n"
1249             "  },\n"
1250             "  {\n"
1251             "    \"height\": xxxx,\n"
1252             "    \"hash\": \"xxxx\",\n"
1253             "    \"branchlen\": 1          (numeric) length of branch connecting the tip to the main chain\n"
1254             "    \"status\": \"xxxx\"        (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
1255             "  }\n"
1256             "]\n"
1257             "Possible values for status:\n"
1258             "1.  \"invalid\"               This branch contains at least one invalid block\n"
1259             "2.  \"headers-only\"          Not all blocks for this branch are available, but the headers are valid\n"
1260             "3.  \"valid-headers\"         All blocks are available for this branch, but they were never fully validated\n"
1261             "4.  \"valid-fork\"            This branch is not part of the active chain, but is fully validated\n"
1262             "5.  \"active\"                This is the tip of the active main chain, which is certainly valid\n"
1263             "\nExamples:\n"
1264             + HelpExampleCli("getchaintips", "")
1265             + HelpExampleRpc("getchaintips", "")
1266         );
1267
1268     LOCK(cs_main);
1269
1270     /* Build up a list of chain tips.  We start with the list of all
1271        known blocks, and successively remove blocks that appear as pprev
1272        of another block.  */
1273     std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
1274     BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
1275         setTips.insert(item.second);
1276     BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
1277     {
1278         const CBlockIndex* pprev=0;
1279         if ( item.second != 0 )
1280             pprev = item.second->pprev;
1281         if (pprev)
1282             setTips.erase(pprev);
1283     }
1284
1285     // Always report the currently active tip.
1286     setTips.insert(chainActive.Tip());
1287
1288     /* Construct the output array.  */
1289     UniValue res(UniValue::VARR); const CBlockIndex *forked;
1290     BOOST_FOREACH(const CBlockIndex* block, setTips)
1291     BOOST_FOREACH(const CBlockIndex* block, setTips)
1292         {
1293             UniValue obj(UniValue::VOBJ);
1294             obj.push_back(Pair("height", block->nHeight));
1295             obj.push_back(Pair("hash", block->phashBlock->GetHex()));
1296             forked = chainActive.FindFork(block);
1297             if ( forked != 0 )
1298             {
1299                 const int branchLen = block->nHeight - forked->nHeight;
1300                 obj.push_back(Pair("branchlen", branchLen));
1301
1302                 string status;
1303                 if (chainActive.Contains(block)) {
1304                     // This block is part of the currently active chain.
1305                     status = "active";
1306                 } else if (block->nStatus & BLOCK_FAILED_MASK) {
1307                     // This block or one of its ancestors is invalid.
1308                     status = "invalid";
1309                 } else if (block->nChainTx == 0) {
1310                     // This block cannot be connected because full block data for it or one of its parents is missing.
1311                     status = "headers-only";
1312                 } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
1313                     // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
1314                     status = "valid-fork";
1315                 } else if (block->IsValid(BLOCK_VALID_TREE)) {
1316                     // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
1317                     status = "valid-headers";
1318                 } else {
1319                     // No clue.
1320                     status = "unknown";
1321                 }
1322                 obj.push_back(Pair("status", status));
1323             }
1324             res.push_back(obj);
1325         }
1326
1327     return res;
1328 }
1329
1330 UniValue mempoolInfoToJSON()
1331 {
1332     UniValue ret(UniValue::VOBJ);
1333     ret.push_back(Pair("size", (int64_t) mempool.size()));
1334     ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
1335     ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
1336
1337     return ret;
1338 }
1339
1340 UniValue getmempoolinfo(const UniValue& params, bool fHelp)
1341 {
1342     if (fHelp || params.size() != 0)
1343         throw runtime_error(
1344             "getmempoolinfo\n"
1345             "\nReturns details on the active state of the TX memory pool.\n"
1346             "\nResult:\n"
1347             "{\n"
1348             "  \"size\": xxxxx                (numeric) Current tx count\n"
1349             "  \"bytes\": xxxxx               (numeric) Sum of all tx sizes\n"
1350             "  \"usage\": xxxxx               (numeric) Total memory usage for the mempool\n"
1351             "}\n"
1352             "\nExamples:\n"
1353             + HelpExampleCli("getmempoolinfo", "")
1354             + HelpExampleRpc("getmempoolinfo", "")
1355         );
1356
1357     return mempoolInfoToJSON();
1358 }
1359
1360 UniValue invalidateblock(const UniValue& params, bool fHelp)
1361 {
1362     if (fHelp || params.size() != 1)
1363         throw runtime_error(
1364             "invalidateblock \"hash\"\n"
1365             "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
1366             "\nArguments:\n"
1367             "1. hash   (string, required) the hash of the block to mark as invalid\n"
1368             "\nResult:\n"
1369             "\nExamples:\n"
1370             + HelpExampleCli("invalidateblock", "\"blockhash\"")
1371             + HelpExampleRpc("invalidateblock", "\"blockhash\"")
1372         );
1373
1374     std::string strHash = params[0].get_str();
1375     uint256 hash(uint256S(strHash));
1376     CValidationState state;
1377
1378     {
1379         LOCK(cs_main);
1380         if (mapBlockIndex.count(hash) == 0)
1381             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1382
1383         CBlockIndex* pblockindex = mapBlockIndex[hash];
1384         InvalidateBlock(state, pblockindex);
1385     }
1386
1387     if (state.IsValid()) {
1388         ActivateBestChain(state);
1389     }
1390
1391     if (!state.IsValid()) {
1392         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1393     }
1394
1395     return NullUniValue;
1396 }
1397
1398 UniValue reconsiderblock(const UniValue& params, bool fHelp)
1399 {
1400     if (fHelp || params.size() != 1)
1401         throw runtime_error(
1402             "reconsiderblock \"hash\"\n"
1403             "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
1404             "This can be used to undo the effects of invalidateblock.\n"
1405             "\nArguments:\n"
1406             "1. hash   (string, required) the hash of the block to reconsider\n"
1407             "\nResult:\n"
1408             "\nExamples:\n"
1409             + HelpExampleCli("reconsiderblock", "\"blockhash\"")
1410             + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
1411         );
1412
1413     std::string strHash = params[0].get_str();
1414     uint256 hash(uint256S(strHash));
1415     CValidationState state;
1416
1417     {
1418         LOCK(cs_main);
1419         if (mapBlockIndex.count(hash) == 0)
1420             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1421
1422         CBlockIndex* pblockindex = mapBlockIndex[hash];
1423         ReconsiderBlock(state, pblockindex);
1424     }
1425
1426     if (state.IsValid()) {
1427         ActivateBestChain(state);
1428     }
1429
1430     if (!state.IsValid()) {
1431         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1432     }
1433
1434     return NullUniValue;
1435 }
This page took 0.109255 seconds and 4 git commands to generate.