From c5cf6e2a359f71238f6f2fc27e2df02471aa2a35 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Sun, 23 Aug 2015 13:13:04 +0300 Subject: [PATCH] RPC: Add dumpblock and dumpblockbynumber methods --- src/bitcoinrpc.cpp | 3 ++ src/bitcoinrpc.h | 2 + src/rpcblockchain.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index c09be24..1f55825 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -280,6 +280,8 @@ static const CRPCCommand vRPCCommands[] = { "getrawmempool", &getrawmempool, true, false }, { "getblock", &getblock, false, false }, { "getblockbynumber", &getblockbynumber, false, false }, + { "dumpblock", &dumpblock, false, false }, + { "dumpblockbynumber", &dumpblockbynumber, false, false }, { "getblockhash", &getblockhash, false, false }, { "gettransaction", &gettransaction, false, false }, { "listtransactions", &listtransactions, false, false }, @@ -1199,6 +1201,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 1) ConvertTo(params[1]); if (strMethod == "getblock" && n > 1) ConvertTo(params[1]); if (strMethod == "getblockbynumber" && n > 0) ConvertTo(params[0]); + if (strMethod == "dumpblockbynumber" && n > 0) ConvertTo(params[0]); if (strMethod == "getblockbynumber" && n > 1) ConvertTo(params[1]); if (strMethod == "getblockhash" && n > 0) ConvertTo(params[0]); if (strMethod == "move" && n > 2) ConvertTo(params[2]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 83e8eed..8a61329 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -223,6 +223,8 @@ extern json_spirit::Value getrawmempool(const json_spirit::Array& params, bool f extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getblockbynumber(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value dumpblock(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value dumpblockbynumber(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getcheckpoint(const json_spirit::Array& params, bool fHelp); #endif diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index e4d9835..83ca8fd 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -5,6 +5,10 @@ #include "main.h" #include "bitcoinrpc.h" +#include +#include +#include +#include using namespace json_spirit; using namespace std; @@ -265,14 +269,93 @@ Value getblockbynumber(const Array& params, bool fHelp) while (pblockindex->nHeight > nHeight) pblockindex = pblockindex->pprev; - uint256 hash = *pblockindex->phashBlock; - - pblockindex = mapBlockIndex[hash]; + pblockindex = mapBlockIndex[*pblockindex->phashBlock]; block.ReadFromDisk(pblockindex, true); return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); } +bool ExportBlock(const string& strBlockHash, const CDataStream& ssBlock) +{ + boost::filesystem::path pathDest = GetDataDir() / strBlockHash; + if (boost::filesystem::is_directory(pathDest)) + pathDest /= strBlockHash; + + try { + boost::iostreams::stream_buffer buf(pathDest.c_str()); + ostream exportStream(&buf); + exportStream << HexStr(ssBlock.begin(), ssBlock.end()); + exportStream.flush(); + + printf("Successfully exported block to %s\n", pathDest.string().c_str()); + return true; + } catch(const boost::filesystem::filesystem_error &e) { + printf("error exporting the block data %s (%s)\n", pathDest.string().c_str(), e.what()); + return false; + } +} + + +Value dumpblock(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "dumpblock [destination]\n" + "Returns serialized contents of a block with given block-hash."); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + block.ReadFromDisk(pblockindex, true); + + CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); + ssBlock << block; + + if (params.size() > 1) + { + return ExportBlock(params[1].get_str(), ssBlock); + } + + return HexStr(ssBlock.begin(), ssBlock.end()); +} + + +Value dumpblockbynumber(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "dumpblockbynumber [destination]\n" + "Returns serialized contents of a block with given block-number."); + + int nHeight = params[0].get_int(); + 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; + + pblockindex = mapBlockIndex[*pblockindex->phashBlock]; + block.ReadFromDisk(pblockindex, true); + + CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); + ssBlock << block; + + if (params.size() > 1) + { + return ExportBlock(params[1].get_str(), ssBlock); + } + + return HexStr(ssBlock.begin(), ssBlock.end()); +} + + // get information of sync-checkpoint Value getcheckpoint(const Array& params, bool fHelp) { -- 1.7.1