~ubuntu-branches/debian/stretch/bitcoin/stretch

« back to all changes in this revision

Viewing changes to src/rpcblockchain.cpp

  • Committer: Package Import Robot
  • Author(s): Anthony Towns
  • Date: 2016-10-21 17:13:13 UTC
  • mfrom: (1.3.2)
  • Revision ID: package-import@ubuntu.com-20161021171313-7eu2ltpbk0xag3q1
Tags: 0.13.0-0.1
* Non-maintainer upload.
* New upstream release.
* Allow compilation with gcc/g++ 6. (Closes: Bug#835963)
* Additional fixes for openssl 1.1 compatibility. (See Bug#828248)
* Check if -latomic is needed (it is on mips*).
* Remove reproducible build patch, since leveldb build system is
  no longer used in 0.13. (See Bug#791834)
* Update description since the blockchain is much more than "several GB"
  now. (Closes: Bug#835809)

Show diffs side-by-side

added added

removed removed

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