Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP22: getblocktemplate #936

merged 2 commits into from Aug 13, 2012
Changes from all commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.


Just for now

@@ -1923,24 +1923,43 @@ Value getwork(const Array& params, bool fHelp)

Value getmemorypool(const Array& params, bool fHelp)
Value getblocktemplate(const Array& params, bool fHelp)
if (fHelp || params.size() > 1)
if (fHelp || params.size() != 1)
throw runtime_error(
"getmemorypool [data]\n"
"If [data] is not specified, returns data needed to construct a block to work on:\n"
"getblocktemplate [params]\n"
"If [params] does not contain a \"data\" key, returns data needed to construct a block to work on:\n"
" \"version\" : block version\n"
" \"previousblockhash\" : hash of current highest block\n"
" \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
" \"coinbaseaux\" : data that should be included in coinbase\n"
" \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
" \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
" \"time\" : timestamp appropriate for next block\n"
" \"target\" : hash target\n"
" \"mintime\" : minimum timestamp appropriate for next block\n"
" \"curtime\" : current timestamp\n"
" \"mutable\" : list of ways the block template may be changed\n"
" \"noncerange\" : range of valid nonces\n"
" \"sigoplimit\" : limit of sigops in blocks\n"
" \"sizelimit\" : limit of block size\n"
" \"bits\" : compressed target of next block\n"
"If [data] is specified, tries to solve the block and returns true if it was successful.");
" \"height\" : height of the next block\n"
"If [params] does contain a \"data\" key, tries to solve the block and returns null if it was successful (and \"rejected\" if not)\n"
"See for full specification.");

if (params.size() == 0)
const Object& oparam = params[0].get_obj();
std::string strMode;
const Value& modeval = find_value(oparam, "mode");
if (modeval.type() == str_type)
strMode = modeval.get_str();
if (find_value(oparam, "data").type() == null_type)
strMode = "template";
strMode = "submit";

if (strMode == "template")
if (vNodes.empty())
throw JSONRPCError(-9, "Bitcoin is not connected!");
@@ -1985,38 +2004,93 @@ Value getmemorypool(const Array& params, bool fHelp)
pblock->nNonce = 0;

Array transactions;
BOOST_FOREACH(CTransaction tx, pblock->vtx) {
map<uint256, int64_t> setTxIndex;
int i = 0;
CTxDB txdb("r");
BOOST_FOREACH (CTransaction& tx, pblock->vtx)
uint256 txHash = tx.GetHash();
setTxIndex[txHash] = i++;

if (tx.IsCoinBase())

Object entry;

ssTx << tx;
entry.push_back(Pair("data", HexStr(ssTx.begin(), ssTx.end())));

transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
entry.push_back(Pair("hash", txHash.GetHex()));

MapPrevTx mapInputs;
map<uint256, CTxIndex> mapUnused;
bool fInvalid = false;
if (tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid))
entry.push_back(Pair("fee", (int64_t)(tx.GetValueIn(mapInputs) - tx.GetValueOut())));

Array deps;
BOOST_FOREACH (MapPrevTx::value_type& inp, mapInputs)
if (setTxIndex.count(inp.first))
entry.push_back(Pair("depends", deps));

int64_t nSigOps = tx.GetLegacySigOpCount();
nSigOps += tx.GetP2SHSigOpCount(mapInputs);
entry.push_back(Pair("sigops", nSigOps));


Object aux;
aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));

uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();

static Array aMutable;
if (aMutable.empty())

Object result;
result.push_back(Pair("version", pblock->nVersion));
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
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("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
result.push_back(Pair("time", (int64_t)pblock->nTime));
result.push_back(Pair("target", hashTarget.GetHex()));
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
result.push_back(Pair("curtime", (int64_t)pblock->nTime));
result.push_back(Pair("bits", HexBits(pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));

return result;
if (strMode == "submit")
// Parse parameters
CDataStream ssBlock(ParseHex(params[0].get_str()), SER_NETWORK, PROTOCOL_VERSION);
CDataStream ssBlock(ParseHex(find_value(oparam, "data").get_str()), SER_NETWORK, PROTOCOL_VERSION);
CBlock pblock;
ssBlock >> pblock;

return ProcessBlock(NULL, &pblock);
bool fAccepted = ProcessBlock(NULL, &pblock);

return fAccepted ? Value::null : "rejected";

throw JSONRPCError(-8, "Invalid mode");

Value getrawmempool(const Array& params, bool fHelp)
@@ -2128,7 +2202,7 @@ static const CRPCCommand vRPCCommands[] =
{ "getwork", &getwork, true },
{ "listaccounts", &listaccounts, false },
{ "settxfee", &settxfee, false },
{ "getmemorypool", &getmemorypool, true },
{ "getblocktemplate", &getblocktemplate, true },
{ "listsinceblock", &listsinceblock, false },
{ "dumpprivkey", &dumpprivkey, false },
{ "importprivkey", &importprivkey, false },
@@ -2736,7 +2810,7 @@ void JSONRequest::parse(const Value& valRequest)
if (valMethod.type() != str_type)
throw JSONRPCError(-32600, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getwork" && strMethod != "getmemorypool")
if (strMethod != "getwork" && strMethod != "getblocktemplate")
printf("ThreadRPCServer method=%s\n", strMethod.c_str());

// Parse params
@@ -3015,6 +3089,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getblocktemplate" && n > 0) ConvertTo<Object>(params[0]);
if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "sendmany" && n > 1) ConvertTo<Object>(params[1]);
if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.