diff options
Diffstat (limited to 'src/bitcoinrpc.cpp')
-rw-r--r-- | src/bitcoinrpc.cpp | 128 |
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 |