aboutsummaryrefslogtreecommitdiff
path: root/src/bitcoinrpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bitcoinrpc.cpp')
-rw-r--r--src/bitcoinrpc.cpp128
1 files changed, 100 insertions, 28 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 3af298a58b..208c830aa9 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -1881,7 +1881,7 @@ Value getwork(const Array& params, bool fHelp)
// Save
mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
- // Prebuild hash buffers
+ // Pre-build hash buffers
char pmidstate[32];
char pdata[128];
char phash1[64];
@@ -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 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())
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) {
- if(tx.IsCoinBase())
+ 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())
continue;
+ Object entry;
+
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
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))
+ 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(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;
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;
}
else
+ 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)
@@ -2047,10 +2121,7 @@ Value getblockhash(const Array& params, bool fHelp)
if (nHeight < 0 || nHeight > nBestHeight)
throw runtime_error("Block number out of range.");
- CBlock block;
- CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
- while (pblockindex->nHeight > nHeight)
- pblockindex = pblockindex->pprev;
+ CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
return pblockindex->phashBlock->GetHex();
}
@@ -2131,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 },
@@ -2194,7 +2265,7 @@ string rfc1123Time()
time(&now);
struct tm* now_gmt = gmtime(&now);
string locale(setlocale(LC_TIME, NULL));
- setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
+ setlocale(LC_TIME, "C"); // we want POSIX (aka "C") weekday/month strings
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
setlocale(LC_TIME, locale.c_str());
return string(buffer);
@@ -2388,7 +2459,7 @@ bool ClientAllowed(const boost::asio::ip::address& address)
if (address == asio::ip::address_v4::loopback()
|| address == asio::ip::address_v6::loopback()
|| (address.is_v4()
- // Chech whether IPv4 addresses match 127.0.0.0/8 (loopback subnet)
+ // Check whether IPv4 addresses match 127.0.0.0/8 (loopback subnet)
&& (address.to_v4().to_ulong() & 0xff000000) == 0x7f000000))
return true;
@@ -2565,7 +2636,7 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
{
vnThreadsRunning[THREAD_RPCLISTENER]++;
- // Immediately start accepting new connections, except when we're canceled or our socket is closed.
+ // Immediately start accepting new connections, except when we're cancelled or our socket is closed.
if (error != asio::error::operation_aborted
&& acceptor->is_open())
RPCListen(acceptor, context, fUseSSL);
@@ -2698,7 +2769,7 @@ void ThreadRPCServer2(void* parg)
}
catch(boost::system::system_error &e)
{
- uiInterface.ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
+ uiInterface.ThreadSafeMessageBox(strprintf(_("An error occurred while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
_("Error"), CClientUIInterface::OK | CClientUIInterface::MODAL);
StartShutdown();
return;
@@ -2739,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
@@ -3018,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]);
@@ -3105,7 +3177,7 @@ int CommandLineRPC(int argc, char *argv[])
int main(int argc, char *argv[])
{
#ifdef _MSC_VER
- // Turn off microsoft heap dump noise
+ // Turn off Microsoft heap dump noise
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
#endif