|
|
|
@ -26,8 +26,20 @@
@@ -26,8 +26,20 @@
|
|
|
|
|
|
|
|
|
|
#include <boost/thread/thread.hpp> // boost::thread::interrupt |
|
|
|
|
|
|
|
|
|
#include <mutex> |
|
|
|
|
#include <condition_variable> |
|
|
|
|
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); |
|
|
|
|
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); |
|
|
|
|
|
|
|
|
@ -168,6 +180,138 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp)
@@ -168,6 +180,138 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp)
|
|
|
|
|
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" |
|
|
|
|
"\nWaits for a specific new block and returns useful info about it.\n" |
|
|
|
|
"\nReturns the current block on timeout or exit.\n" |
|
|
|
|
"\nArguments:\n" |
|
|
|
|
"1. timeout (milliseconds) (int, optional, default=false)\n" |
|
|
|
|
"\nResult::\n" |
|
|
|
|
"{ (json object)\n" |
|
|
|
|
" \"hash\" : { (string) The blockhash\n" |
|
|
|
|
" \"height\" : { (int) Block height\n" |
|
|
|
|
"}\n" |
|
|
|
|
"\nExamples\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" |
|
|
|
|
"\nWaits for a specific new block and returns useful info about it.\n" |
|
|
|
|
"\nReturns the current block on timeout or exit.\n" |
|
|
|
|
"\nArguments:\n" |
|
|
|
|
"1. blockhash to wait for (string)\n" |
|
|
|
|
"2. timeout (milliseconds) (int, optional, default=false)\n" |
|
|
|
|
"\nResult::\n" |
|
|
|
|
"{ (json object)\n" |
|
|
|
|
" \"hash\" : { (string) The blockhash\n" |
|
|
|
|
" \"height\" : { (int) Block height\n" |
|
|
|
|
"}\n" |
|
|
|
|
"\nExamples\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" |
|
|
|
|
"\nWaits for (at least) block height and returns the height and hash\n" |
|
|
|
|
"\nof the current tip.\n" |
|
|
|
|
"\nReturns the current block on timeout or exit.\n" |
|
|
|
|
"\nArguments:\n" |
|
|
|
|
"1. block height to wait for (int)\n" |
|
|
|
|
"2. timeout (milliseconds) (int, optional, default=false)\n" |
|
|
|
|
"\nResult::\n" |
|
|
|
|
"{ (json object)\n" |
|
|
|
|
" \"hash\" : { (string) The blockhash\n" |
|
|
|
|
" \"height\" : { (int) Block height\n" |
|
|
|
|
"}\n" |
|
|
|
|
"\nExamples\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) |
|
|
|
|
{ |
|
|
|
|
if (fHelp || params.size() != 0) |
|
|
|
@ -1203,6 +1347,9 @@ static const CRPCCommand commands[] =
@@ -1203,6 +1347,9 @@ static const CRPCCommand commands[] =
|
|
|
|
|
/* Not shown in help */ |
|
|
|
|
{ "hidden", "invalidateblock", &invalidateblock, true }, |
|
|
|
|
{ "hidden", "reconsiderblock", &reconsiderblock, true }, |
|
|
|
|
{ "hidden", "waitfornewblock", &waitfornewblock, true }, |
|
|
|
|
{ "hidden", "waitforblock", &waitforblock, true }, |
|
|
|
|
{ "hidden", "waitforblockheight", &waitforblockheight, true }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
void RegisterBlockchainRPCCommands(CRPCTable &t) |
|
|
|
|