@ -26,8 +26,20 @@
# include <boost/thread/thread.hpp> // boost::thread::interrupt
# include <boost/thread/thread.hpp> // boost::thread::interrupt
# include <mutex>
# include <condition_variable>
using namespace std ;
using namespace std ;
struct CUpdatedBlock
{
uint256 hash ;
int height ;
} ;
static std : : mutex cs_blockchange ;
static std : : condition_variable cond_blockchange ;
static CUpdatedBlock latestblock ;
extern void TxToJSON ( const CTransaction & tx , const uint256 hashBlock , UniValue & entry ) ;
extern void TxToJSON ( const CTransaction & tx , const uint256 hashBlock , UniValue & entry ) ;
void ScriptPubKeyToJSON ( const CScript & scriptPubKey , UniValue & out , bool fIncludeHex ) ;
void ScriptPubKeyToJSON ( const CScript & scriptPubKey , UniValue & out , bool fIncludeHex ) ;
@ -168,6 +180,138 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp)
return chainActive . Tip ( ) - > GetBlockHash ( ) . GetHex ( ) ;
return chainActive . Tip ( ) - > GetBlockHash ( ) . GetHex ( ) ;
}
}
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 ;
}
cond_blockchange . notify_all ( ) ;
}
UniValue waitfornewblock ( const UniValue & params , bool fHelp )
{
if ( fHelp | | params . size ( ) > 1 )
throw runtime_error (
" waitfornewblock \n "
" \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 "
" 1. timeout (milliseconds) (int, optional, default=false) \n "
" \n Result:: \n "
" { (json object) \n "
" \" hash \" : { (string) The blockhash \n "
" \" height \" : { (int) Block height \n "
" } \n "
" \n Examples \n "
+ HelpExampleCli ( " waitfornewblock " , " 1000 " )
+ HelpExampleRpc ( " waitfornewblock " , " 1000 " )
) ;
int timeout = 0 ;
if ( params . size ( ) > 0 )
timeout = params [ 0 ] . get_int ( ) ;
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 ;
}
UniValue waitforblock ( const UniValue & params , bool fHelp )
{
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 2 )
throw runtime_error (
" waitforblock \n "
" \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 "
" 1. blockhash to wait for (string) \n "
" 2. timeout (milliseconds) (int, optional, default=false) \n "
" \n Result:: \n "
" { (json object) \n "
" \" hash \" : { (string) The blockhash \n "
" \" height \" : { (int) Block height \n "
" } \n "
" \n Examples \n "
+ HelpExampleCli ( " waitforblock " , " \" 0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862 \" , 1000 " )
+ HelpExampleRpc ( " waitforblock " , " \" 0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862 \" , 1000 " )
) ;
int timeout = 0 ;
uint256 hash = uint256S ( params [ 0 ] . get_str ( ) ) ;
if ( params . size ( ) > 1 )
timeout = params [ 1 ] . get_int ( ) ;
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 ;
}
UniValue waitforblockheight ( const UniValue & params , bool fHelp )
{
if ( fHelp | | params . size ( ) < 1 | | params . size ( ) > 2 )
throw runtime_error (
" waitforblock \n "
" \n Waits for (at least) block height and returns the height and hash \n "
" \n of the current tip. \n "
" \n Returns the current block on timeout or exit. \n "
" \n Arguments: \n "
" 1. block height to wait for (int) \n "
" 2. timeout (milliseconds) (int, optional, default=false) \n "
" \n Result:: \n "
" { (json object) \n "
" \" hash \" : { (string) The blockhash \n "
" \" height \" : { (int) Block height \n "
" } \n "
" \n Examples \n "
+ HelpExampleCli ( " waitforblockheight " , " \" 100 \" , 1000 " )
+ HelpExampleRpc ( " waitforblockheight " , " \" 100 \" , 1000 " )
) ;
int timeout = 0 ;
int height = params [ 0 ] . get_int ( ) ;
if ( params . size ( ) > 1 )
timeout = params [ 1 ] . get_int ( ) ;
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 ;
}
UniValue getdifficulty ( const UniValue & params , bool fHelp )
UniValue getdifficulty ( const UniValue & params , bool fHelp )
{
{
if ( fHelp | | params . size ( ) ! = 0 )
if ( fHelp | | params . size ( ) ! = 0 )
@ -1203,6 +1347,9 @@ static const CRPCCommand commands[] =
/* Not shown in help */
/* Not shown in help */
{ " hidden " , " invalidateblock " , & invalidateblock , true } ,
{ " hidden " , " invalidateblock " , & invalidateblock , true } ,
{ " hidden " , " reconsiderblock " , & reconsiderblock , true } ,
{ " hidden " , " reconsiderblock " , & reconsiderblock , true } ,
{ " hidden " , " waitfornewblock " , & waitfornewblock , true } ,
{ " hidden " , " waitforblock " , & waitforblock , true } ,
{ " hidden " , " waitforblockheight " , & waitforblockheight , true } ,
} ;
} ;
void RegisterBlockchainRPCCommands ( CRPCTable & t )
void RegisterBlockchainRPCCommands ( CRPCTable & t )