Skip to content

Commit

Permalink
Merge pull request #2205 from jamescowens/rpc_getblocksbatch
Browse files Browse the repository at this point in the history
rpc: Implement getblocksbatch
  • Loading branch information
jamescowens authored Jun 30, 2021
2 parents 56e7928 + afad60e commit df254c3
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 0 deletions.
124 changes: 124 additions & 0 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,130 @@ UniValue getblockbynumber(const UniValue& params, bool fHelp)
return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
}

UniValue getblocksbatch(const UniValue& params, bool fHelp)
{
g_timer.InitTimer(__func__, LogInstance().WillLogCategory(BCLog::LogFlags::RPC));

if (fHelp || params.size() < 2 || params.size() > 3)
{
throw runtime_error(
"getblocksbatch <starting block number or hash> <number of blocks> [bool:txinfo]\n"
"\n"
"<starting block number or hash> the block number or hash for the block at the\n"
"start of the batch\n"
"\n"
"<number of blocks> the number of blocks to return in the batch, limited to 1000"
"\n"
"[bool:txinfo] optional to print more detailed tx info\n"
"\n"
"Returns a JSON array with details of the requested blocks starting with\n"
"the given block-number or hash.\n");
}

UniValue result(UniValue::VOBJ);
UniValue blocks(UniValue::VARR);

int nHeight = 0;
uint256 hash;
bool block_hash_provided = false;

// Validate parameters.
try
{
// Have to do it this way, because the rpc param 0 must be left out of the special parameter handling in client.cpp.
nHeight = boost::lexical_cast<int>(params[0].get_str());
}
catch (const boost::bad_lexical_cast& e)
{
std::string strHash = params[0].get_str();
hash = uint256S(strHash);
block_hash_provided = true;
}
catch (...)
{
throw JSONRPCError(RPC_INVALID_PARAMETER, "Either a valid block number or block hash must be provided.");
}

if (!block_hash_provided)
{
if (nHeight < 0 || nHeight > nBestHeight)
{
throw JSONRPCError(RPC_INVALID_PARAMETER, "Starting block number out of range");
}
}
else
{
if (mapBlockIndex.count(hash) == 0)
{
throw JSONRPCError(RPC_INVALID_PARAMETER, "Starting block for batch not found.");
}
}

int batch_size = params[1].get_int();
if (batch_size < 1 || batch_size > 1000)
{
throw JSONRPCError(RPC_INVALID_PARAMETER, "Batch size must be between 1 and 1000, inclusive.");
}

bool transaction_details = false;
if (params.size() > 2) transaction_details = params[2].get_bool();

LOCK(cs_main);

g_timer.GetTimes("Finished validating parameters", __func__);

CBlockIndex* pblockindex_head = nullptr;
CBlockIndex* pblockindex = nullptr;

// Find the starting block's index entry point by either rewinding from the head (if the block number was
// provided), or directly from the mapBlockIndex, if the hash was provided.

// Select the block index for the head of the chain.
pblockindex_head = mapBlockIndex[hashBestChain];

if (!block_hash_provided)
{
pblockindex = pblockindex_head;

// Rewind to the block corresponding to the specified height.
while (pblockindex->nHeight > nHeight)
{
pblockindex = pblockindex->pprev;
}

}
else
{
pblockindex = mapBlockIndex[hash];
}

g_timer.GetTimes("Finished finding starting block", __func__);

int i = 0;
while (i < batch_size)
{
CBlock block;
if (!block.ReadFromDisk(pblockindex, true))
{
throw runtime_error("Error reading block from specified batch.");
}

blocks.push_back(blockToJSON(block, pblockindex, transaction_details));
++i;

if (pblockindex == pblockindex_head) break;

pblockindex = pblockindex->pnext;
}

result.pushKV("block_count", i);
result.pushKV("blocks", blocks);

g_timer.GetTimes("Finished populating result for block batch", __func__);

return result;
}

UniValue backupprivatekeys(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getblock" , 1 },
{ "getblockbynumber" , 0 },
{ "getblockbynumber" , 1 },
{ "getblocksbatch" , 1 },
{ "getblocksbatch" , 2 },
{ "getblockhash" , 0 },
{ "setban" , 2 },
{ "setban" , 3 },
Expand Down
1 change: 1 addition & 0 deletions src/rpc/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ static const CRPCCommand vRPCCommands[] =
{ "getbestblockhash", &getbestblockhash, cat_network },
{ "getblock", &getblock, cat_network },
{ "getblockbynumber", &getblockbynumber, cat_network },
{ "getblocksbatch", &getblocksbatch, cat_network },
{ "getblockcount", &getblockcount, cat_network },
{ "getblockhash", &getblockhash, cat_network },
{ "getburnreport", &getburnreport, cat_network },
Expand Down
1 change: 1 addition & 0 deletions src/rpc/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp);
extern UniValue getbestblockhash(const UniValue& params, bool fHelp);
extern UniValue getblock(const UniValue& params, bool fHelp);
extern UniValue getblockbynumber(const UniValue& params, bool fHelp);
extern UniValue getblocksbatch(const UniValue& params, bool fHelp);
extern UniValue getblockchaininfo(const UniValue& params, bool fHelp);
extern UniValue getblockcount(const UniValue& params, bool fHelp);
extern UniValue getblockhash(const UniValue& params, bool fHelp);
Expand Down

0 comments on commit df254c3

Please sign in to comment.