test
[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 "json/json_spirit_value.h"
17
18 using namespace json_spirit;
19 using namespace std;
20
21 extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
22 void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
23
24 double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
25 {
26     // Floating point number that is a multiple of the minimum difficulty,
27     // minimum difficulty = 1.0.
28     if (blockindex == NULL)
29     {
30         if (chainActive.Tip() == NULL)
31             return 1.0;
32         else
33             blockindex = chainActive.Tip();
34     }
35
36     uint32_t bits;
37     if (networkDifficulty) {
38         bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus());
39     } else {
40         bits = blockindex->nBits;
41     }
42
43     uint32_t powLimit =
44         UintToArith256(Params().GetConsensus().powLimit).GetCompact();
45     int nShift = (bits >> 24) & 0xff;
46     int nShiftAmount = (powLimit >> 24) & 0xff;
47
48     double dDiff =
49         (double)(powLimit & 0x00ffffff) / 
50         (double)(bits & 0x00ffffff);
51
52     while (nShift < nShiftAmount)
53     {
54         dDiff *= 256.0;
55         nShift++;
56     }
57     while (nShift > nShiftAmount)
58     {
59         dDiff /= 256.0;
60         nShift--;
61     }
62
63     return dDiff;
64 }
65
66 double GetDifficulty(const CBlockIndex* blockindex)
67 {
68     return GetDifficultyINTERNAL(blockindex, false);
69 }
70
71 double GetNetworkDifficulty(const CBlockIndex* blockindex)
72 {
73     return GetDifficultyINTERNAL(blockindex, true);
74 }
75
76
77 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
78 {
79     Object result;
80     result.push_back(Pair("hash", block.GetHash().GetHex()));
81     int confirmations = -1;
82     // Only report confirmations if the block is on the main chain
83     if (chainActive.Contains(blockindex))
84         confirmations = chainActive.Height() - blockindex->nHeight + 1;
85     result.push_back(Pair("confirmations", confirmations));
86     result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
87     result.push_back(Pair("height", blockindex->nHeight));
88     result.push_back(Pair("version", block.nVersion));
89     result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
90     Array txs;
91     BOOST_FOREACH(const CTransaction&tx, block.vtx)
92     {
93         if(txDetails)
94         {
95             Object objTx;
96             TxToJSON(tx, uint256(), objTx);
97             txs.push_back(objTx);
98         }
99         else
100             txs.push_back(tx.GetHash().GetHex());
101     }
102     result.push_back(Pair("tx", txs));
103     result.push_back(Pair("time", block.GetBlockTime()));
104     result.push_back(Pair("nonce", block.nNonce.GetHex()));
105     result.push_back(Pair("solution", HexStr(block.nSolution)));
106     result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
107     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
108     result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
109
110     if (blockindex->pprev)
111         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
112     CBlockIndex *pnext = chainActive.Next(blockindex);
113     if (pnext)
114         result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
115     return result;
116 }
117
118
119 Value getblockcount(const Array& params, bool fHelp)
120 {
121     if (fHelp || params.size() != 0)
122         throw runtime_error(
123             "getblockcount\n"
124             "\nReturns the number of blocks in the longest block chain.\n"
125             "\nResult:\n"
126             "n    (numeric) The current block count\n"
127             "\nExamples:\n"
128             + HelpExampleCli("getblockcount", "")
129             + HelpExampleRpc("getblockcount", "")
130         );
131
132     LOCK(cs_main);
133     return chainActive.Height();
134 }
135
136 Value getbestblockhash(const Array& params, bool fHelp)
137 {
138     if (fHelp || params.size() != 0)
139         throw runtime_error(
140             "getbestblockhash\n"
141             "\nReturns the hash of the best (tip) block in the longest block chain.\n"
142             "\nResult\n"
143             "\"hex\"      (string) the block hash hex encoded\n"
144             "\nExamples\n"
145             + HelpExampleCli("getbestblockhash", "")
146             + HelpExampleRpc("getbestblockhash", "")
147         );
148
149     LOCK(cs_main);
150     return chainActive.Tip()->GetBlockHash().GetHex();
151 }
152
153 Value getdifficulty(const Array& params, bool fHelp)
154 {
155     if (fHelp || params.size() != 0)
156         throw runtime_error(
157             "getdifficulty\n"
158             "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
159             "\nResult:\n"
160             "n.nnn       (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
161             "\nExamples:\n"
162             + HelpExampleCli("getdifficulty", "")
163             + HelpExampleRpc("getdifficulty", "")
164         );
165
166     LOCK(cs_main);
167     return GetNetworkDifficulty();
168 }
169
170
171 Value getrawmempool(const Array& params, bool fHelp)
172 {
173     if (fHelp || params.size() > 1)
174         throw runtime_error(
175             "getrawmempool ( verbose )\n"
176             "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
177             "\nArguments:\n"
178             "1. verbose           (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
179             "\nResult: (for verbose = false):\n"
180             "[                     (json array of string)\n"
181             "  \"transactionid\"     (string) The transaction id\n"
182             "  ,...\n"
183             "]\n"
184             "\nResult: (for verbose = true):\n"
185             "{                           (json object)\n"
186             "  \"transactionid\" : {       (json object)\n"
187             "    \"size\" : n,             (numeric) transaction size in bytes\n"
188             "    \"fee\" : n,              (numeric) transaction fee in bitcoins\n"
189             "    \"time\" : n,             (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n"
190             "    \"height\" : n,           (numeric) block height when transaction entered pool\n"
191             "    \"startingpriority\" : n, (numeric) priority when transaction entered pool\n"
192             "    \"currentpriority\" : n,  (numeric) transaction priority now\n"
193             "    \"depends\" : [           (array) unconfirmed transactions used as inputs for this transaction\n"
194             "        \"transactionid\",    (string) parent transaction id\n"
195             "       ... ]\n"
196             "  }, ...\n"
197             "}\n"
198             "\nExamples\n"
199             + HelpExampleCli("getrawmempool", "true")
200             + HelpExampleRpc("getrawmempool", "true")
201         );
202
203     LOCK(cs_main);
204
205     bool fVerbose = false;
206     if (params.size() > 0)
207         fVerbose = params[0].get_bool();
208
209     if (fVerbose)
210     {
211         LOCK(mempool.cs);
212         Object o;
213         BOOST_FOREACH(const PAIRTYPE(uint256, CTxMemPoolEntry)& entry, mempool.mapTx)
214         {
215             const uint256& hash = entry.first;
216             const CTxMemPoolEntry& e = entry.second;
217             Object info;
218             info.push_back(Pair("size", (int)e.GetTxSize()));
219             info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
220             info.push_back(Pair("time", e.GetTime()));
221             info.push_back(Pair("height", (int)e.GetHeight()));
222             info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight())));
223             info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height())));
224             const CTransaction& tx = e.GetTx();
225             set<string> setDepends;
226             BOOST_FOREACH(const CTxIn& txin, tx.vin)
227             {
228                 if (mempool.exists(txin.prevout.hash))
229                     setDepends.insert(txin.prevout.hash.ToString());
230             }
231             Array depends(setDepends.begin(), setDepends.end());
232             info.push_back(Pair("depends", depends));
233             o.push_back(Pair(hash.ToString(), info));
234         }
235         return o;
236     }
237     else
238     {
239         vector<uint256> vtxid;
240         mempool.queryHashes(vtxid);
241
242         Array a;
243         BOOST_FOREACH(const uint256& hash, vtxid)
244             a.push_back(hash.ToString());
245
246         return a;
247     }
248 }
249
250 Value getblockhash(const Array& params, bool fHelp)
251 {
252     if (fHelp || params.size() != 1)
253         throw runtime_error(
254             "getblockhash index\n"
255             "\nReturns hash of block in best-block-chain at index provided.\n"
256             "\nArguments:\n"
257             "1. index         (numeric, required) The block index\n"
258             "\nResult:\n"
259             "\"hash\"         (string) The block hash\n"
260             "\nExamples:\n"
261             + HelpExampleCli("getblockhash", "1000")
262             + HelpExampleRpc("getblockhash", "1000")
263         );
264
265     LOCK(cs_main);
266
267     int nHeight = params[0].get_int();
268     if (nHeight < 0 || nHeight > chainActive.Height())
269         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
270
271     CBlockIndex* pblockindex = chainActive[nHeight];
272     return pblockindex->GetBlockHash().GetHex();
273 }
274
275 Value getblock(const Array& params, bool fHelp)
276 {
277     if (fHelp || params.size() < 1 || params.size() > 2)
278         throw runtime_error(
279             "getblock \"hash\" ( verbose )\n"
280             "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
281             "If verbose is true, returns an Object with information about block <hash>.\n"
282             "\nArguments:\n"
283             "1. \"hash\"          (string, required) The block hash\n"
284             "2. verbose           (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
285             "\nResult (for verbose = true):\n"
286             "{\n"
287             "  \"hash\" : \"hash\",     (string) the block hash (same as provided)\n"
288             "  \"confirmations\" : n,   (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
289             "  \"size\" : n,            (numeric) The block size\n"
290             "  \"height\" : n,          (numeric) The block height or index\n"
291             "  \"version\" : n,         (numeric) The block version\n"
292             "  \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
293             "  \"tx\" : [               (array of string) The transaction ids\n"
294             "     \"transactionid\"     (string) The transaction id\n"
295             "     ,...\n"
296             "  ],\n"
297             "  \"time\" : ttt,          (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
298             "  \"nonce\" : n,           (numeric) The nonce\n"
299             "  \"bits\" : \"1d00ffff\", (string) The bits\n"
300             "  \"difficulty\" : x.xxx,  (numeric) The difficulty\n"
301             "  \"previousblockhash\" : \"hash\",  (string) The hash of the previous block\n"
302             "  \"nextblockhash\" : \"hash\"       (string) The hash of the next block\n"
303             "}\n"
304             "\nResult (for verbose=false):\n"
305             "\"data\"             (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
306             "\nExamples:\n"
307             + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
308             + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
309         );
310
311     LOCK(cs_main);
312
313     std::string strHash = params[0].get_str();
314     uint256 hash(uint256S(strHash));
315
316     bool fVerbose = true;
317     if (params.size() > 1)
318         fVerbose = params[1].get_bool();
319
320     if (mapBlockIndex.count(hash) == 0)
321         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
322
323     CBlock block;
324     CBlockIndex* pblockindex = mapBlockIndex[hash];
325
326     if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
327         throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
328
329     if(!ReadBlockFromDisk(block, pblockindex))
330         throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
331
332     if (!fVerbose)
333     {
334         CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
335         ssBlock << block;
336         std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
337         return strHex;
338     }
339
340     return blockToJSON(block, pblockindex);
341 }
342
343 Value gettxoutsetinfo(const Array& params, bool fHelp)
344 {
345     if (fHelp || params.size() != 0)
346         throw runtime_error(
347             "gettxoutsetinfo\n"
348             "\nReturns statistics about the unspent transaction output set.\n"
349             "Note this call may take some time.\n"
350             "\nResult:\n"
351             "{\n"
352             "  \"height\":n,     (numeric) The current block height (index)\n"
353             "  \"bestblock\": \"hex\",   (string) the best block hash hex\n"
354             "  \"transactions\": n,      (numeric) The number of transactions\n"
355             "  \"txouts\": n,            (numeric) The number of output transactions\n"
356             "  \"bytes_serialized\": n,  (numeric) The serialized size\n"
357             "  \"hash_serialized\": \"hash\",   (string) The serialized hash\n"
358             "  \"total_amount\": x.xxx          (numeric) The total amount\n"
359             "}\n"
360             "\nExamples:\n"
361             + HelpExampleCli("gettxoutsetinfo", "")
362             + HelpExampleRpc("gettxoutsetinfo", "")
363         );
364
365     LOCK(cs_main);
366
367     Object ret;
368
369     CCoinsStats stats;
370     FlushStateToDisk();
371     if (pcoinsTip->GetStats(stats)) {
372         ret.push_back(Pair("height", (int64_t)stats.nHeight));
373         ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
374         ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
375         ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
376         ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
377         ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
378         ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
379     }
380     return ret;
381 }
382
383 uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
384 uint32_t komodo_txtime(uint256 hash);
385 uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume);
386 int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
387 int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height);
388 char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
389 uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n);
390
391 Value notaries(const Array& params, bool fHelp)
392 {
393     Array a; Object ret; int32_t i,j,n,m; char *hexstr;  uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr;
394     if ( fHelp || params.size() != 1 )
395         throw runtime_error("notaries height\n");
396     LOCK(cs_main);
397     int32_t height = atoi(params[0].get_str().c_str());
398     if ( height < 0 )
399         height = 0;
400     //fprintf(stderr,"notaries as of height.%d\n",height);
401     if ( height > chainActive.Height()+20000 )
402         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
403     else
404     {
405         if ( (n= komodo_notaries(pubkeys,height)) > 0 )
406         {
407             for (i=0; i<n; i++)
408             {
409                 Object item;
410                 std::string btcaddress,kmdaddress,hex;
411                 hex.resize(66);
412                 hexstr = (char *)hex.data();
413                 for (j=0; j<33; j++)
414                     sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
415                 item.push_back(Pair("pubkey", hex));
416
417                 bitcoin_address(btcaddr,0,pubkeys[i],33);
418                 m = (int32_t)strlen(btcaddr);
419                 btcaddress.resize(m);
420                 ptr = (char *)btcaddress.data();
421                 memcpy(ptr,btcaddr,m);
422                 item.push_back(Pair("BTCaddress", btcaddress));
423
424                 bitcoin_address(kmdaddr,60,pubkeys[i],33);
425                 m = (int32_t)strlen(kmdaddr);
426                 kmdaddress.resize(m);
427                 ptr = (char *)kmdaddress.data();
428                 memcpy(ptr,kmdaddr,m);
429                 item.push_back(Pair("KMDaddress", kmdaddress));
430                 a.push_back(item);
431             }
432         }
433         ret.push_back(Pair("notaries", a));
434     }
435     return ret;
436 }
437
438 Value paxprice(const Array& params, bool fHelp)
439 {
440     if ( fHelp || params.size() < 3 || params.size() > 4 )
441         throw runtime_error("paxprice \"base\" \"rel\" height amount\n");
442     LOCK(cs_main);
443     Object ret; uint64_t basevolume=0,relvolume,seed;
444     std::string base = params[0].get_str();
445     std::string rel = params[1].get_str();
446     int32_t height = atoi(params[2].get_str().c_str());
447     if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
448         basevolume = COIN;
449     relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume);
450     ret.push_back(Pair("base", base));
451     ret.push_back(Pair("rel", rel));
452     ret.push_back(Pair("height", height));
453     char seedstr[32];
454     sprintf(seedstr,"%llu",(long long)seed);
455     ret.push_back(Pair("seed", seedstr));
456     if ( height < 0 || height > chainActive.Height() )
457         throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
458     else
459     {
460         CBlockIndex *pblockindex = chainActive[height];
461         ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime));
462         if ( basevolume != 0 && relvolume != 0 )
463         {
464             ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
465             ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume)));
466             ret.push_back(Pair("basevolume", ValueFromAmount(basevolume)));
467             ret.push_back(Pair("relvolume", ValueFromAmount(relvolume)));
468         } else ret.push_back(Pair("error", "overflow or error in one or more of parameters"));
469     }
470     return ret;
471 }
472
473 Value paxprices(const Array& params, bool fHelp)
474 {
475     if ( fHelp || params.size() != 3 )
476         throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
477     LOCK(cs_main);
478     Object ret; uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
479     std::string base = params[0].get_str();
480     std::string rel = params[1].get_str();
481     int32_t maxsamples = atoi(params[2].get_str().c_str());
482     if ( maxsamples < 1 )
483         maxsamples = 1;
484     else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
485         maxsamples = sizeof(heights)/sizeof(*heights);
486     ret.push_back(Pair("base", base));
487     ret.push_back(Pair("rel", rel));
488     n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
489     Array a;
490     for (i=0; i<n; i++)
491     {
492         Object item;
493         if ( heights[i] < 0 || heights[i] > chainActive.Height() )
494             throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
495         else
496         {
497             CBlockIndex *pblockindex = chainActive[heights[i]];
498             
499             item.push_back(Pair("t", (int64_t)pblockindex->nTime));
500             item.push_back(Pair("p", (double)prices[i] / COIN));
501             a.push_back(item);
502         }
503     }
504     ret.push_back(Pair("array", a));
505     return ret;
506 }
507
508 uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue);
509
510 Value gettxout(const Array& params, bool fHelp)
511 {
512     if (fHelp || params.size() < 2 || params.size() > 3)
513         throw runtime_error(
514             "gettxout \"txid\" n ( includemempool )\n"
515             "\nReturns details about an unspent transaction output.\n"
516             "\nArguments:\n"
517             "1. \"txid\"       (string, required) The transaction id\n"
518             "2. n              (numeric, required) vout value\n"
519             "3. includemempool  (boolean, optional) Whether to included the mem pool\n"
520             "\nResult:\n"
521             "{\n"
522             "  \"bestblock\" : \"hash\",    (string) the block hash\n"
523             "  \"confirmations\" : n,       (numeric) The number of confirmations\n"
524             "  \"value\" : x.xxx,           (numeric) The transaction value in btc\n"
525             "  \"scriptPubKey\" : {         (json object)\n"
526             "     \"asm\" : \"code\",       (string) \n"
527             "     \"hex\" : \"hex\",        (string) \n"
528             "     \"reqSigs\" : n,          (numeric) Number of required signatures\n"
529             "     \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
530             "     \"addresses\" : [          (array of string) array of bitcoin addresses\n"
531             "        \"bitcoinaddress\"     (string) bitcoin address\n"
532             "        ,...\n"
533             "     ]\n"
534             "  },\n"
535             "  \"version\" : n,            (numeric) The version\n"
536             "  \"coinbase\" : true|false   (boolean) Coinbase or not\n"
537             "}\n"
538
539             "\nExamples:\n"
540             "\nGet unspent transactions\n"
541             + HelpExampleCli("listunspent", "") +
542             "\nView the details\n"
543             + HelpExampleCli("gettxout", "\"txid\" 1") +
544             "\nAs a json rpc call\n"
545             + HelpExampleRpc("gettxout", "\"txid\", 1")
546         );
547
548     LOCK(cs_main);
549
550     Object ret;
551
552     std::string strHash = params[0].get_str();
553     uint256 hash(uint256S(strHash));
554     int n = params[1].get_int();
555     bool fMempool = true;
556     if (params.size() > 2)
557         fMempool = params[2].get_bool();
558
559     CCoins coins;
560     if (fMempool) {
561         LOCK(mempool.cs);
562         CCoinsViewMemPool view(pcoinsTip, mempool);
563         if (!view.GetCoins(hash, coins))
564             return Value::null;
565         mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
566     } else {
567         if (!pcoinsTip->GetCoins(hash, coins))
568             return Value::null;
569     }
570     if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
571         return Value::null;
572
573     BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
574     CBlockIndex *pindex = it->second;
575     ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
576     if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
577         ret.push_back(Pair("confirmations", 0));
578     else ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
579     ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
580     uint64_t interest; int32_t txheight; uint32_t locktime;
581     if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue)) != 0 )
582         ret.push_back(Pair("interest", ValueFromAmount(interest)));
583     Object o;
584     ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
585     ret.push_back(Pair("scriptPubKey", o));
586     ret.push_back(Pair("version", coins.nVersion));
587     ret.push_back(Pair("coinbase", coins.fCoinBase));
588
589     return ret;
590 }
591
592 Value verifychain(const Array& params, bool fHelp)
593 {
594     if (fHelp || params.size() > 2)
595         throw runtime_error(
596             "verifychain ( checklevel numblocks )\n"
597             "\nVerifies blockchain database.\n"
598             "\nArguments:\n"
599             "1. checklevel   (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
600             "2. numblocks    (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
601             "\nResult:\n"
602             "true|false       (boolean) Verified or not\n"
603             "\nExamples:\n"
604             + HelpExampleCli("verifychain", "")
605             + HelpExampleRpc("verifychain", "")
606         );
607
608     LOCK(cs_main);
609
610     int nCheckLevel = GetArg("-checklevel", 3);
611     int nCheckDepth = GetArg("-checkblocks", 288);
612     if (params.size() > 0)
613         nCheckLevel = params[0].get_int();
614     if (params.size() > 1)
615         nCheckDepth = params[1].get_int();
616
617     return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
618 }
619
620 /** Implementation of IsSuperMajority with better feedback */
621 Object SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
622 {
623     int nFound = 0;
624     CBlockIndex* pstart = pindex;
625     for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
626     {
627         if (pstart->nVersion >= minVersion)
628             ++nFound;
629         pstart = pstart->pprev;
630     }
631
632     Object rv;
633     rv.push_back(Pair("status", nFound >= nRequired));
634     rv.push_back(Pair("found", nFound));
635     rv.push_back(Pair("required", nRequired));
636     rv.push_back(Pair("window", consensusParams.nMajorityWindow));
637     return rv;
638 }
639
640 Object SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
641 {
642     Object rv;
643     rv.push_back(Pair("id", name));
644     rv.push_back(Pair("version", version));
645     rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
646     rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
647     return rv;
648 }
649
650 Value getblockchaininfo(const Array& params, bool fHelp)
651 {
652     if (fHelp || params.size() != 0)
653         throw runtime_error(
654             "getblockchaininfo\n"
655             "Returns an object containing various state info regarding block chain processing.\n"
656             "\nResult:\n"
657             "{\n"
658             "  \"chain\": \"xxxx\",        (string) current network name as defined in BIP70 (main, test, regtest)\n"
659             "  \"blocks\": xxxxxx,         (numeric) the current number of blocks processed in the server\n"
660             "  \"headers\": xxxxxx,        (numeric) the current number of headers we have validated\n"
661             "  \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
662             "  \"difficulty\": xxxxxx,     (numeric) the current difficulty\n"
663             "  \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
664             "  \"chainwork\": \"xxxx\"     (string) total amount of work in active chain, in hexadecimal\n"
665             "  \"softforks\": [            (array) status of softforks in progress\n"
666             "     {\n"
667             "        \"id\": \"xxxx\",        (string) name of softfork\n"
668             "        \"version\": xx,         (numeric) block version\n"
669             "        \"enforce\": {           (object) progress toward enforcing the softfork rules for new-version blocks\n"
670             "           \"status\": xx,       (boolean) true if threshold reached\n"
671             "           \"found\": xx,        (numeric) number of blocks with the new version found\n"
672             "           \"required\": xx,     (numeric) number of blocks required to trigger\n"
673             "           \"window\": xx,       (numeric) maximum size of examined window of recent blocks\n"
674             "        },\n"
675             "        \"reject\": { ... }      (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
676             "     }, ...\n"
677             "  ]\n"
678             "}\n"
679             "\nExamples:\n"
680             + HelpExampleCli("getblockchaininfo", "")
681             + HelpExampleRpc("getblockchaininfo", "")
682         );
683
684     LOCK(cs_main);
685
686     Object obj;
687     obj.push_back(Pair("chain",                 Params().NetworkIDString()));
688     obj.push_back(Pair("blocks",                (int)chainActive.Height()));
689     obj.push_back(Pair("headers",               pindexBestHeader ? pindexBestHeader->nHeight : -1));
690     obj.push_back(Pair("bestblockhash",         chainActive.Tip()->GetBlockHash().GetHex()));
691     obj.push_back(Pair("difficulty",            (double)GetNetworkDifficulty()));
692     obj.push_back(Pair("verificationprogress",  Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
693     obj.push_back(Pair("chainwork",             chainActive.Tip()->nChainWork.GetHex()));
694     obj.push_back(Pair("pruned",                fPruneMode));
695
696     const Consensus::Params& consensusParams = Params().GetConsensus();
697     CBlockIndex* tip = chainActive.Tip();
698     Array softforks;
699     softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
700     softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
701     softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
702     obj.push_back(Pair("softforks",             softforks));
703
704     if (fPruneMode)
705     {
706         CBlockIndex *block = chainActive.Tip();
707         while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
708             block = block->pprev;
709
710         obj.push_back(Pair("pruneheight",        block->nHeight));
711     }
712     return obj;
713 }
714
715 /** Comparison function for sorting the getchaintips heads.  */
716 struct CompareBlocksByHeight
717 {
718     bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
719     {
720         /* Make sure that unequal blocks with the same height do not compare
721            equal. Use the pointers themselves to make a distinction. */
722
723         if (a->nHeight != b->nHeight)
724           return (a->nHeight > b->nHeight);
725
726         return a < b;
727     }
728 };
729
730 Value getchaintips(const Array& params, bool fHelp)
731 {
732     if (fHelp || params.size() != 0)
733         throw runtime_error(
734             "getchaintips\n"
735             "Return information about all known tips in the block tree,"
736             " including the main chain as well as orphaned branches.\n"
737             "\nResult:\n"
738             "[\n"
739             "  {\n"
740             "    \"height\": xxxx,         (numeric) height of the chain tip\n"
741             "    \"hash\": \"xxxx\",         (string) block hash of the tip\n"
742             "    \"branchlen\": 0          (numeric) zero for main chain\n"
743             "    \"status\": \"active\"      (string) \"active\" for the main chain\n"
744             "  },\n"
745             "  {\n"
746             "    \"height\": xxxx,\n"
747             "    \"hash\": \"xxxx\",\n"
748             "    \"branchlen\": 1          (numeric) length of branch connecting the tip to the main chain\n"
749             "    \"status\": \"xxxx\"        (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
750             "  }\n"
751             "]\n"
752             "Possible values for status:\n"
753             "1.  \"invalid\"               This branch contains at least one invalid block\n"
754             "2.  \"headers-only\"          Not all blocks for this branch are available, but the headers are valid\n"
755             "3.  \"valid-headers\"         All blocks are available for this branch, but they were never fully validated\n"
756             "4.  \"valid-fork\"            This branch is not part of the active chain, but is fully validated\n"
757             "5.  \"active\"                This is the tip of the active main chain, which is certainly valid\n"
758             "\nExamples:\n"
759             + HelpExampleCli("getchaintips", "")
760             + HelpExampleRpc("getchaintips", "")
761         );
762
763     LOCK(cs_main);
764
765     /* Build up a list of chain tips.  We start with the list of all
766        known blocks, and successively remove blocks that appear as pprev
767        of another block.  */
768     std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
769     BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
770         setTips.insert(item.second);
771     BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
772     {
773         const CBlockIndex* pprev = item.second->pprev;
774         if (pprev)
775             setTips.erase(pprev);
776     }
777
778     // Always report the currently active tip.
779     setTips.insert(chainActive.Tip());
780
781     /* Construct the output array.  */
782     Array res;
783     BOOST_FOREACH(const CBlockIndex* block, setTips)
784     {
785         Object obj;
786         obj.push_back(Pair("height", block->nHeight));
787         obj.push_back(Pair("hash", block->phashBlock->GetHex()));
788
789         const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
790         obj.push_back(Pair("branchlen", branchLen));
791
792         string status;
793         if (chainActive.Contains(block)) {
794             // This block is part of the currently active chain.
795             status = "active";
796         } else if (block->nStatus & BLOCK_FAILED_MASK) {
797             // This block or one of its ancestors is invalid.
798             status = "invalid";
799         } else if (block->nChainTx == 0) {
800             // This block cannot be connected because full block data for it or one of its parents is missing.
801             status = "headers-only";
802         } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
803             // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
804             status = "valid-fork";
805         } else if (block->IsValid(BLOCK_VALID_TREE)) {
806             // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
807             status = "valid-headers";
808         } else {
809             // No clue.
810             status = "unknown";
811         }
812         obj.push_back(Pair("status", status));
813
814         res.push_back(obj);
815     }
816
817     return res;
818 }
819
820 Value getmempoolinfo(const Array& params, bool fHelp)
821 {
822     if (fHelp || params.size() != 0)
823         throw runtime_error(
824             "getmempoolinfo\n"
825             "\nReturns details on the active state of the TX memory pool.\n"
826             "\nResult:\n"
827             "{\n"
828             "  \"size\": xxxxx                (numeric) Current tx count\n"
829             "  \"bytes\": xxxxx               (numeric) Sum of all tx sizes\n"
830             "}\n"
831             "\nExamples:\n"
832             + HelpExampleCli("getmempoolinfo", "")
833             + HelpExampleRpc("getmempoolinfo", "")
834         );
835
836     Object ret;
837     ret.push_back(Pair("size", (int64_t) mempool.size()));
838     ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
839
840     return ret;
841 }
842
843 Value invalidateblock(const Array& params, bool fHelp)
844 {
845     if (fHelp || params.size() != 1)
846         throw runtime_error(
847             "invalidateblock \"hash\"\n"
848             "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
849             "\nArguments:\n"
850             "1. hash   (string, required) the hash of the block to mark as invalid\n"
851             "\nResult:\n"
852             "\nExamples:\n"
853             + HelpExampleCli("invalidateblock", "\"blockhash\"")
854             + HelpExampleRpc("invalidateblock", "\"blockhash\"")
855         );
856
857     std::string strHash = params[0].get_str();
858     uint256 hash(uint256S(strHash));
859     CValidationState state;
860
861     {
862         LOCK(cs_main);
863         if (mapBlockIndex.count(hash) == 0)
864             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
865
866         CBlockIndex* pblockindex = mapBlockIndex[hash];
867         InvalidateBlock(state, pblockindex);
868     }
869
870     if (state.IsValid()) {
871         ActivateBestChain(state);
872     }
873
874     if (!state.IsValid()) {
875         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
876     }
877
878     return Value::null;
879 }
880
881 Value reconsiderblock(const Array& params, bool fHelp)
882 {
883     if (fHelp || params.size() != 1)
884         throw runtime_error(
885             "reconsiderblock \"hash\"\n"
886             "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
887             "This can be used to undo the effects of invalidateblock.\n"
888             "\nArguments:\n"
889             "1. hash   (string, required) the hash of the block to reconsider\n"
890             "\nResult:\n"
891             "\nExamples:\n"
892             + HelpExampleCli("reconsiderblock", "\"blockhash\"")
893             + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
894         );
895
896     std::string strHash = params[0].get_str();
897     uint256 hash(uint256S(strHash));
898     CValidationState state;
899
900     {
901         LOCK(cs_main);
902         if (mapBlockIndex.count(hash) == 0)
903             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
904
905         CBlockIndex* pblockindex = mapBlockIndex[hash];
906         ReconsiderBlock(state, pblockindex);
907     }
908
909     if (state.IsValid()) {
910         ActivateBestChain(state);
911     }
912
913     if (!state.IsValid()) {
914         throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
915     }
916
917     return Value::null;
918 }
This page took 0.074899 seconds and 4 git commands to generate.