|
|
@ -1862,24 +1862,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( |
|
|
|
throw runtime_error( |
|
|
|
"getmemorypool [data]\n" |
|
|
|
"getblocktemplate [params]\n" |
|
|
|
"If [data] is not specified, returns data needed to construct a block to work on:\n" |
|
|
|
"If [params] does not contain a \"data\" key, returns data needed to construct a block to work on:\n" |
|
|
|
" \"version\" : block version\n" |
|
|
|
" \"version\" : block version\n" |
|
|
|
" \"previousblockhash\" : hash of current highest block\n" |
|
|
|
" \"previousblockhash\" : hash of current highest block\n" |
|
|
|
" \"transactions\" : contents of non-coinbase transactions that should be included in the next 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" |
|
|
|
" \"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" |
|
|
|
" \"target\" : hash target\n" |
|
|
|
" \"time\" : timestamp appropriate for next block\n" |
|
|
|
|
|
|
|
" \"mintime\" : minimum timestamp appropriate for next block\n" |
|
|
|
" \"mintime\" : minimum timestamp appropriate for next block\n" |
|
|
|
" \"curtime\" : current timestamp\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" |
|
|
|
" \"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 https://en.bitcoin.it/wiki/BIP_0022 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(); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
if (find_value(oparam, "data").type() == null_type) |
|
|
|
|
|
|
|
strMode = "template"; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
strMode = "submit"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (strMode == "template") |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (vNodes.empty()) |
|
|
|
if (vNodes.empty()) |
|
|
|
throw JSONRPCError(-9, "Bitcoin is not connected!"); |
|
|
|
throw JSONRPCError(-9, "Bitcoin is not connected!"); |
|
|
@ -1914,38 +1933,93 @@ Value getmemorypool(const Array& params, bool fHelp) |
|
|
|
pblock->nNonce = 0; |
|
|
|
pblock->nNonce = 0; |
|
|
|
|
|
|
|
|
|
|
|
Array transactions; |
|
|
|
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()) |
|
|
|
if (tx.IsCoinBase()) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
CDataStream ssTx; |
|
|
|
Object entry; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); |
|
|
|
ssTx << tx; |
|
|
|
ssTx << tx; |
|
|
|
|
|
|
|
entry.push_back(Pair("data", 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)) |
|
|
|
|
|
|
|
deps.push_back(setTxIndex[inp.first]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
entry.push_back(Pair("depends", deps)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int64_t nSigOps = tx.GetLegacySigOpCount(); |
|
|
|
|
|
|
|
nSigOps += tx.GetP2SHSigOpCount(mapInputs); |
|
|
|
|
|
|
|
entry.push_back(Pair("sigops", nSigOps)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
transactions.push_back(HexStr(ssTx.begin(), ssTx.end())); |
|
|
|
transactions.push_back(entry); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
aMutable.push_back("time"); |
|
|
|
|
|
|
|
aMutable.push_back("transactions"); |
|
|
|
|
|
|
|
aMutable.push_back("prevblock"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Object result; |
|
|
|
Object result; |
|
|
|
result.push_back(Pair("version", pblock->nVersion)); |
|
|
|
result.push_back(Pair("version", pblock->nVersion)); |
|
|
|
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); |
|
|
|
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); |
|
|
|
result.push_back(Pair("transactions", transactions)); |
|
|
|
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("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("target", hashTarget.GetHex())); |
|
|
|
result.push_back(Pair("time", (int64_t)pblock->nTime)); |
|
|
|
|
|
|
|
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); |
|
|
|
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("bits", HexBits(pblock->nBits))); |
|
|
|
|
|
|
|
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
|
|
|
|
if (strMode == "submit") |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Parse parameters
|
|
|
|
// Parse parameters
|
|
|
|
CDataStream ssBlock(ParseHex(params[0].get_str())); |
|
|
|
CDataStream ssBlock(ParseHex(find_value(oparam, "data").get_str()), SER_NETWORK, PROTOCOL_VERSION); |
|
|
|
CBlock pblock; |
|
|
|
CBlock pblock; |
|
|
|
ssBlock >> pblock; |
|
|
|
ssBlock >> pblock; |
|
|
|
|
|
|
|
|
|
|
|
return ProcessBlock(NULL, &pblock); |
|
|
|
bool fAccepted = ProcessBlock(NULL, &pblock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return fAccepted ? Value::null : "rejected"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
throw JSONRPCError(-8, "Invalid mode"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Value getblockhash(const Array& params, bool fHelp) |
|
|
|
Value getblockhash(const Array& params, bool fHelp) |
|
|
@ -2044,7 +2118,7 @@ pair<string, rpcfn_type> pCallTable[] = |
|
|
|
make_pair("getwork", &getwork), |
|
|
|
make_pair("getwork", &getwork), |
|
|
|
make_pair("listaccounts", &listaccounts), |
|
|
|
make_pair("listaccounts", &listaccounts), |
|
|
|
make_pair("settxfee", &settxfee), |
|
|
|
make_pair("settxfee", &settxfee), |
|
|
|
make_pair("getmemorypool", &getmemorypool), |
|
|
|
make_pair("getblocktemplate", &getblocktemplate), |
|
|
|
make_pair("listsinceblock", &listsinceblock), |
|
|
|
make_pair("listsinceblock", &listsinceblock), |
|
|
|
make_pair("dumpprivkey", &dumpprivkey), |
|
|
|
make_pair("dumpprivkey", &dumpprivkey), |
|
|
|
make_pair("importprivkey", &importprivkey) |
|
|
|
make_pair("importprivkey", &importprivkey) |
|
|
@ -2074,7 +2148,7 @@ string pAllowInSafeMode[] = |
|
|
|
"walletlock", |
|
|
|
"walletlock", |
|
|
|
"validateaddress", |
|
|
|
"validateaddress", |
|
|
|
"getwork", |
|
|
|
"getwork", |
|
|
|
"getmemorypool", |
|
|
|
"getblocktemplate", |
|
|
|
}; |
|
|
|
}; |
|
|
|
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0])); |
|
|
|
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0])); |
|
|
|
|
|
|
|
|
|
|
@ -2499,7 +2573,7 @@ void ThreadRPCServer2(void* parg) |
|
|
|
if (valMethod.type() != str_type) |
|
|
|
if (valMethod.type() != str_type) |
|
|
|
throw JSONRPCError(-32600, "Method must be a string"); |
|
|
|
throw JSONRPCError(-32600, "Method must be a string"); |
|
|
|
string strMethod = valMethod.get_str(); |
|
|
|
string strMethod = valMethod.get_str(); |
|
|
|
if (strMethod != "getwork" && strMethod != "getmemorypool") |
|
|
|
if (strMethod != "getwork" && strMethod != "getblocktemplate") |
|
|
|
printf("ThreadRPCServer method=%s\n", strMethod.c_str()); |
|
|
|
printf("ThreadRPCServer method=%s\n", strMethod.c_str()); |
|
|
|
|
|
|
|
|
|
|
|
// Parse params
|
|
|
|
// Parse params
|
|
|
@ -2681,6 +2755,7 @@ int CommandLineRPC(int argc, char *argv[]) |
|
|
|
if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]); |
|
|
|
if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]); |
|
|
|
if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]); |
|
|
|
if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]); |
|
|
|
if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]); |
|
|
|
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 == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]); |
|
|
|
if (strMethod == "sendmany" && n > 1) |
|
|
|
if (strMethod == "sendmany" && n > 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|