|
|
|
@ -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));
|
|
|
|
|