getblocktemplate: longpolling support
This commit is contained in:
committed by
Wladimir J. van der Laan
parent
f0fc81a083
commit
ff6a7af154
@@ -324,6 +324,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
|
||||
);
|
||||
|
||||
std::string strMode = "template";
|
||||
Value lpval = Value::null;
|
||||
if (params.size() > 0)
|
||||
{
|
||||
const Object& oparam = params[0].get_obj();
|
||||
@@ -336,6 +337,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
|
||||
}
|
||||
else
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
||||
lpval = find_value(oparam, "longpollid");
|
||||
}
|
||||
|
||||
if (strMode != "template")
|
||||
@@ -347,8 +349,63 @@ Value getblocktemplate(const Array& params, bool fHelp)
|
||||
if (IsInitialBlockDownload())
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
|
||||
|
||||
// Update block
|
||||
static unsigned int nTransactionsUpdatedLast;
|
||||
|
||||
if (lpval.type() != null_type)
|
||||
{
|
||||
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
|
||||
uint256 hashWatchedChain;
|
||||
boost::system_time checktxtime;
|
||||
unsigned int nTransactionsUpdatedLastLP;
|
||||
|
||||
if (lpval.type() == str_type)
|
||||
{
|
||||
// Format: <hashBestChain><nTransactionsUpdatedLast>
|
||||
std::string lpstr = lpval.get_str();
|
||||
|
||||
hashWatchedChain.SetHex(lpstr.substr(0, 64));
|
||||
nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
|
||||
hashWatchedChain = chainActive.Tip()->GetBlockHash();
|
||||
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
|
||||
}
|
||||
|
||||
// Release the wallet and main lock while waiting
|
||||
#ifdef ENABLE_WALLET
|
||||
if(pwalletMain)
|
||||
LEAVE_CRITICAL_SECTION(pwalletMain->cs_wallet);
|
||||
#endif
|
||||
LEAVE_CRITICAL_SECTION(cs_main);
|
||||
{
|
||||
checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
|
||||
|
||||
boost::unique_lock<boost::mutex> lock(csBestBlock);
|
||||
while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
|
||||
{
|
||||
if (!cvBlockChange.timed_wait(lock, checktxtime))
|
||||
{
|
||||
// Timeout: Check transactions for update
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
||||
break;
|
||||
checktxtime += boost::posix_time::seconds(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
ENTER_CRITICAL_SECTION(cs_main);
|
||||
#ifdef ENABLE_WALLET
|
||||
if(pwalletMain)
|
||||
ENTER_CRITICAL_SECTION(pwalletMain->cs_wallet);
|
||||
#endif
|
||||
|
||||
if (!IsRPCRunning())
|
||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
|
||||
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
|
||||
}
|
||||
|
||||
// Update block
|
||||
static CBlockIndex* pindexPrev;
|
||||
static int64_t nStart;
|
||||
static CBlockTemplate* pblocktemplate;
|
||||
@@ -436,6 +493,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
|
||||
result.push_back(Pair("transactions", transactions));
|
||||
result.push_back(Pair("coinbaseaux", aux));
|
||||
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
|
||||
result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
|
||||
result.push_back(Pair("target", hashTarget.GetHex()));
|
||||
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
|
||||
result.push_back(Pair("mutable", aMutable));
|
||||
|
||||
Reference in New Issue
Block a user