2012-08-21 17:03:38 +02:00
// Copyright (c) 2010 Satoshi Nakamoto
2016-12-31 19:01:21 +01:00
// Copyright (c) 2009-2016 The Bitcoin Core developers
2014-11-20 03:19:29 +01:00
// Distributed under the MIT software license, see the accompanying
2012-08-21 17:03:38 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-03-27 12:14:43 +02:00
# include "rpc/blockchain.h"
2015-08-01 21:15:23 +02:00
# include "amount.h"
2015-07-05 14:17:46 +02:00
# include "chain.h"
# include "chainparams.h"
2014-05-10 14:54:20 +02:00
# include "checkpoints.h"
2015-07-05 14:17:46 +02:00
# include "coins.h"
2015-01-24 15:57:12 +01:00
# include "consensus/validation.h"
2016-12-02 01:06:41 +01:00
# include "validation.h"
2016-09-22 02:51:00 +02:00
# include "core_io.h"
2016-03-31 23:30:17 +02:00
# include "policy/feerate.h"
2015-11-16 21:21:51 +01:00
# include "policy/policy.h"
2015-01-24 15:57:12 +01:00
# include "primitives/transaction.h"
2016-01-15 01:55:17 +01:00
# include "rpc/server.h"
2015-07-05 14:17:46 +02:00
# include "streams.h"
2013-04-13 07:13:08 +02:00
# include "sync.h"
2017-06-07 19:00:11 +02:00
# include "txdb.h"
2015-07-05 14:17:46 +02:00
# include "txmempool.h"
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
# include "util.h"
2015-07-05 14:17:46 +02:00
# include "utilstrencodings.h"
2016-03-28 18:18:30 +02:00
# include "hash.h"
2013-04-13 07:13:08 +02:00
# include <stdint.h>
2015-09-04 16:11:34 +02:00
# include <univalue.h>
2012-08-21 17:03:38 +02:00
2016-03-28 18:18:30 +02:00
# include <boost/thread/thread.hpp> // boost::thread::interrupt
2016-09-02 03:55:21 +02:00
# include <mutex>
# include <condition_variable>
2012-08-21 17:03:38 +02:00
2016-09-02 03:55:21 +02:00
struct CUpdatedBlock
{
uint256 hash ;
int height ;
} ;
static std : : mutex cs_blockchange ;
static std : : condition_variable cond_blockchange ;
static CUpdatedBlock latestblock ;
2015-05-18 14:02:18 +02:00
extern void TxToJSON ( const CTransaction & tx , const uint256 hashBlock , UniValue & entry ) ;
2013-01-04 22:51:00 +01:00
2012-08-21 17:03:38 +02:00
double GetDifficulty ( const CBlockIndex * blockindex )
{
2017-08-07 07:36:37 +02:00
if ( blockindex = = nullptr )
2012-08-21 17:03:38 +02:00
{
2017-08-07 07:36:37 +02:00
if ( chainActive . Tip ( ) = = nullptr )
2012-08-21 17:03:38 +02:00
return 1.0 ;
else
2013-10-10 23:07:44 +02:00
blockindex = chainActive . Tip ( ) ;
2012-08-21 17:03:38 +02:00
}
int nShift = ( blockindex - > nBits > > 24 ) & 0xff ;
double dDiff =
( double ) 0x0000ffff / ( double ) ( blockindex - > nBits & 0x00ffffff ) ;
while ( nShift < 29 )
{
dDiff * = 256.0 ;
nShift + + ;
}
while ( nShift > 29 )
{
dDiff / = 256.0 ;
nShift - - ;
}
return dDiff ;
}
2015-06-05 21:37:17 +02:00
UniValue blockheaderToJSON ( const CBlockIndex * blockindex )
{
UniValue result ( UniValue : : VOBJ ) ;
result . push_back ( Pair ( " hash " , blockindex - > GetBlockHash ( ) . GetHex ( ) ) ) ;
int confirmations = - 1 ;
// Only report confirmations if the block is on the main chain
if ( chainActive . Contains ( blockindex ) )
confirmations = chainActive . Height ( ) - blockindex - > nHeight + 1 ;
result . push_back ( Pair ( " confirmations " , confirmations ) ) ;
result . push_back ( Pair ( " height " , blockindex - > nHeight ) ) ;
result . push_back ( Pair ( " version " , blockindex - > nVersion ) ) ;
2016-04-05 00:21:00 +02:00
result . push_back ( Pair ( " versionHex " , strprintf ( " %08x " , blockindex - > nVersion ) ) ) ;
2015-06-05 21:37:17 +02:00
result . push_back ( Pair ( " merkleroot " , blockindex - > hashMerkleRoot . GetHex ( ) ) ) ;
result . push_back ( Pair ( " time " , ( int64_t ) blockindex - > nTime ) ) ;
2015-11-13 22:57:10 +01:00
result . push_back ( Pair ( " mediantime " , ( int64_t ) blockindex - > GetMedianTimePast ( ) ) ) ;
2015-06-05 21:37:17 +02:00
result . push_back ( Pair ( " nonce " , ( uint64_t ) blockindex - > nNonce ) ) ;
result . push_back ( Pair ( " bits " , strprintf ( " %08x " , blockindex - > nBits ) ) ) ;
result . push_back ( Pair ( " difficulty " , GetDifficulty ( blockindex ) ) ) ;
result . push_back ( Pair ( " chainwork " , blockindex - > nChainWork . GetHex ( ) ) ) ;
if ( blockindex - > pprev )
result . push_back ( Pair ( " previousblockhash " , blockindex - > pprev - > GetBlockHash ( ) . GetHex ( ) ) ) ;
CBlockIndex * pnext = chainActive . Next ( blockindex ) ;
if ( pnext )
result . push_back ( Pair ( " nextblockhash " , pnext - > GetBlockHash ( ) . GetHex ( ) ) ) ;
return result ;
}
2017-03-27 16:12:02 +02:00
UniValue blockToJSON ( const CBlock & block , const CBlockIndex * blockindex , bool txDetails )
2012-08-21 17:03:38 +02:00
{
2015-05-10 14:48:35 +02:00
UniValue result ( UniValue : : VOBJ ) ;
2016-03-12 15:11:59 +01:00
result . push_back ( Pair ( " hash " , blockindex - > GetBlockHash ( ) . GetHex ( ) ) ) ;
2014-08-28 17:14:22 +02:00
int confirmations = - 1 ;
// Only report confirmations if the block is on the main chain
if ( chainActive . Contains ( blockindex ) )
confirmations = chainActive . Height ( ) - blockindex - > nHeight + 1 ;
result . push_back ( Pair ( " confirmations " , confirmations ) ) ;
2016-01-22 18:46:11 +01:00
result . push_back ( Pair ( " strippedsize " , ( int ) : : GetSerializeSize ( block , SER_NETWORK , PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS ) ) ) ;
2012-08-21 17:03:38 +02:00
result . push_back ( Pair ( " size " , ( int ) : : GetSerializeSize ( block , SER_NETWORK , PROTOCOL_VERSION ) ) ) ;
2016-07-18 19:28:26 +02:00
result . push_back ( Pair ( " weight " , ( int ) : : GetBlockWeight ( block ) ) ) ;
2012-08-21 17:03:38 +02:00
result . push_back ( Pair ( " height " , blockindex - > nHeight ) ) ;
result . push_back ( Pair ( " version " , block . nVersion ) ) ;
2016-04-05 00:21:00 +02:00
result . push_back ( Pair ( " versionHex " , strprintf ( " %08x " , block . nVersion ) ) ) ;
2012-08-21 17:03:38 +02:00
result . push_back ( Pair ( " merkleroot " , block . hashMerkleRoot . GetHex ( ) ) ) ;
2015-05-10 14:48:35 +02:00
UniValue txs ( UniValue : : VARR ) ;
2016-11-11 02:26:00 +01:00
for ( const auto & tx : block . vtx )
2014-11-28 20:32:52 +01:00
{
if ( txDetails )
{
2015-05-10 14:48:35 +02:00
UniValue objTx ( UniValue : : VOBJ ) ;
2017-08-11 21:21:14 +02:00
TxToUniv ( * tx , uint256 ( ) , objTx , true , RPCSerializationFlags ( ) ) ;
2014-11-28 20:32:52 +01:00
txs . push_back ( objTx ) ;
}
else
2016-11-11 02:26:00 +01:00
txs . push_back ( tx - > GetHash ( ) . GetHex ( ) ) ;
2014-11-28 20:32:52 +01:00
}
2012-08-21 17:03:38 +02:00
result . push_back ( Pair ( " tx " , txs ) ) ;
2014-05-06 14:58:43 +02:00
result . push_back ( Pair ( " time " , block . GetBlockTime ( ) ) ) ;
2015-11-13 22:57:10 +01:00
result . push_back ( Pair ( " mediantime " , ( int64_t ) blockindex - > GetMedianTimePast ( ) ) ) ;
2014-05-05 20:08:13 +02:00
result . push_back ( Pair ( " nonce " , ( uint64_t ) block . nNonce ) ) ;
2014-06-27 13:28:08 +02:00
result . push_back ( Pair ( " bits " , strprintf ( " %08x " , block . nBits ) ) ) ;
2012-08-21 17:03:38 +02:00
result . push_back ( Pair ( " difficulty " , GetDifficulty ( blockindex ) ) ) ;
2013-07-24 07:58:23 +02:00
result . push_back ( Pair ( " chainwork " , blockindex - > nChainWork . GetHex ( ) ) ) ;
2012-08-21 17:03:38 +02:00
if ( blockindex - > pprev )
result . push_back ( Pair ( " previousblockhash " , blockindex - > pprev - > GetBlockHash ( ) . GetHex ( ) ) ) ;
2013-10-10 23:07:44 +02:00
CBlockIndex * pnext = chainActive . Next ( blockindex ) ;
2013-05-12 15:50:22 +02:00
if ( pnext )
result . push_back ( Pair ( " nextblockhash " , pnext - > GetBlockHash ( ) . GetHex ( ) ) ) ;
2012-08-21 17:03:38 +02:00
return result ;
}
2016-09-22 09:46:41 +02:00
UniValue getblockcount ( const JSONRPCRequest & request )
2012-08-21 17:03:38 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 0 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2012-08-21 17:03:38 +02:00
" getblockcount \n "
2016-10-20 12:39:48 +02:00
" \n Returns the number of blocks in the longest blockchain. \n "
2013-10-29 12:29:44 +01:00
" \n Result: \n "
" n (numeric) The current block count \n "
" \n Examples: \n "
+ HelpExampleCli ( " getblockcount " , " " )
+ HelpExampleRpc ( " getblockcount " , " " )
) ;
2012-08-21 17:03:38 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2013-10-10 23:07:44 +02:00
return chainActive . Height ( ) ;
2012-08-21 17:03:38 +02:00
}
2016-09-22 09:46:41 +02:00
UniValue getbestblockhash ( const JSONRPCRequest & request )
2013-07-03 17:02:29 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 0 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2013-07-03 17:02:29 +02:00
" getbestblockhash \n "
2016-10-20 12:39:48 +02:00
" \n Returns the hash of the best (tip) block in the longest blockchain. \n "
2016-12-22 05:26:03 +01:00
" \n Result: \n "
2013-10-29 12:29:44 +01:00
" \" hex \" (string) the block hash hex encoded \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2013-10-29 12:29:44 +01:00
+ HelpExampleCli ( " getbestblockhash " , " " )
+ HelpExampleRpc ( " getbestblockhash " , " " )
) ;
2013-07-03 17:02:29 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2013-10-10 23:07:44 +02:00
return chainActive . Tip ( ) - > GetBlockHash ( ) . GetHex ( ) ;
2013-07-03 17:02:29 +02:00
}
2012-08-21 17:03:38 +02:00
2016-09-02 03:55:21 +02:00
void RPCNotifyBlockChange ( bool ibd , const CBlockIndex * pindex )
{
if ( pindex ) {
std : : lock_guard < std : : mutex > lock ( cs_blockchange ) ;
latestblock . hash = pindex - > GetBlockHash ( ) ;
latestblock . height = pindex - > nHeight ;
}
2017-01-14 02:06:50 +01:00
cond_blockchange . notify_all ( ) ;
2016-09-02 03:55:21 +02:00
}
2016-09-22 09:46:41 +02:00
UniValue waitfornewblock ( const JSONRPCRequest & request )
2016-09-02 03:55:21 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) > 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-11-12 13:27:36 +01:00
" waitfornewblock (timeout) \n "
2016-09-02 03:55:21 +02:00
" \n Waits for a specific new block and returns useful info about it. \n "
" \n Returns the current block on timeout or exit. \n "
" \n Arguments: \n "
2016-11-12 13:27:36 +01:00
" 1. timeout (int, optional, default=0) Time in milliseconds to wait for a response. 0 indicates no timeout. \n "
" \n Result: \n "
2016-09-02 03:55:21 +02:00
" { (json object) \n "
" \" hash \" : { (string) The blockhash \n "
" \" height \" : { (int) Block height \n "
" } \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2016-09-02 03:55:21 +02:00
+ HelpExampleCli ( " waitfornewblock " , " 1000 " )
+ HelpExampleRpc ( " waitfornewblock " , " 1000 " )
) ;
int timeout = 0 ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 0 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
timeout = request . params [ 0 ] . get_int ( ) ;
2016-09-02 03:55:21 +02:00
CUpdatedBlock block ;
{
std : : unique_lock < std : : mutex > lock ( cs_blockchange ) ;
block = latestblock ;
if ( timeout )
cond_blockchange . wait_for ( lock , std : : chrono : : milliseconds ( timeout ) , [ & block ] { return latestblock . height ! = block . height | | latestblock . hash ! = block . hash | | ! IsRPCRunning ( ) ; } ) ;
else
cond_blockchange . wait ( lock , [ & block ] { return latestblock . height ! = block . height | | latestblock . hash ! = block . hash | | ! IsRPCRunning ( ) ; } ) ;
block = latestblock ;
}
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " hash " , block . hash . GetHex ( ) ) ) ;
ret . push_back ( Pair ( " height " , block . height ) ) ;
return ret ;
}
2016-09-22 09:46:41 +02:00
UniValue waitforblock ( const JSONRPCRequest & request )
2016-09-02 03:55:21 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-11-12 13:27:36 +01:00
" waitforblock <blockhash> (timeout) \n "
2016-09-02 03:55:21 +02:00
" \n Waits for a specific new block and returns useful info about it. \n "
" \n Returns the current block on timeout or exit. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" blockhash \" (required, string) Block hash to wait for. \n "
" 2. timeout (int, optional, default=0) Time in milliseconds to wait for a response. 0 indicates no timeout. \n "
2016-11-12 13:27:36 +01:00
" \n Result: \n "
2016-09-02 03:55:21 +02:00
" { (json object) \n "
" \" hash \" : { (string) The blockhash \n "
" \" height \" : { (int) Block height \n "
" } \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2016-09-02 03:55:21 +02:00
+ HelpExampleCli ( " waitforblock " , " \" 0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862 \" , 1000 " )
+ HelpExampleRpc ( " waitforblock " , " \" 0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862 \" , 1000 " )
) ;
int timeout = 0 ;
2016-09-22 09:46:41 +02:00
uint256 hash = uint256S ( request . params [ 0 ] . get_str ( ) ) ;
2016-09-02 03:55:21 +02:00
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
timeout = request . params [ 1 ] . get_int ( ) ;
2016-09-02 03:55:21 +02:00
CUpdatedBlock block ;
{
std : : unique_lock < std : : mutex > lock ( cs_blockchange ) ;
if ( timeout )
cond_blockchange . wait_for ( lock , std : : chrono : : milliseconds ( timeout ) , [ & hash ] { return latestblock . hash = = hash | | ! IsRPCRunning ( ) ; } ) ;
else
cond_blockchange . wait ( lock , [ & hash ] { return latestblock . hash = = hash | | ! IsRPCRunning ( ) ; } ) ;
block = latestblock ;
}
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " hash " , block . hash . GetHex ( ) ) ) ;
ret . push_back ( Pair ( " height " , block . height ) ) ;
return ret ;
}
2016-09-22 09:46:41 +02:00
UniValue waitforblockheight ( const JSONRPCRequest & request )
2016-09-02 03:55:21 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-12-09 18:06:42 +01:00
" waitforblockheight <height> (timeout) \n "
2016-09-02 03:55:21 +02:00
" \n Waits for (at least) block height and returns the height and hash \n "
2016-11-12 13:27:36 +01:00
" of the current tip. \n "
2016-09-02 03:55:21 +02:00
" \n Returns the current block on timeout or exit. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. height (required, int) Block height to wait for (int) \n "
2016-11-12 13:27:36 +01:00
" 2. timeout (int, optional, default=0) Time in milliseconds to wait for a response. 0 indicates no timeout. \n "
" \n Result: \n "
2016-09-02 03:55:21 +02:00
" { (json object) \n "
" \" hash \" : { (string) The blockhash \n "
" \" height \" : { (int) Block height \n "
" } \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2016-09-02 03:55:21 +02:00
+ HelpExampleCli ( " waitforblockheight " , " \" 100 \" , 1000 " )
+ HelpExampleRpc ( " waitforblockheight " , " \" 100 \" , 1000 " )
) ;
int timeout = 0 ;
2016-09-22 09:46:41 +02:00
int height = request . params [ 0 ] . get_int ( ) ;
2016-09-02 03:55:21 +02:00
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
timeout = request . params [ 1 ] . get_int ( ) ;
2016-09-02 03:55:21 +02:00
CUpdatedBlock block ;
{
std : : unique_lock < std : : mutex > lock ( cs_blockchange ) ;
if ( timeout )
cond_blockchange . wait_for ( lock , std : : chrono : : milliseconds ( timeout ) , [ & height ] { return latestblock . height > = height | | ! IsRPCRunning ( ) ; } ) ;
else
cond_blockchange . wait ( lock , [ & height ] { return latestblock . height > = height | | ! IsRPCRunning ( ) ; } ) ;
block = latestblock ;
}
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " hash " , block . hash . GetHex ( ) ) ) ;
ret . push_back ( Pair ( " height " , block . height ) ) ;
return ret ;
}
2016-09-22 09:46:41 +02:00
UniValue getdifficulty ( const JSONRPCRequest & request )
2012-08-21 17:03:38 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 0 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2012-08-21 17:03:38 +02:00
" getdifficulty \n "
2013-10-29 12:29:44 +01:00
" \n Returns the proof-of-work difficulty as a multiple of the minimum difficulty. \n "
" \n Result: \n "
" n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty. \n "
" \n Examples: \n "
+ HelpExampleCli ( " getdifficulty " , " " )
+ HelpExampleRpc ( " getdifficulty " , " " )
) ;
2012-08-21 17:03:38 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2012-08-21 17:03:38 +02:00
return GetDifficulty ( ) ;
}
2016-01-04 19:43:17 +01:00
std : : string EntryDescriptionString ( )
{
2016-09-15 16:46:01 +02:00
return " \" size \" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted. \n "
2016-01-04 19:43:17 +01:00
" \" fee \" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " \n "
" \" modifiedfee \" : n, (numeric) transaction fee with fee deltas used for mining priority \n "
" \" time \" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT \n "
" \" height \" : n, (numeric) block height when transaction entered pool \n "
" \" descendantcount \" : n, (numeric) number of in-mempool descendant transactions (including this one) \n "
2016-09-15 16:46:01 +02:00
" \" descendantsize \" : n, (numeric) virtual transaction size of in-mempool descendants (including this one) \n "
2016-01-04 19:43:17 +01:00
" \" descendantfees \" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) \n "
2016-05-17 14:42:35 +02:00
" \" ancestorcount \" : n, (numeric) number of in-mempool ancestor transactions (including this one) \n "
2016-09-15 16:46:01 +02:00
" \" ancestorsize \" : n, (numeric) virtual transaction size of in-mempool ancestors (including this one) \n "
2016-05-17 14:42:35 +02:00
" \" ancestorfees \" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) \n "
2016-01-04 19:43:17 +01:00
" \" depends \" : [ (array) unconfirmed transactions used as inputs for this transaction \n "
" \" transactionid \" , (string) parent transaction id \n "
" ... ] \n " ;
}
void entryToJSON ( UniValue & info , const CTxMemPoolEntry & e )
{
AssertLockHeld ( mempool . cs ) ;
info . push_back ( Pair ( " size " , ( int ) e . GetTxSize ( ) ) ) ;
info . push_back ( Pair ( " fee " , ValueFromAmount ( e . GetFee ( ) ) ) ) ;
info . push_back ( Pair ( " modifiedfee " , ValueFromAmount ( e . GetModifiedFee ( ) ) ) ) ;
info . push_back ( Pair ( " time " , e . GetTime ( ) ) ) ;
info . push_back ( Pair ( " height " , ( int ) e . GetHeight ( ) ) ) ;
info . push_back ( Pair ( " descendantcount " , e . GetCountWithDescendants ( ) ) ) ;
info . push_back ( Pair ( " descendantsize " , e . GetSizeWithDescendants ( ) ) ) ;
info . push_back ( Pair ( " descendantfees " , e . GetModFeesWithDescendants ( ) ) ) ;
2016-05-17 14:42:35 +02:00
info . push_back ( Pair ( " ancestorcount " , e . GetCountWithAncestors ( ) ) ) ;
info . push_back ( Pair ( " ancestorsize " , e . GetSizeWithAncestors ( ) ) ) ;
info . push_back ( Pair ( " ancestorfees " , e . GetModFeesWithAncestors ( ) ) ) ;
2016-01-04 19:43:17 +01:00
const CTransaction & tx = e . GetTx ( ) ;
2017-01-04 05:22:19 +01:00
std : : set < std : : string > setDepends ;
2017-06-02 03:18:57 +02:00
for ( const CTxIn & txin : tx . vin )
2016-01-04 19:43:17 +01:00
{
if ( mempool . exists ( txin . prevout . hash ) )
setDepends . insert ( txin . prevout . hash . ToString ( ) ) ;
}
UniValue depends ( UniValue : : VARR ) ;
2017-06-02 03:18:57 +02:00
for ( const std : : string & dep : setDepends )
2016-01-04 19:43:17 +01:00
{
depends . push_back ( dep ) ;
}
info . push_back ( Pair ( " depends " , depends ) ) ;
}
2017-03-27 16:12:02 +02:00
UniValue mempoolToJSON ( bool fVerbose )
2012-08-21 17:03:38 +02:00
{
2013-11-11 08:35:14 +01:00
if ( fVerbose )
{
LOCK ( mempool . cs ) ;
2015-05-10 14:48:35 +02:00
UniValue o ( UniValue : : VOBJ ) ;
2017-06-02 03:18:57 +02:00
for ( const CTxMemPoolEntry & e : mempool . mapTx )
2013-11-11 08:35:14 +01:00
{
2015-06-24 10:32:20 +02:00
const uint256 & hash = e . GetTx ( ) . GetHash ( ) ;
2015-05-10 14:48:35 +02:00
UniValue info ( UniValue : : VOBJ ) ;
2016-01-04 19:43:17 +01:00
entryToJSON ( info , e ) ;
2013-11-11 08:35:14 +01:00
o . push_back ( Pair ( hash . ToString ( ) , info ) ) ;
}
return o ;
}
else
{
2017-01-04 05:22:19 +01:00
std : : vector < uint256 > vtxid ;
2013-11-11 08:35:14 +01:00
mempool . queryHashes ( vtxid ) ;
2012-08-21 17:03:38 +02:00
2015-05-10 14:48:35 +02:00
UniValue a ( UniValue : : VARR ) ;
2017-06-02 03:18:57 +02:00
for ( const uint256 & hash : vtxid )
2013-11-11 08:35:14 +01:00
a . push_back ( hash . ToString ( ) ) ;
return a ;
}
2012-08-21 17:03:38 +02:00
}
2016-09-22 09:46:41 +02:00
UniValue getrawmempool ( const JSONRPCRequest & request )
2015-08-06 19:38:19 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) > 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2015-08-06 19:38:19 +02:00
" getrawmempool ( verbose ) \n "
" \n Returns all transaction ids in memory pool as a json array of string transaction ids. \n "
2017-05-06 05:51:01 +02:00
" \n Hint: use getmempoolentry to fetch a specific transaction from the mempool. \n "
2015-08-06 19:38:19 +02:00
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids \n "
2015-08-06 19:38:19 +02:00
" \n Result: (for verbose = false): \n "
" [ (json array of string) \n "
" \" transactionid \" (string) The transaction id \n "
" ,... \n "
" ] \n "
" \n Result: (for verbose = true): \n "
" { (json object) \n "
" \" transactionid \" : { (json object) \n "
2016-01-04 19:43:17 +01:00
+ EntryDescriptionString ( )
+ " }, ... \n "
2015-08-06 19:38:19 +02:00
" } \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2015-08-06 19:38:19 +02:00
+ HelpExampleCli ( " getrawmempool " , " true " )
+ HelpExampleRpc ( " getrawmempool " , " true " )
) ;
bool fVerbose = false ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 0 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
fVerbose = request . params [ 0 ] . get_bool ( ) ;
2015-08-06 19:38:19 +02:00
return mempoolToJSON ( fVerbose ) ;
}
2016-09-22 09:46:41 +02:00
UniValue getmempoolancestors ( const JSONRPCRequest & request )
2016-01-04 19:58:59 +01:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 ) {
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-01-04 19:58:59 +01:00
" getmempoolancestors txid (verbose) \n "
" \n If txid is in the mempool, returns all in-mempool ancestors. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" txid \" (string, required) The transaction id (must be in mempool) \n "
" 2. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids \n "
2016-01-04 19:58:59 +01:00
" \n Result (for verbose=false): \n "
2016-01-04 20:48:22 +01:00
" [ (json array of strings) \n "
2016-01-04 19:58:59 +01:00
" \" transactionid \" (string) The transaction id of an in-mempool ancestor transaction \n "
" ,... \n "
" ] \n "
" \n Result (for verbose=true): \n "
" { (json object) \n "
" \" transactionid \" : { (json object) \n "
+ EntryDescriptionString ( )
+ " }, ... \n "
" } \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2016-01-04 19:58:59 +01:00
+ HelpExampleCli ( " getmempoolancestors " , " \" mytxid \" " )
+ HelpExampleRpc ( " getmempoolancestors " , " \" mytxid \" " )
) ;
}
bool fVerbose = false ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
fVerbose = request . params [ 1 ] . get_bool ( ) ;
2016-01-04 19:58:59 +01:00
2016-09-22 09:46:41 +02:00
uint256 hash = ParseHashV ( request . params [ 0 ] , " parameter 1 " ) ;
2016-01-04 19:58:59 +01:00
LOCK ( mempool . cs ) ;
CTxMemPool : : txiter it = mempool . mapTx . find ( hash ) ;
if ( it = = mempool . mapTx . end ( ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Transaction not in mempool " ) ;
}
CTxMemPool : : setEntries setAncestors ;
uint64_t noLimit = std : : numeric_limits < uint64_t > : : max ( ) ;
std : : string dummy ;
mempool . CalculateMemPoolAncestors ( * it , setAncestors , noLimit , noLimit , noLimit , noLimit , dummy , false ) ;
if ( ! fVerbose ) {
UniValue o ( UniValue : : VARR ) ;
2017-06-02 03:18:57 +02:00
for ( CTxMemPool : : txiter ancestorIt : setAncestors ) {
2016-01-04 19:58:59 +01:00
o . push_back ( ancestorIt - > GetTx ( ) . GetHash ( ) . ToString ( ) ) ;
}
return o ;
} else {
UniValue o ( UniValue : : VOBJ ) ;
2017-06-02 03:18:57 +02:00
for ( CTxMemPool : : txiter ancestorIt : setAncestors ) {
2016-01-04 19:58:59 +01:00
const CTxMemPoolEntry & e = * ancestorIt ;
2016-09-02 18:19:01 +02:00
const uint256 & _hash = e . GetTx ( ) . GetHash ( ) ;
2016-01-04 19:58:59 +01:00
UniValue info ( UniValue : : VOBJ ) ;
entryToJSON ( info , e ) ;
2016-09-02 18:19:01 +02:00
o . push_back ( Pair ( _hash . ToString ( ) , info ) ) ;
2016-01-04 19:58:59 +01:00
}
return o ;
}
}
2016-09-22 09:46:41 +02:00
UniValue getmempooldescendants ( const JSONRPCRequest & request )
2016-01-04 20:48:22 +01:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 ) {
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-01-04 20:48:22 +01:00
" getmempooldescendants txid (verbose) \n "
" \n If txid is in the mempool, returns all in-mempool descendants. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" txid \" (string, required) The transaction id (must be in mempool) \n "
" 2. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids \n "
2016-01-04 20:48:22 +01:00
" \n Result (for verbose=false): \n "
" [ (json array of strings) \n "
" \" transactionid \" (string) The transaction id of an in-mempool descendant transaction \n "
" ,... \n "
" ] \n "
" \n Result (for verbose=true): \n "
" { (json object) \n "
" \" transactionid \" : { (json object) \n "
+ EntryDescriptionString ( )
+ " }, ... \n "
" } \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2016-01-04 20:48:22 +01:00
+ HelpExampleCli ( " getmempooldescendants " , " \" mytxid \" " )
+ HelpExampleRpc ( " getmempooldescendants " , " \" mytxid \" " )
) ;
}
bool fVerbose = false ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
fVerbose = request . params [ 1 ] . get_bool ( ) ;
2016-01-04 20:48:22 +01:00
2016-09-22 09:46:41 +02:00
uint256 hash = ParseHashV ( request . params [ 0 ] , " parameter 1 " ) ;
2016-01-04 20:48:22 +01:00
LOCK ( mempool . cs ) ;
CTxMemPool : : txiter it = mempool . mapTx . find ( hash ) ;
if ( it = = mempool . mapTx . end ( ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Transaction not in mempool " ) ;
}
CTxMemPool : : setEntries setDescendants ;
mempool . CalculateDescendants ( it , setDescendants ) ;
// CTxMemPool::CalculateDescendants will include the given tx
setDescendants . erase ( it ) ;
if ( ! fVerbose ) {
UniValue o ( UniValue : : VARR ) ;
2017-06-02 03:18:57 +02:00
for ( CTxMemPool : : txiter descendantIt : setDescendants ) {
2016-01-04 20:48:22 +01:00
o . push_back ( descendantIt - > GetTx ( ) . GetHash ( ) . ToString ( ) ) ;
}
return o ;
} else {
UniValue o ( UniValue : : VOBJ ) ;
2017-06-02 03:18:57 +02:00
for ( CTxMemPool : : txiter descendantIt : setDescendants ) {
2016-01-04 20:48:22 +01:00
const CTxMemPoolEntry & e = * descendantIt ;
2016-09-02 18:19:01 +02:00
const uint256 & _hash = e . GetTx ( ) . GetHash ( ) ;
2016-01-04 20:48:22 +01:00
UniValue info ( UniValue : : VOBJ ) ;
entryToJSON ( info , e ) ;
2016-09-02 18:19:01 +02:00
o . push_back ( Pair ( _hash . ToString ( ) , info ) ) ;
2016-01-04 20:48:22 +01:00
}
return o ;
}
}
2016-09-22 09:46:41 +02:00
UniValue getmempoolentry ( const JSONRPCRequest & request )
2016-01-04 20:57:58 +01:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 1 ) {
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-01-04 20:57:58 +01:00
" getmempoolentry txid \n "
" \n Returns mempool data for given transaction \n "
" \n Arguments: \n "
" 1. \" txid \" (string, required) The transaction id (must be in mempool) \n "
" \n Result: \n "
" { (json object) \n "
+ EntryDescriptionString ( )
+ " } \n "
2016-12-22 05:26:03 +01:00
" \n Examples: \n "
2016-01-04 20:57:58 +01:00
+ HelpExampleCli ( " getmempoolentry " , " \" mytxid \" " )
+ HelpExampleRpc ( " getmempoolentry " , " \" mytxid \" " )
) ;
}
2016-09-22 09:46:41 +02:00
uint256 hash = ParseHashV ( request . params [ 0 ] , " parameter 1 " ) ;
2016-01-04 20:57:58 +01:00
LOCK ( mempool . cs ) ;
CTxMemPool : : txiter it = mempool . mapTx . find ( hash ) ;
if ( it = = mempool . mapTx . end ( ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Transaction not in mempool " ) ;
}
const CTxMemPoolEntry & e = * it ;
UniValue info ( UniValue : : VOBJ ) ;
entryToJSON ( info , e ) ;
return info ;
}
2016-09-22 09:46:41 +02:00
UniValue getblockhash ( const JSONRPCRequest & request )
2012-08-21 17:03:38 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-12-09 18:06:42 +01:00
" getblockhash height \n "
" \n Returns hash of block in best-block-chain at height provided. \n "
2013-10-29 12:29:44 +01:00
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. height (numeric, required) The height index \n "
2013-10-29 12:29:44 +01:00
" \n Result: \n "
" \" hash \" (string) The block hash \n "
" \n Examples: \n "
+ HelpExampleCli ( " getblockhash " , " 1000 " )
+ HelpExampleRpc ( " getblockhash " , " 1000 " )
) ;
2012-08-21 17:03:38 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2016-09-22 09:46:41 +02:00
int nHeight = request . params [ 0 ] . get_int ( ) ;
2013-10-10 23:07:44 +02:00
if ( nHeight < 0 | | nHeight > chainActive . Height ( ) )
2014-10-24 15:43:40 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Block height out of range " ) ;
2012-08-21 17:03:38 +02:00
2013-10-10 23:07:44 +02:00
CBlockIndex * pblockindex = chainActive [ nHeight ] ;
return pblockindex - > GetBlockHash ( ) . GetHex ( ) ;
2012-08-21 17:03:38 +02:00
}
2016-09-22 09:46:41 +02:00
UniValue getblockheader ( const JSONRPCRequest & request )
2015-06-05 21:37:17 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2015-06-05 21:37:17 +02:00
" getblockheader \" hash \" ( verbose ) \n "
" \n If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. \n "
" If verbose is true, returns an Object with information about blockheader <hash>. \n "
" \n Arguments: \n "
" 1. \" hash \" (string, required) The block hash \n "
" 2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data \n "
" \n Result (for verbose = true): \n "
" { \n "
" \" hash \" : \" hash \" , (string) the block hash (same as provided) \n "
" \" confirmations \" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain \n "
" \" height \" : n, (numeric) The block height or index \n "
" \" version \" : n, (numeric) The block version \n "
2016-04-05 00:21:00 +02:00
" \" versionHex \" : \" 00000000 \" , (string) The block version formatted in hexadecimal \n "
2015-06-05 21:37:17 +02:00
" \" merkleroot \" : \" xxxx \" , (string) The merkle root \n "
" \" time \" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT) \n "
2015-11-13 22:57:10 +01:00
" \" mediantime \" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT) \n "
2015-06-05 21:37:17 +02:00
" \" nonce \" : n, (numeric) The nonce \n "
" \" bits \" : \" 1d00ffff \" , (string) The bits \n "
" \" difficulty \" : x.xxx, (numeric) The difficulty \n "
2017-01-11 14:29:46 +01:00
" \" chainwork \" : \" 0000...1f3 \" (string) Expected number of hashes required to produce the current chain (in hex) \n "
2015-06-05 21:37:17 +02:00
" \" previousblockhash \" : \" hash \" , (string) The hash of the previous block \n "
2015-12-09 18:02:19 +01:00
" \" nextblockhash \" : \" hash \" , (string) The hash of the next block \n "
2015-06-05 21:37:17 +02:00
" } \n "
" \n Result (for verbose=false): \n "
" \" data \" (string) A string that is serialized, hex-encoded data for block 'hash'. \n "
" \n Examples: \n "
+ HelpExampleCli ( " getblockheader " , " \" 00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09 \" " )
+ HelpExampleRpc ( " getblockheader " , " \" 00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09 \" " )
) ;
LOCK ( cs_main ) ;
2016-09-22 09:46:41 +02:00
std : : string strHash = request . params [ 0 ] . get_str ( ) ;
2015-06-05 21:37:17 +02:00
uint256 hash ( uint256S ( strHash ) ) ;
bool fVerbose = true ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
fVerbose = request . params [ 1 ] . get_bool ( ) ;
2015-06-05 21:37:17 +02:00
if ( mapBlockIndex . count ( hash ) = = 0 )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
CBlockIndex * pblockindex = mapBlockIndex [ hash ] ;
if ( ! fVerbose )
{
CDataStream ssBlock ( SER_NETWORK , PROTOCOL_VERSION ) ;
ssBlock < < pblockindex - > GetBlockHeader ( ) ;
std : : string strHex = HexStr ( ssBlock . begin ( ) , ssBlock . end ( ) ) ;
return strHex ;
}
return blockheaderToJSON ( pblockindex ) ;
}
2016-09-22 09:46:41 +02:00
UniValue getblock ( const JSONRPCRequest & request )
2012-08-21 17:03:38 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 1 | | request . params . size ( ) > 2 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2017-04-10 15:28:56 +02:00
" getblock \" blockhash \" ( verbosity ) \n "
" \n If verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'. \n "
" If verbosity is 1, returns an Object with information about block <hash>. \n "
" If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n "
2013-10-29 12:29:44 +01:00
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" blockhash \" (string, required) The block hash \n "
2017-04-10 15:28:56 +02:00
" 2. verbosity (numeric, optional, default=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data \n "
" \n Result (for verbosity = 0): \n "
" \" data \" (string) A string that is serialized, hex-encoded data for block 'hash'. \n "
" \n Result (for verbosity = 1): \n "
2013-10-29 12:29:44 +01:00
" { \n "
" \" hash \" : \" hash \" , (string) the block hash (same as provided) \n "
2014-08-28 17:14:22 +02:00
" \" confirmations \" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain \n "
2013-10-29 12:29:44 +01:00
" \" size \" : n, (numeric) The block size \n "
2016-01-22 18:46:11 +01:00
" \" strippedsize \" : n, (numeric) The block size excluding witness data \n "
2016-09-15 16:46:01 +02:00
" \" weight \" : n (numeric) The block weight as defined in BIP 141 \n "
2013-10-29 12:29:44 +01:00
" \" height \" : n, (numeric) The block height or index \n "
" \" version \" : n, (numeric) The block version \n "
2016-04-05 00:21:00 +02:00
" \" versionHex \" : \" 00000000 \" , (string) The block version formatted in hexadecimal \n "
2013-10-29 12:29:44 +01:00
" \" merkleroot \" : \" xxxx \" , (string) The merkle root \n "
" \" tx \" : [ (array of string) The transaction ids \n "
" \" transactionid \" (string) The transaction id \n "
" ,... \n "
" ], \n "
" \" time \" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT) \n "
2015-11-13 22:57:10 +01:00
" \" mediantime \" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT) \n "
2013-10-29 12:29:44 +01:00
" \" nonce \" : n, (numeric) The nonce \n "
" \" bits \" : \" 1d00ffff \" , (string) The bits \n "
" \" difficulty \" : x.xxx, (numeric) The difficulty \n "
2015-12-18 20:07:48 +01:00
" \" chainwork \" : \" xxxx \" , (string) Expected number of hashes required to produce the chain up to this block (in hex) \n "
2013-10-29 12:29:44 +01:00
" \" previousblockhash \" : \" hash \" , (string) The hash of the previous block \n "
" \" nextblockhash \" : \" hash \" (string) The hash of the next block \n "
" } \n "
2017-04-10 15:28:56 +02:00
" \n Result (for verbosity = 2): \n "
" { \n "
" ..., Same output as verbosity = 1. \n "
" \" tx \" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \" tx \" result. \n "
" ,... \n "
" ], \n "
" ,... Same output as verbosity = 1. \n "
" } \n "
2013-10-29 12:29:44 +01:00
" \n Examples: \n "
+ HelpExampleCli ( " getblock " , " \" 00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09 \" " )
+ HelpExampleRpc ( " getblock " , " \" 00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09 \" " )
2013-06-07 07:23:30 +02:00
) ;
2012-08-21 17:03:38 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2016-09-22 09:46:41 +02:00
std : : string strHash = request . params [ 0 ] . get_str ( ) ;
2014-12-16 14:50:05 +01:00
uint256 hash ( uint256S ( strHash ) ) ;
2012-08-21 17:03:38 +02:00
2017-04-10 15:28:56 +02:00
int verbosity = 1 ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) ) {
2017-04-10 15:28:56 +02:00
if ( request . params [ 1 ] . isNum ( ) )
verbosity = request . params [ 1 ] . get_int ( ) ;
else
verbosity = request . params [ 1 ] . get_bool ( ) ? 1 : 0 ;
}
2013-06-07 07:23:30 +02:00
2012-08-21 17:03:38 +02:00
if ( mapBlockIndex . count ( hash ) = = 0 )
2012-10-04 09:34:44 +02:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
2012-08-21 17:03:38 +02:00
CBlock block ;
CBlockIndex * pblockindex = mapBlockIndex [ hash ] ;
2014-07-10 02:37:27 +02:00
2015-04-27 05:18:24 +02:00
if ( fHavePruned & & ! ( pblockindex - > nStatus & BLOCK_HAVE_DATA ) & & pblockindex - > nTx > 0 )
2017-02-09 22:39:18 +01:00
throw JSONRPCError ( RPC_MISC_ERROR , " Block not available (pruned data) " ) ;
2015-04-27 05:18:24 +02:00
2017-02-09 22:39:18 +01:00
if ( ! ReadBlockFromDisk ( block , pblockindex , Params ( ) . GetConsensus ( ) ) )
// Block not found on disk. This could be because we have the block
// header in our index but don't have the block (for example if a
// non-whitelisted node sends us an unrequested long chain of valid
// blocks, we add the headers to our index, but don't accept the
// block).
throw JSONRPCError ( RPC_MISC_ERROR , " Block not found on disk " ) ;
2012-08-21 17:03:38 +02:00
2017-04-10 15:28:56 +02:00
if ( verbosity < = 0 )
2013-06-07 07:23:30 +02:00
{
2016-11-20 15:54:51 +01:00
CDataStream ssBlock ( SER_NETWORK , PROTOCOL_VERSION | RPCSerializationFlags ( ) ) ;
2013-06-07 07:23:30 +02:00
ssBlock < < block ;
std : : string strHex = HexStr ( ssBlock . begin ( ) , ssBlock . end ( ) ) ;
return strHex ;
}
2017-04-10 15:28:56 +02:00
return blockToJSON ( block , pblockindex , verbosity > = 2 ) ;
2012-08-21 17:03:38 +02:00
}
2016-03-28 18:18:30 +02:00
struct CCoinsStats
{
int nHeight ;
uint256 hashBlock ;
uint64_t nTransactions ;
uint64_t nTransactionOutputs ;
2017-05-19 01:29:29 +02:00
uint64_t nBogoSize ;
2016-03-28 18:18:30 +02:00
uint256 hashSerialized ;
2017-05-13 00:19:19 +02:00
uint64_t nDiskSize ;
2016-03-28 18:18:30 +02:00
CAmount nTotalAmount ;
2017-05-19 01:29:29 +02:00
CCoinsStats ( ) : nHeight ( 0 ) , nTransactions ( 0 ) , nTransactionOutputs ( 0 ) , nBogoSize ( 0 ) , nDiskSize ( 0 ) , nTotalAmount ( 0 ) { }
2016-03-28 18:18:30 +02:00
} ;
2017-04-27 01:39:58 +02:00
static void ApplyStats ( CCoinsStats & stats , CHashWriter & ss , const uint256 & hash , const std : : map < uint32_t , Coin > & outputs )
{
assert ( ! outputs . empty ( ) ) ;
ss < < hash ;
ss < < VARINT ( outputs . begin ( ) - > second . nHeight * 2 + outputs . begin ( ) - > second . fCoinBase ) ;
stats . nTransactions + + ;
for ( const auto output : outputs ) {
ss < < VARINT ( output . first + 1 ) ;
2017-07-07 09:54:42 +02:00
ss < < output . second . out . scriptPubKey ;
2017-04-27 01:39:58 +02:00
ss < < VARINT ( output . second . out . nValue ) ;
stats . nTransactionOutputs + + ;
stats . nTotalAmount + = output . second . out . nValue ;
2017-05-19 01:29:29 +02:00
stats . nBogoSize + = 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ +
2 /* scriptPubKey len */ + output . second . out . scriptPubKey . size ( ) /* scriptPubKey */ ;
2017-04-27 01:39:58 +02:00
}
ss < < VARINT ( 0 ) ;
}
2016-03-28 18:18:30 +02:00
//! Calculate statistics about the unspent transaction output set
static bool GetUTXOStats ( CCoinsView * view , CCoinsStats & stats )
{
2016-08-30 22:41:56 +02:00
std : : unique_ptr < CCoinsViewCursor > pcursor ( view - > Cursor ( ) ) ;
2016-03-28 18:18:30 +02:00
CHashWriter ss ( SER_GETHASH , PROTOCOL_VERSION ) ;
stats . hashBlock = pcursor - > GetBestBlock ( ) ;
{
LOCK ( cs_main ) ;
stats . nHeight = mapBlockIndex . find ( stats . hashBlock ) - > second - > nHeight ;
}
ss < < stats . hashBlock ;
2017-04-25 20:29:39 +02:00
uint256 prevkey ;
std : : map < uint32_t , Coin > outputs ;
2016-03-28 18:18:30 +02:00
while ( pcursor - > Valid ( ) ) {
boost : : this_thread : : interruption_point ( ) ;
2017-04-25 20:29:39 +02:00
COutPoint key ;
Coin coin ;
if ( pcursor - > GetKey ( key ) & & pcursor - > GetValue ( coin ) ) {
if ( ! outputs . empty ( ) & & key . hash ! = prevkey ) {
ApplyStats ( stats , ss , prevkey , outputs ) ;
outputs . clear ( ) ;
2016-03-28 18:18:30 +02:00
}
2017-04-25 20:29:39 +02:00
prevkey = key . hash ;
outputs [ key . n ] = std : : move ( coin ) ;
2016-03-28 18:18:30 +02:00
} else {
return error ( " %s: unable to read value " , __func__ ) ;
}
pcursor - > Next ( ) ;
}
2017-04-25 20:29:39 +02:00
if ( ! outputs . empty ( ) ) {
ApplyStats ( stats , ss , prevkey , outputs ) ;
}
2016-03-28 18:18:30 +02:00
stats . hashSerialized = ss . GetHash ( ) ;
2017-05-13 00:19:19 +02:00
stats . nDiskSize = view - > EstimateSize ( ) ;
2016-03-28 18:18:30 +02:00
return true ;
}
2016-11-29 18:39:19 +01:00
UniValue pruneblockchain ( const JSONRPCRequest & request )
{
if ( request . fHelp | | request . params . size ( ) ! = 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-11-29 18:39:19 +01:00
" pruneblockchain \n "
" \n Arguments: \n "
2017-02-16 17:07:15 +01:00
" 1. \" height \" (numeric, required) The block height to prune up to. May be set to a discrete height, or a unix timestamp \n "
" to prune blocks whose block time is at least 2 hours older than the provided timestamp. \n "
2017-01-11 20:25:32 +01:00
" \n Result: \n "
" n (numeric) Height of the last block pruned. \n "
" \n Examples: \n "
+ HelpExampleCli ( " pruneblockchain " , " 1000 " )
+ HelpExampleRpc ( " pruneblockchain " , " 1000 " ) ) ;
2016-11-29 18:39:19 +01:00
if ( ! fPruneMode )
2017-02-09 22:39:18 +01:00
throw JSONRPCError ( RPC_MISC_ERROR , " Cannot prune blocks because node is not in prune mode. " ) ;
2016-11-29 18:39:19 +01:00
LOCK ( cs_main ) ;
int heightParam = request . params [ 0 ] . get_int ( ) ;
if ( heightParam < 0 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Negative block height. " ) ;
2017-01-09 19:35:12 +01:00
// Height value more than a billion is too high to be a block height, and
// too low to be a block time (corresponds to timestamp from Sep 2001).
if ( heightParam > 1000000000 ) {
2017-02-16 17:07:15 +01:00
// Add a 2 hour buffer to include blocks which might have had old timestamps
2017-03-02 18:20:34 +01:00
CBlockIndex * pindex = chainActive . FindEarliestAtLeast ( heightParam - TIMESTAMP_WINDOW ) ;
2017-01-09 19:35:12 +01:00
if ( ! pindex ) {
2017-02-09 22:39:18 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Could not find block with at least the specified timestamp. " ) ;
2017-01-09 19:35:12 +01:00
}
heightParam = pindex - > nHeight ;
}
2016-11-29 18:39:19 +01:00
unsigned int height = ( unsigned int ) heightParam ;
unsigned int chainHeight = ( unsigned int ) chainActive . Height ( ) ;
if ( chainHeight < Params ( ) . PruneAfterHeight ( ) )
2017-02-09 22:39:18 +01:00
throw JSONRPCError ( RPC_MISC_ERROR , " Blockchain is too short for pruning. " ) ;
2016-11-29 18:39:19 +01:00
else if ( height > chainHeight )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Blockchain is shorter than the attempted prune height. " ) ;
2017-01-11 20:25:32 +01:00
else if ( height > chainHeight - MIN_BLOCKS_TO_KEEP ) {
2016-12-25 21:19:40 +01:00
LogPrint ( BCLog : : RPC , " Attempt to prune blocks close to the tip. Retaining the minimum number of blocks. " ) ;
2017-01-11 20:25:32 +01:00
height = chainHeight - MIN_BLOCKS_TO_KEEP ;
}
2016-11-29 18:39:19 +01:00
PruneBlockFilesManual ( height ) ;
2017-01-11 20:25:32 +01:00
return uint64_t ( height ) ;
2016-11-29 18:39:19 +01:00
}
2016-09-22 09:46:41 +02:00
UniValue gettxoutsetinfo ( const JSONRPCRequest & request )
2012-09-25 23:04:54 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 0 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2012-09-25 23:04:54 +02:00
" gettxoutsetinfo \n "
2013-10-29 12:29:44 +01:00
" \n Returns statistics about the unspent transaction output set. \n "
" Note this call may take some time. \n "
" \n Result: \n "
" { \n "
" \" height \" :n, (numeric) The current block height (index) \n "
" \" bestblock \" : \" hex \" , (string) the best block hash hex \n "
" \" transactions \" : n, (numeric) The number of transactions \n "
" \" txouts \" : n, (numeric) The number of output transactions \n "
2017-05-19 01:29:29 +02:00
" \" bogosize \" : n, (numeric) A meaningless metric for UTXO set size \n "
" \" hash_serialized_2 \" : \" hash \" , (string) The serialized hash \n "
2017-05-13 00:19:19 +02:00
" \" disk_size \" : n, (numeric) The estimated size of the chainstate on disk \n "
2013-10-29 12:29:44 +01:00
" \" total_amount \" : x.xxx (numeric) The total amount \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " gettxoutsetinfo " , " " )
+ HelpExampleRpc ( " gettxoutsetinfo " , " " )
) ;
2012-09-25 23:04:54 +02:00
2015-05-10 14:48:35 +02:00
UniValue ret ( UniValue : : VOBJ ) ;
2012-09-25 23:04:54 +02:00
CCoinsStats stats ;
Improve chainstate/blockindex disk writing policy
There are 3 pieces of data that are maintained on disk. The actual block
and undo data, the block index (which can refer to positions on disk),
and the chainstate (which refers to the best block hash).
Earlier, there was no guarantee that blocks were written to disk before
block index entries referring to them were written. This commit introduces
dirty flags for block index data, and delays writing entries until the actual
block data is flushed.
With this stricter ordering in writes, it is now safe to not always flush
after every block, so there is no need for the IsInitialBlockDownload()
check there - instead we just write whenever enough time has passed or
the cache size grows too large. Also updating the wallet's best known block
is delayed until this is done, otherwise the wallet may end up referring to an
unknown block.
In addition, only do a write inside the block processing loop if necessary
(because of cache size exceeded). Otherwise, move the writing to a point
after processing is done, after relaying.
2014-11-07 11:38:35 +01:00
FlushStateToDisk ( ) ;
2017-06-07 19:00:11 +02:00
if ( GetUTXOStats ( pcoinsdbview , stats ) ) {
2014-05-05 20:08:13 +02:00
ret . push_back ( Pair ( " height " , ( int64_t ) stats . nHeight ) ) ;
2013-05-01 16:23:27 +02:00
ret . push_back ( Pair ( " bestblock " , stats . hashBlock . GetHex ( ) ) ) ;
2014-05-05 20:08:13 +02:00
ret . push_back ( Pair ( " transactions " , ( int64_t ) stats . nTransactions ) ) ;
ret . push_back ( Pair ( " txouts " , ( int64_t ) stats . nTransactionOutputs ) ) ;
2017-05-19 01:29:29 +02:00
ret . push_back ( Pair ( " bogosize " , ( int64_t ) stats . nBogoSize ) ) ;
2017-04-25 20:29:18 +02:00
ret . push_back ( Pair ( " hash_serialized_2 " , stats . hashSerialized . GetHex ( ) ) ) ;
2017-05-13 00:19:19 +02:00
ret . push_back ( Pair ( " disk_size " , stats . nDiskSize ) ) ;
2013-05-01 16:23:27 +02:00
ret . push_back ( Pair ( " total_amount " , ValueFromAmount ( stats . nTotalAmount ) ) ) ;
2016-09-28 21:05:11 +02:00
} else {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Unable to read UTXO set " ) ;
2012-09-25 23:04:54 +02:00
}
return ret ;
}
2012-08-21 17:03:38 +02:00
2016-09-22 09:46:41 +02:00
UniValue gettxout ( const JSONRPCRequest & request )
2012-09-25 23:04:54 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) < 2 | | request . params . size ( ) > 3 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-09-25 20:44:06 +02:00
" gettxout \" txid \" n ( include_mempool ) \n "
2013-10-29 12:29:44 +01:00
" \n Returns details about an unspent transaction output. \n "
" \n Arguments: \n "
2017-07-18 02:19:21 +02:00
" 1. \" txid \" (string, required) The transaction id \n "
" 2. \" n \" (numeric, required) vout number \n "
" 3. \" include_mempool \" (boolean, optional) Whether to include the mempool. Default: true. "
" Note that an unspent output that is spent in the mempool won't appear. \n "
2013-10-29 12:29:44 +01:00
" \n Result: \n "
" { \n "
" \" bestblock \" : \" hash \" , (string) the block hash \n "
" \" confirmations \" : n, (numeric) The number of confirmations \n "
2015-08-01 21:15:23 +02:00
" \" value \" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + " \n "
2013-10-29 12:29:44 +01:00
" \" scriptPubKey \" : { (json object) \n "
" \" asm \" : \" code \" , (string) \n "
" \" hex \" : \" hex \" , (string) \n "
" \" reqSigs \" : n, (numeric) Number of required signatures \n "
" \" type \" : \" pubkeyhash \" , (string) The type, eg pubkeyhash \n "
" \" addresses \" : [ (array of string) array of bitcoin addresses \n "
2016-11-21 14:39:58 +01:00
" \" address \" (string) bitcoin address \n "
2013-10-29 12:29:44 +01:00
" ,... \n "
" ] \n "
" }, \n "
" \" coinbase \" : true|false (boolean) Coinbase or not \n "
" } \n "
" \n Examples: \n "
" \n Get unspent transactions \n "
+ HelpExampleCli ( " listunspent " , " " ) +
" \n View the details \n "
+ HelpExampleCli ( " gettxout " , " \" txid \" 1 " ) +
" \n As a json rpc call \n "
+ HelpExampleRpc ( " gettxout " , " \" txid \" , 1 " )
) ;
2012-08-21 17:03:38 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2015-05-10 14:48:35 +02:00
UniValue ret ( UniValue : : VOBJ ) ;
2012-09-25 23:04:54 +02:00
2016-09-22 09:46:41 +02:00
std : : string strHash = request . params [ 0 ] . get_str ( ) ;
2014-12-16 14:50:05 +01:00
uint256 hash ( uint256S ( strHash ) ) ;
2016-09-22 09:46:41 +02:00
int n = request . params [ 1 ] . get_int ( ) ;
2017-04-25 20:29:39 +02:00
COutPoint out ( hash , n ) ;
2012-09-25 23:04:54 +02:00
bool fMempool = true ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 2 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
fMempool = request . params [ 2 ] . get_bool ( ) ;
2012-09-25 23:04:54 +02:00
2017-04-25 20:29:39 +02:00
Coin coin ;
2012-09-25 23:04:54 +02:00
if ( fMempool ) {
LOCK ( mempool . cs ) ;
2014-09-24 03:19:04 +02:00
CCoinsViewMemPool view ( pcoinsTip , mempool ) ;
2017-06-27 20:46:19 +02:00
if ( ! view . GetCoin ( out , coin ) | | mempool . isSpent ( out ) ) {
2014-08-20 21:15:16 +02:00
return NullUniValue ;
2017-04-25 20:29:39 +02:00
}
2012-09-25 23:04:54 +02:00
} else {
2017-05-31 02:58:54 +02:00
if ( ! pcoinsTip - > GetCoin ( out , coin ) ) {
2014-08-20 21:15:16 +02:00
return NullUniValue ;
2017-04-25 20:29:39 +02:00
}
2012-09-25 23:04:54 +02:00
}
2014-09-04 02:02:44 +02:00
BlockMap : : iterator it = mapBlockIndex . find ( pcoinsTip - > GetBestBlock ( ) ) ;
2013-11-05 02:27:39 +01:00
CBlockIndex * pindex = it - > second ;
ret . push_back ( Pair ( " bestblock " , pindex - > GetBlockHash ( ) . GetHex ( ) ) ) ;
2017-04-25 20:29:39 +02:00
if ( coin . nHeight = = MEMPOOL_HEIGHT ) {
2012-09-25 23:04:54 +02:00
ret . push_back ( Pair ( " confirmations " , 0 ) ) ;
2017-04-25 20:29:39 +02:00
} else {
ret . push_back ( Pair ( " confirmations " , ( int64_t ) ( pindex - > nHeight - coin . nHeight + 1 ) ) ) ;
}
ret . push_back ( Pair ( " value " , ValueFromAmount ( coin . out . nValue ) ) ) ;
2015-05-10 14:48:35 +02:00
UniValue o ( UniValue : : VOBJ ) ;
2017-04-25 20:29:39 +02:00
ScriptPubKeyToUniv ( coin . out . scriptPubKey , o , true ) ;
2012-09-25 23:04:54 +02:00
ret . push_back ( Pair ( " scriptPubKey " , o ) ) ;
2017-04-25 20:29:39 +02:00
ret . push_back ( Pair ( " coinbase " , ( bool ) coin . fCoinBase ) ) ;
2012-09-25 23:04:54 +02:00
return ret ;
}
2012-08-21 17:03:38 +02:00
2016-09-22 09:46:41 +02:00
UniValue verifychain ( const JSONRPCRequest & request )
2013-06-19 17:53:02 +02:00
{
2017-08-01 21:17:40 +02:00
int nCheckLevel = gArgs . GetArg ( " -checklevel " , DEFAULT_CHECKLEVEL ) ;
int nCheckDepth = gArgs . GetArg ( " -checkblocks " , DEFAULT_CHECKBLOCKS ) ;
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) > 2 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-09-25 20:44:06 +02:00
" verifychain ( checklevel nblocks ) \n "
2013-10-29 12:29:44 +01:00
" \n Verifies blockchain database. \n "
" \n Arguments: \n "
2015-06-27 21:08:36 +02:00
" 1. checklevel (numeric, optional, 0-4, default= " + strprintf ( " %d " , nCheckLevel ) + " ) How thorough the block verification is. \n "
2016-09-25 20:44:06 +02:00
" 2. nblocks (numeric, optional, default= " + strprintf ( " %d " , nCheckDepth ) + " , 0=all) The number of blocks to check. \n "
2013-10-29 12:29:44 +01:00
" \n Result: \n "
" true|false (boolean) Verified or not \n "
" \n Examples: \n "
+ HelpExampleCli ( " verifychain " , " " )
+ HelpExampleRpc ( " verifychain " , " " )
) ;
2013-06-19 17:53:02 +02:00
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 0 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
nCheckLevel = request . params [ 0 ] . get_int ( ) ;
2017-07-10 17:44:39 +02:00
if ( ! request . params [ 1 ] . isNull ( ) )
2016-09-22 09:46:41 +02:00
nCheckDepth = request . params [ 1 ] . get_int ( ) ;
2013-06-19 17:53:02 +02:00
2015-04-17 14:40:24 +02:00
return CVerifyDB ( ) . VerifyDB ( Params ( ) , pcoinsTip , nCheckLevel , nCheckDepth ) ;
2013-06-19 17:53:02 +02:00
}
2012-08-21 17:03:38 +02:00
2015-06-27 08:03:34 +02:00
/** Implementation of IsSuperMajority with better feedback */
2016-07-22 01:27:55 +02:00
static UniValue SoftForkMajorityDesc ( int version , CBlockIndex * pindex , const Consensus : : Params & consensusParams )
2015-06-27 08:03:34 +02:00
{
2016-07-22 01:27:55 +02:00
UniValue rv ( UniValue : : VOBJ ) ;
bool activated = false ;
switch ( version )
2015-06-27 08:03:34 +02:00
{
2016-07-22 01:27:55 +02:00
case 2 :
activated = pindex - > nHeight > = consensusParams . BIP34Height ;
break ;
case 3 :
activated = pindex - > nHeight > = consensusParams . BIP66Height ;
break ;
case 4 :
activated = pindex - > nHeight > = consensusParams . BIP65Height ;
break ;
2015-06-27 08:03:34 +02:00
}
2016-07-22 01:27:55 +02:00
rv . push_back ( Pair ( " status " , activated ) ) ;
2015-06-27 08:03:34 +02:00
return rv ;
}
static UniValue SoftForkDesc ( const std : : string & name , int version , CBlockIndex * pindex , const Consensus : : Params & consensusParams )
{
UniValue rv ( UniValue : : VOBJ ) ;
rv . push_back ( Pair ( " id " , name ) ) ;
rv . push_back ( Pair ( " version " , version ) ) ;
2016-07-22 01:27:55 +02:00
rv . push_back ( Pair ( " reject " , SoftForkMajorityDesc ( version , pindex , consensusParams ) ) ) ;
2015-06-27 08:03:34 +02:00
return rv ;
}
2016-04-12 08:14:18 +02:00
static UniValue BIP9SoftForkDesc ( const Consensus : : Params & consensusParams , Consensus : : DeploymentPos id )
2016-03-03 21:00:03 +01:00
{
UniValue rv ( UniValue : : VOBJ ) ;
2016-04-05 00:21:00 +02:00
const ThresholdState thresholdState = VersionBitsTipState ( consensusParams , id ) ;
switch ( thresholdState ) {
2016-03-03 21:00:03 +01:00
case THRESHOLD_DEFINED : rv . push_back ( Pair ( " status " , " defined " ) ) ; break ;
case THRESHOLD_STARTED : rv . push_back ( Pair ( " status " , " started " ) ) ; break ;
case THRESHOLD_LOCKED_IN : rv . push_back ( Pair ( " status " , " locked_in " ) ) ; break ;
case THRESHOLD_ACTIVE : rv . push_back ( Pair ( " status " , " active " ) ) ; break ;
case THRESHOLD_FAILED : rv . push_back ( Pair ( " status " , " failed " ) ) ; break ;
}
2016-04-05 00:21:00 +02:00
if ( THRESHOLD_STARTED = = thresholdState )
{
rv . push_back ( Pair ( " bit " , consensusParams . vDeployments [ id ] . bit ) ) ;
}
rv . push_back ( Pair ( " startTime " , consensusParams . vDeployments [ id ] . nStartTime ) ) ;
rv . push_back ( Pair ( " timeout " , consensusParams . vDeployments [ id ] . nTimeout ) ) ;
2016-05-07 00:08:39 +02:00
rv . push_back ( Pair ( " since " , VersionBitsTipStateSinceHeight ( consensusParams , id ) ) ) ;
2017-01-14 02:06:50 +01:00
if ( THRESHOLD_STARTED = = thresholdState )
{
UniValue statsUV ( UniValue : : VOBJ ) ;
BIP9Stats statsStruct = VersionBitsTipStatistics ( consensusParams , id ) ;
statsUV . push_back ( Pair ( " period " , statsStruct . period ) ) ;
statsUV . push_back ( Pair ( " threshold " , statsStruct . threshold ) ) ;
statsUV . push_back ( Pair ( " elapsed " , statsStruct . elapsed ) ) ;
statsUV . push_back ( Pair ( " count " , statsStruct . count ) ) ;
statsUV . push_back ( Pair ( " possible " , statsStruct . possible ) ) ;
rv . push_back ( Pair ( " statistics " , statsUV ) ) ;
}
2016-03-03 21:00:03 +01:00
return rv ;
}
2016-06-24 18:55:07 +02:00
void BIP9SoftForkDescPushBack ( UniValue & bip9_softforks , const std : : string & name , const Consensus : : Params & consensusParams , Consensus : : DeploymentPos id )
{
// Deployments with timeout value of 0 are hidden.
// A timeout value of 0 guarantees a softfork will never be activated.
// This is used when softfork codes are merged without specifying the deployment schedule.
if ( consensusParams . vDeployments [ id ] . nTimeout > 0 )
bip9_softforks . push_back ( Pair ( name , BIP9SoftForkDesc ( consensusParams , id ) ) ) ;
}
2016-09-22 09:46:41 +02:00
UniValue getblockchaininfo ( const JSONRPCRequest & request )
2014-05-05 13:22:28 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 0 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2014-05-05 13:22:28 +02:00
" getblockchaininfo \n "
2016-10-20 12:39:48 +02:00
" Returns an object containing various state info regarding blockchain processing. \n "
2014-05-05 13:22:28 +02:00
" \n Result: \n "
" { \n "
2014-06-12 14:52:12 +02:00
" \" chain \" : \" xxxx \" , (string) current network name as defined in BIP70 (main, test, regtest) \n "
2014-05-05 13:22:28 +02:00
" \" blocks \" : xxxxxx, (numeric) the current number of blocks processed in the server \n "
2014-07-12 00:03:10 +02:00
" \" headers \" : xxxxxx, (numeric) the current number of headers we have validated \n "
2014-05-05 13:22:28 +02:00
" \" bestblockhash \" : \" ... \" , (string) the hash of the currently best block \n "
" \" difficulty \" : xxxxxx, (numeric) the current difficulty \n "
2015-11-13 22:49:47 +01:00
" \" mediantime \" : xxxxxx, (numeric) median time for the current best block \n "
2014-05-05 13:22:28 +02:00
" \" verificationprogress \" : xxxx, (numeric) estimate of verification progress [0..1] \n "
" \" chainwork \" : \" xxxx \" (string) total amount of work in active chain, in hexadecimal \n "
2015-07-19 14:07:35 +02:00
" \" pruned \" : xx, (boolean) if the blocks are subject to pruning \n "
2016-10-05 00:20:07 +02:00
" \" pruneheight \" : xxxxxx, (numeric) lowest-height complete block stored \n "
2015-06-27 08:03:34 +02:00
" \" softforks \" : [ (array) status of softforks in progress \n "
" { \n "
" \" id \" : \" xxxx \" , (string) name of softfork \n "
" \" version \" : xx, (numeric) block version \n "
2016-07-22 01:27:55 +02:00
" \" reject \" : { (object) progress toward rejecting pre-softfork blocks \n "
2015-06-27 08:03:34 +02:00
" \" status \" : xx, (boolean) true if threshold reached \n "
" }, \n "
" }, ... \n "
2016-03-03 21:00:03 +01:00
" ], \n "
2016-04-12 08:14:18 +02:00
" \" bip9_softforks \" : { (object) status of BIP9 softforks in progress \n "
" \" xxxx \" : { (string) name of the softfork \n "
2016-06-24 18:55:07 +02:00
" \" status \" : \" xxxx \" , (string) one of \" defined \" , \" started \" , \" locked_in \" , \" active \" , \" failed \" \n "
2016-06-25 08:19:36 +02:00
" \" bit \" : xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \" started \" status) \n "
2016-04-05 00:21:00 +02:00
" \" startTime \" : xx, (numeric) the minimum median time past of a block at which the bit gains its meaning \n "
2016-05-07 00:08:39 +02:00
" \" timeout \" : xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in \n "
2017-01-14 02:06:50 +01:00
" \" since \" : xx, (numeric) height of the first block to which the status applies \n "
" \" statistics \" : { (object) numeric statistics about BIP9 signalling for a softfork (only for \" started \" status) \n "
" \" period \" : xx, (numeric) the length in blocks of the BIP9 signalling period \n "
" \" threshold \" : xx, (numeric) the number of blocks with the version bit set required to activate the feature \n "
" \" elapsed \" : xx, (numeric) the number of blocks elapsed since the beginning of the current period \n "
" \" count \" : xx, (numeric) the number of blocks with the version bit set in the current period \n "
" \" possible \" : xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n "
" } \n "
2016-03-03 21:00:03 +01:00
" } \n "
2016-04-12 08:14:18 +02:00
" } \n "
2014-05-05 13:22:28 +02:00
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getblockchaininfo " , " " )
+ HelpExampleRpc ( " getblockchaininfo " , " " )
) ;
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2015-05-10 14:48:35 +02:00
UniValue obj ( UniValue : : VOBJ ) ;
2014-06-11 12:23:49 +02:00
obj . push_back ( Pair ( " chain " , Params ( ) . NetworkIDString ( ) ) ) ;
obj . push_back ( Pair ( " blocks " , ( int ) chainActive . Height ( ) ) ) ;
2014-07-12 00:03:10 +02:00
obj . push_back ( Pair ( " headers " , pindexBestHeader ? pindexBestHeader - > nHeight : - 1 ) ) ;
2014-06-11 12:23:49 +02:00
obj . push_back ( Pair ( " bestblockhash " , chainActive . Tip ( ) - > GetBlockHash ( ) . GetHex ( ) ) ) ;
obj . push_back ( Pair ( " difficulty " , ( double ) GetDifficulty ( ) ) ) ;
2015-11-13 21:35:04 +01:00
obj . push_back ( Pair ( " mediantime " , ( int64_t ) chainActive . Tip ( ) - > GetMedianTimePast ( ) ) ) ;
2017-01-04 16:31:56 +01:00
obj . push_back ( Pair ( " verificationprogress " , GuessVerificationProgress ( Params ( ) . TxData ( ) , chainActive . Tip ( ) ) ) ) ;
2014-06-11 12:23:49 +02:00
obj . push_back ( Pair ( " chainwork " , chainActive . Tip ( ) - > nChainWork . GetHex ( ) ) ) ;
2015-04-24 22:12:06 +02:00
obj . push_back ( Pair ( " pruned " , fPruneMode ) ) ;
2015-06-27 08:03:34 +02:00
const Consensus : : Params & consensusParams = Params ( ) . GetConsensus ( ) ;
CBlockIndex * tip = chainActive . Tip ( ) ;
UniValue softforks ( UniValue : : VARR ) ;
2016-04-12 08:14:18 +02:00
UniValue bip9_softforks ( UniValue : : VOBJ ) ;
2015-06-27 08:03:34 +02:00
softforks . push_back ( SoftForkDesc ( " bip34 " , 2 , tip , consensusParams ) ) ;
softforks . push_back ( SoftForkDesc ( " bip66 " , 3 , tip , consensusParams ) ) ;
2015-09-27 20:32:10 +02:00
softforks . push_back ( SoftForkDesc ( " bip65 " , 4 , tip , consensusParams ) ) ;
2016-06-24 18:55:07 +02:00
BIP9SoftForkDescPushBack ( bip9_softforks , " csv " , consensusParams , Consensus : : DEPLOYMENT_CSV ) ;
BIP9SoftForkDescPushBack ( bip9_softforks , " segwit " , consensusParams , Consensus : : DEPLOYMENT_SEGWIT ) ;
2015-06-27 08:03:34 +02:00
obj . push_back ( Pair ( " softforks " , softforks ) ) ;
2016-03-03 21:00:03 +01:00
obj . push_back ( Pair ( " bip9_softforks " , bip9_softforks ) ) ;
2015-06-27 08:03:34 +02:00
2015-04-24 22:12:06 +02:00
if ( fPruneMode )
{
CBlockIndex * block = chainActive . Tip ( ) ;
while ( block & & block - > pprev & & ( block - > pprev - > nStatus & BLOCK_HAVE_DATA ) )
block = block - > pprev ;
obj . push_back ( Pair ( " pruneheight " , block - > nHeight ) ) ;
}
2014-05-05 13:22:28 +02:00
return obj ;
}
2014-08-03 18:12:19 +02:00
2014-11-20 03:19:29 +01:00
/** Comparison function for sorting the getchaintips heads. */
2014-08-03 18:12:19 +02:00
struct CompareBlocksByHeight
{
bool operator ( ) ( const CBlockIndex * a , const CBlockIndex * b ) const
{
/* Make sure that unequal blocks with the same height do not compare
2014-10-31 09:36:30 +01:00
equal . Use the pointers themselves to make a distinction . */
2014-08-03 18:12:19 +02:00
if ( a - > nHeight ! = b - > nHeight )
return ( a - > nHeight > b - > nHeight ) ;
return a < b ;
}
} ;
2016-09-22 09:46:41 +02:00
UniValue getchaintips ( const JSONRPCRequest & request )
2014-08-03 18:12:19 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 0 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2014-08-03 18:12:19 +02:00
" getchaintips \n "
" Return information about all known tips in the block tree, "
" including the main chain as well as orphaned branches. \n "
" \n Result: \n "
" [ \n "
" { \n "
" \" height \" : xxxx, (numeric) height of the chain tip \n "
" \" hash \" : \" xxxx \" , (string) block hash of the tip \n "
" \" branchlen \" : 0 (numeric) zero for main chain \n "
2014-11-27 10:46:55 +01:00
" \" status \" : \" active \" (string) \" active \" for the main chain \n "
2014-08-03 18:12:19 +02:00
" }, \n "
" { \n "
" \" height \" : xxxx, \n "
" \" hash \" : \" xxxx \" , \n "
" \" branchlen \" : 1 (numeric) length of branch connecting the tip to the main chain \n "
2014-11-27 10:46:55 +01:00
" \" status \" : \" xxxx \" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid) \n "
2014-08-03 18:12:19 +02:00
" } \n "
" ] \n "
2014-12-01 20:48:50 +01:00
" Possible values for status: \n "
" 1. \" invalid \" This branch contains at least one invalid block \n "
" 2. \" headers-only \" Not all blocks for this branch are available, but the headers are valid \n "
" 3. \" valid-headers \" All blocks are available for this branch, but they were never fully validated \n "
" 4. \" valid-fork \" This branch is not part of the active chain, but is fully validated \n "
" 5. \" active \" This is the tip of the active main chain, which is certainly valid \n "
2014-08-03 18:12:19 +02:00
" \n Examples: \n "
+ HelpExampleCli ( " getchaintips " , " " )
+ HelpExampleRpc ( " getchaintips " , " " )
) ;
2014-10-19 10:46:17 +02:00
LOCK ( cs_main ) ;
2016-04-18 18:10:47 +02:00
/*
2017-01-04 05:22:19 +01:00
* Idea : the set of chain tips is chainActive . tip , plus orphan blocks which do not have another orphan building off of them .
2016-04-18 18:10:47 +02:00
* Algorithm :
* - Make one pass through mapBlockIndex , picking out the orphan blocks , and also storing a set of the orphan block ' s pprev pointers .
* - Iterate through the orphan blocks . If the block isn ' t pointed to by another orphan , it is a chain tip .
* - add chainActive . Tip ( )
*/
2014-08-03 18:12:19 +02:00
std : : set < const CBlockIndex * , CompareBlocksByHeight > setTips ;
2016-04-18 18:10:47 +02:00
std : : set < const CBlockIndex * > setOrphans ;
std : : set < const CBlockIndex * > setPrevs ;
2017-06-02 03:28:42 +02:00
for ( const std : : pair < const uint256 , CBlockIndex * > & item : mapBlockIndex )
2014-08-03 18:12:19 +02:00
{
2016-04-18 18:10:47 +02:00
if ( ! chainActive . Contains ( item . second ) ) {
setOrphans . insert ( item . second ) ;
setPrevs . insert ( item . second - > pprev ) ;
}
}
for ( std : : set < const CBlockIndex * > : : iterator it = setOrphans . begin ( ) ; it ! = setOrphans . end ( ) ; + + it )
{
if ( setPrevs . erase ( * it ) = = 0 ) {
setTips . insert ( * it ) ;
}
2014-08-03 18:12:19 +02:00
}
2014-11-27 10:46:55 +01:00
// Always report the currently active tip.
setTips . insert ( chainActive . Tip ( ) ) ;
2014-08-03 18:12:19 +02:00
/* Construct the output array. */
2015-05-10 14:48:35 +02:00
UniValue res ( UniValue : : VARR ) ;
2017-06-02 03:18:57 +02:00
for ( const CBlockIndex * block : setTips )
2014-08-03 18:12:19 +02:00
{
2015-05-10 14:48:35 +02:00
UniValue obj ( UniValue : : VOBJ ) ;
2014-08-03 18:12:19 +02:00
obj . push_back ( Pair ( " height " , block - > nHeight ) ) ;
obj . push_back ( Pair ( " hash " , block - > phashBlock - > GetHex ( ) ) ) ;
const int branchLen = block - > nHeight - chainActive . FindFork ( block ) - > nHeight ;
obj . push_back ( Pair ( " branchlen " , branchLen ) ) ;
2017-01-04 05:22:19 +01:00
std : : string status ;
2014-11-27 10:46:55 +01:00
if ( chainActive . Contains ( block ) ) {
// This block is part of the currently active chain.
status = " active " ;
} else if ( block - > nStatus & BLOCK_FAILED_MASK ) {
// This block or one of its ancestors is invalid.
status = " invalid " ;
} else if ( block - > nChainTx = = 0 ) {
// This block cannot be connected because full block data for it or one of its parents is missing.
status = " headers-only " ;
} else if ( block - > IsValid ( BLOCK_VALID_SCRIPTS ) ) {
// This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized.
status = " valid-fork " ;
} else if ( block - > IsValid ( BLOCK_VALID_TREE ) ) {
// The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain.
status = " valid-headers " ;
} else {
// No clue.
status = " unknown " ;
}
obj . push_back ( Pair ( " status " , status ) ) ;
2014-08-03 18:12:19 +02:00
res . push_back ( obj ) ;
}
return res ;
}
2014-08-07 05:58:19 +02:00
2015-08-06 19:38:19 +02:00
UniValue mempoolInfoToJSON ( )
{
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " size " , ( int64_t ) mempool . size ( ) ) ) ;
ret . push_back ( Pair ( " bytes " , ( int64_t ) mempool . GetTotalTxSize ( ) ) ) ;
ret . push_back ( Pair ( " usage " , ( int64_t ) mempool . DynamicMemoryUsage ( ) ) ) ;
2017-08-01 21:17:40 +02:00
size_t maxmempool = gArgs . GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ;
2015-10-23 08:31:27 +02:00
ret . push_back ( Pair ( " maxmempool " , ( int64_t ) maxmempool ) ) ;
ret . push_back ( Pair ( " mempoolminfee " , ValueFromAmount ( mempool . GetMinFee ( maxmempool ) . GetFeePerK ( ) ) ) ) ;
2015-08-06 19:38:19 +02:00
return ret ;
}
2016-09-22 09:46:41 +02:00
UniValue getmempoolinfo ( const JSONRPCRequest & request )
2014-08-07 05:58:19 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 0 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2014-08-07 05:58:19 +02:00
" getmempoolinfo \n "
" \n Returns details on the active state of the TX memory pool. \n "
" \n Result: \n "
" { \n "
2015-11-27 16:53:29 +01:00
" \" size \" : xxxxx, (numeric) Current tx count \n "
2016-09-15 16:46:01 +02:00
" \" bytes \" : xxxxx, (numeric) Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted \n "
2015-11-27 16:53:29 +01:00
" \" usage \" : xxxxx, (numeric) Total memory usage for the mempool \n "
" \" maxmempool \" : xxxxx, (numeric) Maximum memory usage for the mempool \n "
2017-05-29 20:10:13 +02:00
" \" mempoolminfee \" : xxxxx (numeric) Minimum feerate ( " + CURRENCY_UNIT + " per KB) for tx to be accepted \n "
2014-08-07 05:58:19 +02:00
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getmempoolinfo " , " " )
+ HelpExampleRpc ( " getmempoolinfo " , " " )
) ;
2015-08-06 19:38:19 +02:00
return mempoolInfoToJSON ( ) ;
2014-08-07 05:58:19 +02:00
}
2016-09-22 09:46:41 +02:00
UniValue preciousblock ( const JSONRPCRequest & request )
2016-08-26 23:05:09 +02:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-12-09 18:06:42 +01:00
" preciousblock \" blockhash \" \n "
2016-08-26 23:05:09 +02:00
" \n Treats a block as if it were received before others with the same work. \n "
" \n A later preciousblock call can override the effect of an earlier one. \n "
" \n The effects of preciousblock are not retained across restarts. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" blockhash \" (string, required) the hash of the block to mark as precious \n "
2016-08-26 23:05:09 +02:00
" \n Result: \n "
" \n Examples: \n "
+ HelpExampleCli ( " preciousblock " , " \" blockhash \" " )
+ HelpExampleRpc ( " preciousblock " , " \" blockhash \" " )
) ;
2016-09-22 09:46:41 +02:00
std : : string strHash = request . params [ 0 ] . get_str ( ) ;
2016-08-26 23:05:09 +02:00
uint256 hash ( uint256S ( strHash ) ) ;
CBlockIndex * pblockindex ;
{
LOCK ( cs_main ) ;
if ( mapBlockIndex . count ( hash ) = = 0 )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
pblockindex = mapBlockIndex [ hash ] ;
}
CValidationState state ;
PreciousBlock ( state , Params ( ) , pblockindex ) ;
if ( ! state . IsValid ( ) ) {
throw JSONRPCError ( RPC_DATABASE_ERROR , state . GetRejectReason ( ) ) ;
}
return NullUniValue ;
}
2016-09-22 09:46:41 +02:00
UniValue invalidateblock ( const JSONRPCRequest & request )
2014-11-19 09:39:42 +01:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-12-09 18:06:42 +01:00
" invalidateblock \" blockhash \" \n "
2014-11-19 09:39:42 +01:00
" \n Permanently marks a block as invalid, as if it violated a consensus rule. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" blockhash \" (string, required) the hash of the block to mark as invalid \n "
2014-11-19 09:39:42 +01:00
" \n Result: \n "
" \n Examples: \n "
+ HelpExampleCli ( " invalidateblock " , " \" blockhash \" " )
+ HelpExampleRpc ( " invalidateblock " , " \" blockhash \" " )
) ;
2016-09-22 09:46:41 +02:00
std : : string strHash = request . params [ 0 ] . get_str ( ) ;
2014-12-16 14:50:05 +01:00
uint256 hash ( uint256S ( strHash ) ) ;
2014-11-19 09:39:42 +01:00
CValidationState state ;
{
LOCK ( cs_main ) ;
if ( mapBlockIndex . count ( hash ) = = 0 )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
CBlockIndex * pblockindex = mapBlockIndex [ hash ] ;
2016-04-17 09:58:50 +02:00
InvalidateBlock ( state , Params ( ) , pblockindex ) ;
2014-11-19 09:39:42 +01:00
}
if ( state . IsValid ( ) ) {
2016-10-15 20:01:31 +02:00
ActivateBestChain ( state , Params ( ) ) ;
2014-11-19 09:39:42 +01:00
}
if ( ! state . IsValid ( ) ) {
throw JSONRPCError ( RPC_DATABASE_ERROR , state . GetRejectReason ( ) ) ;
}
2015-05-10 13:35:44 +02:00
return NullUniValue ;
2014-11-19 09:39:42 +01:00
}
2016-09-22 09:46:41 +02:00
UniValue reconsiderblock ( const JSONRPCRequest & request )
2014-11-19 09:39:42 +01:00
{
2016-09-22 09:46:41 +02:00
if ( request . fHelp | | request . params . size ( ) ! = 1 )
2017-01-04 05:22:19 +01:00
throw std : : runtime_error (
2016-12-09 18:06:42 +01:00
" reconsiderblock \" blockhash \" \n "
2014-11-19 09:39:42 +01:00
" \n Removes invalidity status of a block and its descendants, reconsider them for activation. \n "
" This can be used to undo the effects of invalidateblock. \n "
" \n Arguments: \n "
2016-12-09 18:06:42 +01:00
" 1. \" blockhash \" (string, required) the hash of the block to reconsider \n "
2014-11-19 09:39:42 +01:00
" \n Result: \n "
" \n Examples: \n "
+ HelpExampleCli ( " reconsiderblock " , " \" blockhash \" " )
+ HelpExampleRpc ( " reconsiderblock " , " \" blockhash \" " )
) ;
2016-09-22 09:46:41 +02:00
std : : string strHash = request . params [ 0 ] . get_str ( ) ;
2014-12-16 14:50:05 +01:00
uint256 hash ( uint256S ( strHash ) ) ;
2014-11-19 09:39:42 +01:00
{
LOCK ( cs_main ) ;
if ( mapBlockIndex . count ( hash ) = = 0 )
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
CBlockIndex * pblockindex = mapBlockIndex [ hash ] ;
2016-05-09 17:26:37 +02:00
ResetBlockFailureFlags ( pblockindex ) ;
2014-11-19 09:39:42 +01:00
}
2016-05-06 18:53:23 +02:00
CValidationState state ;
2016-10-15 20:01:31 +02:00
ActivateBestChain ( state , Params ( ) ) ;
2014-11-19 09:39:42 +01:00
if ( ! state . IsValid ( ) ) {
throw JSONRPCError ( RPC_DATABASE_ERROR , state . GetRejectReason ( ) ) ;
}
2015-05-10 13:35:44 +02:00
return NullUniValue ;
2014-11-19 09:39:42 +01:00
}
2016-03-29 19:43:02 +02:00
2017-02-10 02:24:30 +01:00
UniValue getchaintxstats ( const JSONRPCRequest & request )
{
if ( request . fHelp | | request . params . size ( ) > 2 )
throw std : : runtime_error (
" getchaintxstats ( nblocks blockhash ) \n "
" \n Compute statistics about the total number and rate of transactions in the chain. \n "
" \n Arguments: \n "
" 1. nblocks (numeric, optional) Size of the window in number of blocks (default: one month). \n "
" 2. \" blockhash \" (string, optional) The hash of the block that ends the window. \n "
" \n Result: \n "
" { \n "
" \" time \" : xxxxx, (numeric) The timestamp for the statistics in UNIX format. \n "
" \" txcount \" : xxxxx, (numeric) The total number of transactions in the chain up to that point. \n "
" \" txrate \" : x.xx, (numeric) The average rate of transactions per second in the window. \n "
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getchaintxstats " , " " )
+ HelpExampleRpc ( " getchaintxstats " , " 2016 " )
) ;
const CBlockIndex * pindex ;
int blockcount = 30 * 24 * 60 * 60 / Params ( ) . GetConsensus ( ) . nPowTargetSpacing ; // By default: 1 month
2017-08-15 01:38:18 +02:00
if ( ! request . params [ 0 ] . isNull ( ) ) {
2017-02-10 02:24:30 +01:00
blockcount = request . params [ 0 ] . get_int ( ) ;
}
2017-08-15 01:38:18 +02:00
bool havehash = ! request . params [ 1 ] . isNull ( ) ;
2017-02-10 02:24:30 +01:00
uint256 hash ;
if ( havehash ) {
hash = uint256S ( request . params [ 1 ] . get_str ( ) ) ;
}
{
LOCK ( cs_main ) ;
if ( havehash ) {
auto it = mapBlockIndex . find ( hash ) ;
if ( it = = mapBlockIndex . end ( ) ) {
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Block not found " ) ;
}
pindex = it - > second ;
if ( ! chainActive . Contains ( pindex ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Block is not in main chain " ) ;
}
} else {
pindex = chainActive . Tip ( ) ;
}
}
if ( blockcount < 1 | | blockcount > = pindex - > nHeight ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid block count: should be between 1 and the block's height " ) ;
}
const CBlockIndex * pindexPast = pindex - > GetAncestor ( pindex - > nHeight - blockcount ) ;
int nTimeDiff = pindex - > GetMedianTimePast ( ) - pindexPast - > GetMedianTimePast ( ) ;
int nTxDiff = pindex - > nChainTx - pindexPast - > nChainTx ;
UniValue ret ( UniValue : : VOBJ ) ;
ret . push_back ( Pair ( " time " , ( int64_t ) pindex - > nTime ) ) ;
ret . push_back ( Pair ( " txcount " , ( int64_t ) pindex - > nChainTx ) ) ;
ret . push_back ( Pair ( " txrate " , ( ( double ) nTxDiff ) / nTimeDiff ) ) ;
return ret ;
}
2016-03-29 19:43:02 +02:00
static const CRPCCommand commands [ ] =
2016-09-25 20:44:06 +02:00
{ // category name actor (function) okSafe argNames
// --------------------- ------------------------ ----------------------- ------ ----------
{ " blockchain " , " getblockchaininfo " , & getblockchaininfo , true , { } } ,
2017-02-10 02:24:30 +01:00
{ " blockchain " , " getchaintxstats " , & getchaintxstats , true , { " nblocks " , " blockhash " } } ,
2016-09-25 20:44:06 +02:00
{ " blockchain " , " getbestblockhash " , & getbestblockhash , true , { } } ,
{ " blockchain " , " getblockcount " , & getblockcount , true , { } } ,
2017-04-10 15:28:56 +02:00
{ " blockchain " , " getblock " , & getblock , true , { " blockhash " , " verbosity|verbose " } } ,
2016-12-09 18:06:42 +01:00
{ " blockchain " , " getblockhash " , & getblockhash , true , { " height " } } ,
{ " blockchain " , " getblockheader " , & getblockheader , true , { " blockhash " , " verbose " } } ,
2016-09-25 20:44:06 +02:00
{ " blockchain " , " getchaintips " , & getchaintips , true , { } } ,
{ " blockchain " , " getdifficulty " , & getdifficulty , true , { } } ,
{ " blockchain " , " getmempoolancestors " , & getmempoolancestors , true , { " txid " , " verbose " } } ,
{ " blockchain " , " getmempooldescendants " , & getmempooldescendants , true , { " txid " , " verbose " } } ,
{ " blockchain " , " getmempoolentry " , & getmempoolentry , true , { " txid " } } ,
{ " blockchain " , " getmempoolinfo " , & getmempoolinfo , true , { } } ,
{ " blockchain " , " getrawmempool " , & getrawmempool , true , { " verbose " } } ,
{ " blockchain " , " gettxout " , & gettxout , true , { " txid " , " n " , " include_mempool " } } ,
{ " blockchain " , " gettxoutsetinfo " , & gettxoutsetinfo , true , { } } ,
2016-11-29 18:39:19 +01:00
{ " blockchain " , " pruneblockchain " , & pruneblockchain , true , { " height " } } ,
2016-09-25 20:44:06 +02:00
{ " blockchain " , " verifychain " , & verifychain , true , { " checklevel " , " nblocks " } } ,
2016-12-09 18:06:42 +01:00
{ " blockchain " , " preciousblock " , & preciousblock , true , { " blockhash " } } ,
2016-08-26 23:05:09 +02:00
2016-03-29 19:43:02 +02:00
/* Not shown in help */
2016-12-09 18:06:42 +01:00
{ " hidden " , " invalidateblock " , & invalidateblock , true , { " blockhash " } } ,
{ " hidden " , " reconsiderblock " , & reconsiderblock , true , { " blockhash " } } ,
2016-09-25 20:44:06 +02:00
{ " hidden " , " waitfornewblock " , & waitfornewblock , true , { " timeout " } } ,
2016-12-09 18:06:42 +01:00
{ " hidden " , " waitforblock " , & waitforblock , true , { " blockhash " , " timeout " } } ,
2016-09-25 20:44:06 +02:00
{ " hidden " , " waitforblockheight " , & waitforblockheight , true , { " height " , " timeout " } } ,
2016-03-29 19:43:02 +02:00
} ;
2016-06-07 18:42:42 +02:00
void RegisterBlockchainRPCCommands ( CRPCTable & t )
2016-03-29 19:43:02 +02:00
{
for ( unsigned int vcidx = 0 ; vcidx < ARRAYLEN ( commands ) ; vcidx + + )
2016-06-07 18:42:42 +02:00
t . appendCommand ( commands [ vcidx ] . name , & commands [ vcidx ] ) ;
2016-03-29 19:43:02 +02:00
}