|
|
@ -324,6 +324,7 @@ Value getblocktemplate(const Array& params, bool fHelp) |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
std::string strMode = "template"; |
|
|
|
std::string strMode = "template"; |
|
|
|
|
|
|
|
Value lpval = Value::null; |
|
|
|
if (params.size() > 0) |
|
|
|
if (params.size() > 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
const Object& oparam = params[0].get_obj(); |
|
|
|
const Object& oparam = params[0].get_obj(); |
|
|
@ -336,6 +337,7 @@ Value getblocktemplate(const Array& params, bool fHelp) |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); |
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); |
|
|
|
|
|
|
|
lpval = find_value(oparam, "longpollid"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (strMode != "template") |
|
|
|
if (strMode != "template") |
|
|
@ -347,8 +349,63 @@ Value getblocktemplate(const Array& params, bool fHelp) |
|
|
|
if (IsInitialBlockDownload()) |
|
|
|
if (IsInitialBlockDownload()) |
|
|
|
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); |
|
|
|
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); |
|
|
|
|
|
|
|
|
|
|
|
// Update block
|
|
|
|
|
|
|
|
static unsigned int nTransactionsUpdatedLast; |
|
|
|
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 CBlockIndex* pindexPrev; |
|
|
|
static int64_t nStart; |
|
|
|
static int64_t nStart; |
|
|
|
static CBlockTemplate* pblocktemplate; |
|
|
|
static CBlockTemplate* pblocktemplate; |
|
|
@ -436,6 +493,7 @@ Value getblocktemplate(const Array& params, bool fHelp) |
|
|
|
result.push_back(Pair("transactions", transactions)); |
|
|
|
result.push_back(Pair("transactions", transactions)); |
|
|
|
result.push_back(Pair("coinbaseaux", aux)); |
|
|
|
result.push_back(Pair("coinbaseaux", aux)); |
|
|
|
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue)); |
|
|
|
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("target", hashTarget.GetHex())); |
|
|
|
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); |
|
|
|
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); |
|
|
|
result.push_back(Pair("mutable", aMutable)); |
|
|
|
result.push_back(Pair("mutable", aMutable)); |
|
|
|