]> Git Repo - VerusCoin.git/blame - src/rpcblockchain.cpp
test
[VerusCoin.git] / src / rpcblockchain.cpp
CommitLineData
c625ae04 1// Copyright (c) 2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
72fb3d29 3// Distributed under the MIT software license, see the accompanying
c625ae04
JG
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
ac14bcc1 6#include "checkpoints.h"
da29ecbc 7#include "consensus/validation.h"
51ed9ec9 8#include "main.h"
da29ecbc 9#include "primitives/transaction.h"
ac14bcc1 10#include "rpcserver.h"
51ed9ec9 11#include "sync.h"
ad49c256 12#include "util.h"
51ed9ec9
BD
13
14#include <stdint.h>
15
16#include "json/json_spirit_value.h"
c625ae04
JG
17
18using namespace json_spirit;
19using namespace std;
20
73351c36 21extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry);
be066fad 22void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex);
4e68391a 23
695a7a88 24double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
c625ae04
JG
25{
26 // Floating point number that is a multiple of the minimum difficulty,
27 // minimum difficulty = 1.0.
28 if (blockindex == NULL)
29 {
4c6d41b8 30 if (chainActive.Tip() == NULL)
c625ae04
JG
31 return 1.0;
32 else
4c6d41b8 33 blockindex = chainActive.Tip();
c625ae04
JG
34 }
35
333ea3c4
JG
36 uint32_t bits;
37 if (networkDifficulty) {
38 bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus());
39 } else {
40 bits = blockindex->nBits;
695a7a88
JG
41 }
42
333ea3c4 43 uint32_t powLimit =
f50e8313 44 UintToArith256(Params().GetConsensus().powLimit).GetCompact();
333ea3c4 45 int nShift = (bits >> 24) & 0xff;
24809b16 46 int nShiftAmount = (powLimit >> 24) & 0xff;
c625ae04
JG
47
48 double dDiff =
24809b16 49 (double)(powLimit & 0x00ffffff) /
333ea3c4 50 (double)(bits & 0x00ffffff);
c625ae04 51
24809b16 52 while (nShift < nShiftAmount)
c625ae04
JG
53 {
54 dDiff *= 256.0;
55 nShift++;
56 }
24809b16 57 while (nShift > nShiftAmount)
c625ae04
JG
58 {
59 dDiff /= 256.0;
60 nShift--;
61 }
62
63 return dDiff;
64}
65
695a7a88
JG
66double GetDifficulty(const CBlockIndex* blockindex)
67{
68 return GetDifficultyINTERNAL(blockindex, false);
69}
70
71double GetNetworkDifficulty(const CBlockIndex* blockindex)
72{
73 return GetDifficultyINTERNAL(blockindex, true);
74}
75
c625ae04 76
73351c36 77Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
c625ae04
JG
78{
79 Object result;
80 result.push_back(Pair("hash", block.GetHash().GetHex()));
57153d4e
WL
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));
c625ae04
JG
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)
73351c36
JS
92 {
93 if(txDetails)
94 {
95 Object objTx;
4f152496 96 TxToJSON(tx, uint256(), objTx);
73351c36
JS
97 txs.push_back(objTx);
98 }
99 else
805344dc 100 txs.push_back(tx.GetHash().GetHex());
73351c36 101 }
c625ae04 102 result.push_back(Pair("tx", txs));
d56e30ca 103 result.push_back(Pair("time", block.GetBlockTime()));
fdda3c50 104 result.push_back(Pair("nonce", block.nNonce.GetHex()));
e1dde421 105 result.push_back(Pair("solution", HexStr(block.nSolution)));
645d497a 106 result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
c625ae04 107 result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
1b3656d5 108 result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
c625ae04
JG
109
110 if (blockindex->pprev)
111 result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
4c6d41b8 112 CBlockIndex *pnext = chainActive.Next(blockindex);
0fe8010a
PW
113 if (pnext)
114 result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
c625ae04
JG
115 return result;
116}
117
118
119Value getblockcount(const Array& params, bool fHelp)
120{
121 if (fHelp || params.size() != 0)
122 throw runtime_error(
123 "getblockcount\n"
a6099ef3 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 );
c625ae04 131
4401b2d7 132 LOCK(cs_main);
4c6d41b8 133 return chainActive.Height();
c625ae04
JG
134}
135
091aa8da
JG
136Value getbestblockhash(const Array& params, bool fHelp)
137{
138 if (fHelp || params.size() != 0)
139 throw runtime_error(
140 "getbestblockhash\n"
a6099ef3 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 );
091aa8da 148
4401b2d7 149 LOCK(cs_main);
4c6d41b8 150 return chainActive.Tip()->GetBlockHash().GetHex();
091aa8da 151}
c625ae04
JG
152
153Value getdifficulty(const Array& params, bool fHelp)
154{
155 if (fHelp || params.size() != 0)
156 throw runtime_error(
157 "getdifficulty\n"
a6099ef3 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 );
c625ae04 165
4401b2d7 166 LOCK(cs_main);
695a7a88 167 return GetNetworkDifficulty();
c625ae04
JG
168}
169
170
c625ae04
JG
171Value getrawmempool(const Array& params, bool fHelp)
172{
4d707d51 173 if (fHelp || params.size() > 1)
c625ae04 174 throw runtime_error(
4d707d51 175 "getrawmempool ( verbose )\n"
a6099ef3 176 "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
4d707d51
GA
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"
a6099ef3 181 " \"transactionid\" (string) The transaction id\n"
182 " ,...\n"
183 "]\n"
4d707d51
GA
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"
803f51ef 197 "}\n"
a6099ef3 198 "\nExamples\n"
4d707d51
GA
199 + HelpExampleCli("getrawmempool", "true")
200 + HelpExampleRpc("getrawmempool", "true")
a6099ef3 201 );
c625ae04 202
4401b2d7
EL
203 LOCK(cs_main);
204
4d707d51
GA
205 bool fVerbose = false;
206 if (params.size() > 0)
207 fVerbose = params[0].get_bool();
c625ae04 208
4d707d51
GA
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())));
d56e30ca 220 info.push_back(Pair("time", e.GetTime()));
4d707d51
GA
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);
c625ae04 241
4d707d51
GA
242 Array a;
243 BOOST_FOREACH(const uint256& hash, vtxid)
244 a.push_back(hash.ToString());
245
246 return a;
247 }
c625ae04
JG
248}
249
250Value getblockhash(const Array& params, bool fHelp)
251{
252 if (fHelp || params.size() != 1)
253 throw runtime_error(
a6099ef3 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 );
c625ae04 264
4401b2d7
EL
265 LOCK(cs_main);
266
c625ae04 267 int nHeight = params[0].get_int();
4c6d41b8 268 if (nHeight < 0 || nHeight > chainActive.Height())
6261e6e6 269 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
c625ae04 270
4c6d41b8
PW
271 CBlockIndex* pblockindex = chainActive[nHeight];
272 return pblockindex->GetBlockHash().GetHex();
c625ae04
JG
273}
274
b4e5b1d6 275uint256 _komodo_getblockhash(int32_t nHeight)
6b0e06b5 276{
277 uint256 hash;
278 LOCK(cs_main);
279 if ( nHeight >= 0 && nHeight <= chainActive.Height() )
280 {
281 CBlockIndex* pblockindex = chainActive[nHeight];
282 hash = pblockindex->GetBlockHash();
aa81a2b8 283 int32_t i;
284 for (i=0; i<32; i++)
285 printf("%02x",((uint8_t *)&hash)[i]);
286 printf(" blockhash.%d\n",nHeight);
6b0e06b5 287 } else memset(&hash,0,sizeof(hash));
288 return(hash);
289}
290
c625ae04
JG
291Value getblock(const Array& params, bool fHelp)
292{
23319521 293 if (fHelp || params.size() < 1 || params.size() > 2)
c625ae04 294 throw runtime_error(
a6099ef3 295 "getblock \"hash\" ( verbose )\n"
296 "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
297 "If verbose is true, returns an Object with information about block <hash>.\n"
298 "\nArguments:\n"
299 "1. \"hash\" (string, required) The block hash\n"
300 "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
301 "\nResult (for verbose = true):\n"
302 "{\n"
303 " \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
57153d4e 304 " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
a6099ef3 305 " \"size\" : n, (numeric) The block size\n"
306 " \"height\" : n, (numeric) The block height or index\n"
307 " \"version\" : n, (numeric) The block version\n"
308 " \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
309 " \"tx\" : [ (array of string) The transaction ids\n"
310 " \"transactionid\" (string) The transaction id\n"
311 " ,...\n"
312 " ],\n"
313 " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
314 " \"nonce\" : n, (numeric) The nonce\n"
315 " \"bits\" : \"1d00ffff\", (string) The bits\n"
316 " \"difficulty\" : x.xxx, (numeric) The difficulty\n"
317 " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
318 " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
319 "}\n"
320 "\nResult (for verbose=false):\n"
321 "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
322 "\nExamples:\n"
323 + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
324 + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
23319521 325 );
c625ae04 326
4401b2d7
EL
327 LOCK(cs_main);
328
c625ae04 329 std::string strHash = params[0].get_str();
34cdc411 330 uint256 hash(uint256S(strHash));
c625ae04 331
23319521
LD
332 bool fVerbose = true;
333 if (params.size() > 1)
334 fVerbose = params[1].get_bool();
335
c625ae04 336 if (mapBlockIndex.count(hash) == 0)
738835d7 337 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
c625ae04
JG
338
339 CBlock block;
340 CBlockIndex* pblockindex = mapBlockIndex[hash];
954d2e72 341
03c56872
JS
342 if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
343 throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
344
f2dd868d 345 if(!ReadBlockFromDisk(block, pblockindex))
954d2e72 346 throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
c625ae04 347
23319521
LD
348 if (!fVerbose)
349 {
350 CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
351 ssBlock << block;
352 std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
353 return strHex;
354 }
355
c625ae04
JG
356 return blockToJSON(block, pblockindex);
357}
358
beeb5761
PW
359Value gettxoutsetinfo(const Array& params, bool fHelp)
360{
361 if (fHelp || params.size() != 0)
362 throw runtime_error(
363 "gettxoutsetinfo\n"
a6099ef3 364 "\nReturns statistics about the unspent transaction output set.\n"
365 "Note this call may take some time.\n"
366 "\nResult:\n"
367 "{\n"
368 " \"height\":n, (numeric) The current block height (index)\n"
369 " \"bestblock\": \"hex\", (string) the best block hash hex\n"
370 " \"transactions\": n, (numeric) The number of transactions\n"
371 " \"txouts\": n, (numeric) The number of output transactions\n"
372 " \"bytes_serialized\": n, (numeric) The serialized size\n"
373 " \"hash_serialized\": \"hash\", (string) The serialized hash\n"
374 " \"total_amount\": x.xxx (numeric) The total amount\n"
375 "}\n"
376 "\nExamples:\n"
377 + HelpExampleCli("gettxoutsetinfo", "")
378 + HelpExampleRpc("gettxoutsetinfo", "")
379 );
beeb5761 380
4401b2d7
EL
381 LOCK(cs_main);
382
beeb5761
PW
383 Object ret;
384
385 CCoinsStats stats;
51ce901a 386 FlushStateToDisk();
beeb5761 387 if (pcoinsTip->GetStats(stats)) {
4b61a6a4 388 ret.push_back(Pair("height", (int64_t)stats.nHeight));
e31aa7c9 389 ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
4b61a6a4
KD
390 ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
391 ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
392 ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize));
e31aa7c9
PW
393 ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex()));
394 ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
beeb5761
PW
395 }
396 return ret;
397}
c625ae04 398
17878015 399uint64_t komodo_interest(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
7a77c443 400uint32_t komodo_txtime(uint256 hash);
0bda6249 401uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume);
d836ec3f 402int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel);
1e9d15c6 403int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height);
404char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
50760585 405uint32_t komodo_interest_args(int32_t *txheightp,uint32_t *tiptimep,uint64_t *valuep,uint256 hash,int32_t n);
dbaf1154 406int32_t komodo_minerids(uint8_t *minerids,int32_t height);
407
408Value minerids(const Array& params, bool fHelp)
409{
47cbf8e6 410 Object ret; Array a; uint8_t minerids[1000],pubkeys[64][33]; int32_t i,j,n,numnotaries,tally[65];
dbaf1154 411 if ( fHelp || params.size() != 1 )
412 throw runtime_error("minerids needs height\n");
413 LOCK(cs_main);
056447a6 414 int32_t height = atoi(params[0].get_str().c_str());
55ecfab2 415 if ( height <= 0 )
416 height = chainActive.Tip()->nHeight;
d6be719d 417 if ( (n= komodo_minerids(minerids,height)) > 0 )
dbaf1154 418 {
419 memset(tally,0,sizeof(tally));
47cbf8e6 420 numnotaries = komodo_notaries(pubkeys,height);
421 if ( numnotaries > 0 )
dbaf1154 422 {
47cbf8e6 423 for (i=0; i<n; i++)
424 {
425 if ( minerids[i] >= numnotaries )
426 tally[64]++;
427 else tally[minerids[i]]++;
428 }
dbaf1154 429 for (i=0; i<64; i++)
430 {
1855a4ed 431 Object item; std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m;
dbaf1154 432 hex.resize(66);
433 hexstr = (char *)hex.data();
434 for (j=0; j<33; j++)
435 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
8711ee8f 436 item.push_back(Pair("notaryid", i));
1855a4ed 437
438 bitcoin_address(kmdaddr,60,pubkeys[i],33);
439 m = (int32_t)strlen(kmdaddr);
440 kmdaddress.resize(m);
441 ptr = (char *)kmdaddress.data();
442 memcpy(ptr,kmdaddr,m);
443 item.push_back(Pair("KMDaddress", kmdaddress));
444
dbaf1154 445 item.push_back(Pair("pubkey", hex));
446 item.push_back(Pair("blocks", tally[i]));
447 a.push_back(item);
448 }
55ecfab2 449 Object item;
14ecdc67 450 item.push_back(Pair("pubkey", (char *)"external miners"));
451 item.push_back(Pair("blocks", tally[64]));
452 a.push_back(item);
dbaf1154 453 }
454 ret.push_back(Pair("mined", a));
455 } else ret.push_back(Pair("error", (char *)"couldnt extract minerids"));
456 return ret;
457}
e596e202 458
1e9d15c6 459Value notaries(const Array& params, bool fHelp)
460{
ff4657a7 461 Array a; Object ret; int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr;
1e9d15c6 462 if ( fHelp || params.size() != 1 )
463 throw runtime_error("notaries height\n");
464 LOCK(cs_main);
a8af456e 465 int32_t height = atoi(params[0].get_str().c_str());
895f044a 466 if ( height < 0 )
467 height = 0;
6677fa31 468 //fprintf(stderr,"notaries as of height.%d\n",height);
c29e766f 469 //if ( height > chainActive.Height()+20000 )
470 // throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
471 //else
1e9d15c6 472 {
1e9d15c6 473 if ( (n= komodo_notaries(pubkeys,height)) > 0 )
474 {
475 for (i=0; i<n; i++)
476 {
98622aa7 477 Object item;
ff4657a7 478 std::string btcaddress,kmdaddress,hex;
1ffa653a 479 hex.resize(66);
480 hexstr = (char *)hex.data();
481 for (j=0; j<33; j++)
482 sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]);
483 item.push_back(Pair("pubkey", hex));
484
1e9d15c6 485 bitcoin_address(btcaddr,0,pubkeys[i],33);
486 m = (int32_t)strlen(btcaddr);
69900ca4 487 btcaddress.resize(m);
1e9d15c6 488 ptr = (char *)btcaddress.data();
6eb6f5f7 489 memcpy(ptr,btcaddr,m);
1ffa653a 490 item.push_back(Pair("BTCaddress", btcaddress));
491
1e9d15c6 492 bitcoin_address(kmdaddr,60,pubkeys[i],33);
493 m = (int32_t)strlen(kmdaddr);
69900ca4 494 kmdaddress.resize(m);
1e9d15c6 495 ptr = (char *)kmdaddress.data();
69900ca4 496 memcpy(ptr,kmdaddr,m);
1e9d15c6 497 item.push_back(Pair("KMDaddress", kmdaddress));
498 a.push_back(item);
499 }
500 }
501 ret.push_back(Pair("notaries", a));
37e7db08 502 ret.push_back(Pair("numnotaries", n));
1e9d15c6 503 }
504 return ret;
505}
a9869d0d 506
9bd3a9cd 507int32_t komodo_pending_withdraws(char *opretstr);
aa114a60 508int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base);
700606cc 509extern char CURRENCIES[][8];
9bd3a9cd 510
511Value paxpending(const Array& params, bool fHelp)
7cc6844b 512{
aa114a60 513 Object ret; Array a; char opretbuf[10000*2]; int32_t opretlen,baseid; uint64_t available,deposited,issued,withdrawn,approved,redeemed;
7cc6844b 514 if ( fHelp || params.size() != 0 )
9bd3a9cd 515 throw runtime_error("paxpending needs no args\n");
7cc6844b 516 LOCK(cs_main);
517 if ( (opretlen= komodo_pending_withdraws(opretbuf)) > 0 )
518 ret.push_back(Pair("withdraws", opretbuf));
519 else ret.push_back(Pair("withdraws", (char *)""));
3cbfd2b4 520 for (baseid=0; baseid<32; baseid++)
521 {
522 Object item,obj;
51ee9373 523 if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 )
3cbfd2b4 524 {
525 if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 )
526 {
aa114a60 527 item.push_back(Pair("available", ValueFromAmount(available)));
1db587b5 528 item.push_back(Pair("deposited", ValueFromAmount(deposited)));
529 item.push_back(Pair("issued", ValueFromAmount(issued)));
530 item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn)));
531 item.push_back(Pair("approved", ValueFromAmount(approved)));
532 item.push_back(Pair("redeemed", ValueFromAmount(redeemed)));
3cbfd2b4 533 obj.push_back(Pair(CURRENCIES[baseid],item));
534 a.push_back(obj);
535 }
536 }
537 }
538 ret.push_back(Pair("fiatstatus", a));
7cc6844b 539 return ret;
540}
541
a9869d0d 542Value paxprice(const Array& params, bool fHelp)
543{
1f346363 544 if ( fHelp || params.size() < 3 || params.size() > 4 )
05f1a5d1 545 throw runtime_error("paxprice \"base\" \"rel\" height amount\n");
a9869d0d 546 LOCK(cs_main);
0bda6249 547 Object ret; uint64_t basevolume=0,relvolume,seed;
a9869d0d 548 std::string base = params[0].get_str();
549 std::string rel = params[1].get_str();
96eb75ee 550 int32_t height = atoi(params[2].get_str().c_str());
05f1a5d1 551 if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 )
1f346363 552 basevolume = COIN;
0bda6249 553 relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume);
a9869d0d 554 ret.push_back(Pair("base", base));
555 ret.push_back(Pair("rel", rel));
556 ret.push_back(Pair("height", height));
73ccdf55 557 char seedstr[32];
558 sprintf(seedstr,"%llu",(long long)seed);
559 ret.push_back(Pair("seed", seedstr));
d019c447 560 if ( height < 0 || height > chainActive.Height() )
561 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
562 else
1f346363 563 {
d019c447 564 CBlockIndex *pblockindex = chainActive[height];
1d8bddf7 565 ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime));
d019c447 566 if ( basevolume != 0 && relvolume != 0 )
567 {
568 ret.push_back(Pair("price",((double)relvolume / (double)basevolume)));
569 ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume)));
570 ret.push_back(Pair("basevolume", ValueFromAmount(basevolume)));
571 ret.push_back(Pair("relvolume", ValueFromAmount(relvolume)));
46e78b7f 572 } else ret.push_back(Pair("error", "overflow or error in one or more of parameters"));
a4ebaad7 573 }
574 return ret;
575}
576
577Value paxprices(const Array& params, bool fHelp)
578{
579 if ( fHelp || params.size() != 3 )
d836ec3f 580 throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n");
a4ebaad7 581 LOCK(cs_main);
d836ec3f 582 Object ret; uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)];
a4ebaad7 583 std::string base = params[0].get_str();
584 std::string rel = params[1].get_str();
0d195951 585 int32_t maxsamples = atoi(params[2].get_str().c_str());
05dfe053 586 if ( maxsamples < 1 )
587 maxsamples = 1;
d836ec3f 588 else if ( maxsamples > sizeof(heights)/sizeof(*heights) )
589 maxsamples = sizeof(heights)/sizeof(*heights);
a4ebaad7 590 ret.push_back(Pair("base", base));
591 ret.push_back(Pair("rel", rel));
d836ec3f 592 n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str());
96eb75ee 593 Array a;
594 for (i=0; i<n; i++)
a4ebaad7 595 {
96eb75ee 596 Object item;
56d91e9c 597 if ( heights[i] < 0 || heights[i] > chainActive.Height() )
598 throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
599 else
600 {
601 CBlockIndex *pblockindex = chainActive[heights[i]];
602
603 item.push_back(Pair("t", (int64_t)pblockindex->nTime));
604 item.push_back(Pair("p", (double)prices[i] / COIN));
605 a.push_back(item);
606 }
1f346363 607 }
96eb75ee 608 ret.push_back(Pair("array", a));
a9869d0d 609 return ret;
610}
7a77c443 611
798f28c7 612uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue);
0fec0cc4 613
beeb5761
PW
614Value gettxout(const Array& params, bool fHelp)
615{
616 if (fHelp || params.size() < 2 || params.size() > 3)
617 throw runtime_error(
a6099ef3 618 "gettxout \"txid\" n ( includemempool )\n"
619 "\nReturns details about an unspent transaction output.\n"
620 "\nArguments:\n"
621 "1. \"txid\" (string, required) The transaction id\n"
622 "2. n (numeric, required) vout value\n"
623 "3. includemempool (boolean, optional) Whether to included the mem pool\n"
624 "\nResult:\n"
625 "{\n"
626 " \"bestblock\" : \"hash\", (string) the block hash\n"
627 " \"confirmations\" : n, (numeric) The number of confirmations\n"
628 " \"value\" : x.xxx, (numeric) The transaction value in btc\n"
629 " \"scriptPubKey\" : { (json object)\n"
630 " \"asm\" : \"code\", (string) \n"
631 " \"hex\" : \"hex\", (string) \n"
632 " \"reqSigs\" : n, (numeric) Number of required signatures\n"
633 " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n"
634 " \"addresses\" : [ (array of string) array of bitcoin addresses\n"
635 " \"bitcoinaddress\" (string) bitcoin address\n"
636 " ,...\n"
637 " ]\n"
638 " },\n"
639 " \"version\" : n, (numeric) The version\n"
640 " \"coinbase\" : true|false (boolean) Coinbase or not\n"
641 "}\n"
642
643 "\nExamples:\n"
644 "\nGet unspent transactions\n"
645 + HelpExampleCli("listunspent", "") +
646 "\nView the details\n"
647 + HelpExampleCli("gettxout", "\"txid\" 1") +
648 "\nAs a json rpc call\n"
649 + HelpExampleRpc("gettxout", "\"txid\", 1")
650 );
c625ae04 651
4401b2d7
EL
652 LOCK(cs_main);
653
beeb5761
PW
654 Object ret;
655
656 std::string strHash = params[0].get_str();
34cdc411 657 uint256 hash(uint256S(strHash));
beeb5761
PW
658 int n = params[1].get_int();
659 bool fMempool = true;
660 if (params.size() > 2)
661 fMempool = params[2].get_bool();
662
663 CCoins coins;
664 if (fMempool) {
665 LOCK(mempool.cs);
7c70438d 666 CCoinsViewMemPool view(pcoinsTip, mempool);
beeb5761
PW
667 if (!view.GetCoins(hash, coins))
668 return Value::null;
669 mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool
670 } else {
671 if (!pcoinsTip->GetCoins(hash, coins))
672 return Value::null;
673 }
674 if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
675 return Value::null;
676
145d5be8 677 BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
7a77c443 678 CBlockIndex *pindex = it->second;
84674082 679 ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
beeb5761
PW
680 if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
681 ret.push_back(Pair("confirmations", 0));
cad0d1ca 682 else ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1));
4e68391a 683 ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue)));
798f28c7 684 uint64_t interest; int32_t txheight; uint32_t locktime;
685 if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue)) != 0 )
0fec0cc4 686 ret.push_back(Pair("interest", ValueFromAmount(interest)));
beeb5761 687 Object o;
be066fad 688 ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true);
beeb5761
PW
689 ret.push_back(Pair("scriptPubKey", o));
690 ret.push_back(Pair("version", coins.nVersion));
691 ret.push_back(Pair("coinbase", coins.fCoinBase));
692
693 return ret;
694}
c625ae04 695
f5906533
JG
696Value verifychain(const Array& params, bool fHelp)
697{
698 if (fHelp || params.size() > 2)
699 throw runtime_error(
a6099ef3 700 "verifychain ( checklevel numblocks )\n"
701 "\nVerifies blockchain database.\n"
702 "\nArguments:\n"
6943cb9b
PK
703 "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
704 "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
a6099ef3 705 "\nResult:\n"
706 "true|false (boolean) Verified or not\n"
707 "\nExamples:\n"
708 + HelpExampleCli("verifychain", "")
709 + HelpExampleRpc("verifychain", "")
710 );
f5906533 711
4401b2d7
EL
712 LOCK(cs_main);
713
f5906533
JG
714 int nCheckLevel = GetArg("-checklevel", 3);
715 int nCheckDepth = GetArg("-checkblocks", 288);
716 if (params.size() > 0)
717 nCheckLevel = params[0].get_int();
718 if (params.size() > 1)
719 nCheckDepth = params[1].get_int();
720
2e280311 721 return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth);
f5906533 722}
c625ae04 723
ba1da90b
WL
724/** Implementation of IsSuperMajority with better feedback */
725Object SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
726{
727 int nFound = 0;
728 CBlockIndex* pstart = pindex;
729 for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
730 {
731 if (pstart->nVersion >= minVersion)
732 ++nFound;
733 pstart = pstart->pprev;
734 }
735
736 Object rv;
737 rv.push_back(Pair("status", nFound >= nRequired));
738 rv.push_back(Pair("found", nFound));
739 rv.push_back(Pair("required", nRequired));
740 rv.push_back(Pair("window", consensusParams.nMajorityWindow));
741 return rv;
742}
743
744Object SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
745{
746 Object rv;
747 rv.push_back(Pair("id", name));
748 rv.push_back(Pair("version", version));
749 rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
750 rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
751 return rv;
752}
753
d387b8ec
WL
754Value getblockchaininfo(const Array& params, bool fHelp)
755{
756 if (fHelp || params.size() != 0)
757 throw runtime_error(
758 "getblockchaininfo\n"
759 "Returns an object containing various state info regarding block chain processing.\n"
760 "\nResult:\n"
761 "{\n"
f6984e81 762 " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
d387b8ec 763 " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
ad6e6017 764 " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
d387b8ec
WL
765 " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
766 " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
767 " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n"
768 " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
ba1da90b
WL
769 " \"softforks\": [ (array) status of softforks in progress\n"
770 " {\n"
771 " \"id\": \"xxxx\", (string) name of softfork\n"
772 " \"version\": xx, (numeric) block version\n"
773 " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n"
774 " \"status\": xx, (boolean) true if threshold reached\n"
775 " \"found\": xx, (numeric) number of blocks with the new version found\n"
776 " \"required\": xx, (numeric) number of blocks required to trigger\n"
777 " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n"
778 " },\n"
779 " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
780 " }, ...\n"
781 " ]\n"
d387b8ec
WL
782 "}\n"
783 "\nExamples:\n"
784 + HelpExampleCli("getblockchaininfo", "")
785 + HelpExampleRpc("getblockchaininfo", "")
786 );
787
4401b2d7
EL
788 LOCK(cs_main);
789
d387b8ec 790 Object obj;
f5ae6c98
PK
791 obj.push_back(Pair("chain", Params().NetworkIDString()));
792 obj.push_back(Pair("blocks", (int)chainActive.Height()));
ad6e6017 793 obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
f5ae6c98 794 obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
695a7a88 795 obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
11982d36 796 obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip())));
f5ae6c98 797 obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
1b2e5555 798 obj.push_back(Pair("pruned", fPruneMode));
ba1da90b
WL
799
800 const Consensus::Params& consensusParams = Params().GetConsensus();
801 CBlockIndex* tip = chainActive.Tip();
802 Array softforks;
803 softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
804 softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
6af25b0f 805 softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
ba1da90b
WL
806 obj.push_back(Pair("softforks", softforks));
807
1b2e5555
JS
808 if (fPruneMode)
809 {
810 CBlockIndex *block = chainActive.Tip();
811 while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA))
812 block = block->pprev;
813
814 obj.push_back(Pair("pruneheight", block->nHeight));
815 }
d387b8ec
WL
816 return obj;
817}
b33bd7a3 818
72fb3d29 819/** Comparison function for sorting the getchaintips heads. */
b33bd7a3
DK
820struct CompareBlocksByHeight
821{
822 bool operator()(const CBlockIndex* a, const CBlockIndex* b) const
823 {
824 /* Make sure that unequal blocks with the same height do not compare
771d5002 825 equal. Use the pointers themselves to make a distinction. */
b33bd7a3
DK
826
827 if (a->nHeight != b->nHeight)
828 return (a->nHeight > b->nHeight);
829
830 return a < b;
831 }
832};
833
834Value getchaintips(const Array& params, bool fHelp)
835{
836 if (fHelp || params.size() != 0)
837 throw runtime_error(
838 "getchaintips\n"
839 "Return information about all known tips in the block tree,"
840 " including the main chain as well as orphaned branches.\n"
841 "\nResult:\n"
842 "[\n"
843 " {\n"
844 " \"height\": xxxx, (numeric) height of the chain tip\n"
845 " \"hash\": \"xxxx\", (string) block hash of the tip\n"
846 " \"branchlen\": 0 (numeric) zero for main chain\n"
1b91be49 847 " \"status\": \"active\" (string) \"active\" for the main chain\n"
b33bd7a3
DK
848 " },\n"
849 " {\n"
850 " \"height\": xxxx,\n"
851 " \"hash\": \"xxxx\",\n"
852 " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n"
1b91be49 853 " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n"
b33bd7a3
DK
854 " }\n"
855 "]\n"
32b93a1b
PW
856 "Possible values for status:\n"
857 "1. \"invalid\" This branch contains at least one invalid block\n"
858 "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n"
859 "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n"
860 "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n"
861 "5. \"active\" This is the tip of the active main chain, which is certainly valid\n"
b33bd7a3
DK
862 "\nExamples:\n"
863 + HelpExampleCli("getchaintips", "")
864 + HelpExampleRpc("getchaintips", "")
865 );
866
4401b2d7
EL
867 LOCK(cs_main);
868
b33bd7a3
DK
869 /* Build up a list of chain tips. We start with the list of all
870 known blocks, and successively remove blocks that appear as pprev
871 of another block. */
872 std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
873 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
874 setTips.insert(item.second);
875 BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
876 {
877 const CBlockIndex* pprev = item.second->pprev;
878 if (pprev)
879 setTips.erase(pprev);
880 }
881
1b91be49
PW
882 // Always report the currently active tip.
883 setTips.insert(chainActive.Tip());
884
b33bd7a3
DK
885 /* Construct the output array. */
886 Array res;
887 BOOST_FOREACH(const CBlockIndex* block, setTips)
888 {
889 Object obj;
890 obj.push_back(Pair("height", block->nHeight));
891 obj.push_back(Pair("hash", block->phashBlock->GetHex()));
892
893 const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
894 obj.push_back(Pair("branchlen", branchLen));
895
1b91be49
PW
896 string status;
897 if (chainActive.Contains(block)) {
898 // This block is part of the currently active chain.
899 status = "active";
900 } else if (block->nStatus & BLOCK_FAILED_MASK) {
901 // This block or one of its ancestors is invalid.
902 status = "invalid";
903 } else if (block->nChainTx == 0) {
904 // This block cannot be connected because full block data for it or one of its parents is missing.
905 status = "headers-only";
906 } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {
907 // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
908 status = "valid-fork";
909 } else if (block->IsValid(BLOCK_VALID_TREE)) {
910 // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
911 status = "valid-headers";
912 } else {
913 // No clue.
914 status = "unknown";
915 }
916 obj.push_back(Pair("status", status));
917
b33bd7a3
DK
918 res.push_back(obj);
919 }
920
921 return res;
922}
6f2c26a4
JG
923
924Value getmempoolinfo(const Array& params, bool fHelp)
925{
926 if (fHelp || params.size() != 0)
927 throw runtime_error(
928 "getmempoolinfo\n"
929 "\nReturns details on the active state of the TX memory pool.\n"
930 "\nResult:\n"
931 "{\n"
932 " \"size\": xxxxx (numeric) Current tx count\n"
933 " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n"
934 "}\n"
935 "\nExamples:\n"
936 + HelpExampleCli("getmempoolinfo", "")
937 + HelpExampleRpc("getmempoolinfo", "")
938 );
939
940 Object ret;
941 ret.push_back(Pair("size", (int64_t) mempool.size()));
942 ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
943
944 return ret;
945}
946
9b0a8d31
PW
947Value invalidateblock(const Array& params, bool fHelp)
948{
949 if (fHelp || params.size() != 1)
950 throw runtime_error(
951 "invalidateblock \"hash\"\n"
952 "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
953 "\nArguments:\n"
954 "1. hash (string, required) the hash of the block to mark as invalid\n"
955 "\nResult:\n"
956 "\nExamples:\n"
957 + HelpExampleCli("invalidateblock", "\"blockhash\"")
958 + HelpExampleRpc("invalidateblock", "\"blockhash\"")
959 );
960
961 std::string strHash = params[0].get_str();
34cdc411 962 uint256 hash(uint256S(strHash));
9b0a8d31
PW
963 CValidationState state;
964
965 {
966 LOCK(cs_main);
967 if (mapBlockIndex.count(hash) == 0)
968 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
969
970 CBlockIndex* pblockindex = mapBlockIndex[hash];
971 InvalidateBlock(state, pblockindex);
972 }
973
974 if (state.IsValid()) {
975 ActivateBestChain(state);
976 }
977
978 if (!state.IsValid()) {
979 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
980 }
981
982 return Value::null;
983}
984
985Value reconsiderblock(const Array& params, bool fHelp)
986{
987 if (fHelp || params.size() != 1)
988 throw runtime_error(
989 "reconsiderblock \"hash\"\n"
990 "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
991 "This can be used to undo the effects of invalidateblock.\n"
992 "\nArguments:\n"
993 "1. hash (string, required) the hash of the block to reconsider\n"
994 "\nResult:\n"
995 "\nExamples:\n"
996 + HelpExampleCli("reconsiderblock", "\"blockhash\"")
997 + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
998 );
999
1000 std::string strHash = params[0].get_str();
34cdc411 1001 uint256 hash(uint256S(strHash));
9b0a8d31
PW
1002 CValidationState state;
1003
1004 {
1005 LOCK(cs_main);
1006 if (mapBlockIndex.count(hash) == 0)
1007 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
1008
1009 CBlockIndex* pblockindex = mapBlockIndex[hash];
1010 ReconsiderBlock(state, pblockindex);
1011 }
1012
1013 if (state.IsValid()) {
1014 ActivateBestChain(state);
1015 }
1016
1017 if (!state.IsValid()) {
1018 throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
1019 }
1020
1021 return Value::null;
1022}
This page took 0.411793 seconds and 4 git commands to generate.