Skip to content

Commit a3f0306

Browse files
UdjinM6codablock
authored andcommitted
Implement getmerkleblocks rpc (#2894)
1 parent a6eee07 commit a3f0306

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

src/rpc/blockchain.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,86 @@ UniValue getblockheaders(const JSONRPCRequest& request)
837837
return arrHeaders;
838838
}
839839

840+
UniValue getmerkleblocks(const JSONRPCRequest& request)
841+
{
842+
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
843+
throw std::runtime_error(
844+
"getmerkleblocks \"filter\" \"hash\" ( count )\n"
845+
"\nReturns an array of items with information about <count> merkleblocks starting from <hash> which match <filter>.\n"
846+
"\nArguments:\n"
847+
"1. \"filter\" (string, required) The hex encoded bloom filter\n"
848+
"2. \"hash\" (string, required) The block hash\n"
849+
"3. count (numeric, optional, default/max=" + strprintf("%s", MAX_HEADERS_RESULTS) +")\n"
850+
"\nResult (for verbose=false):\n"
851+
"[\n"
852+
" \"data\", (string) A string that is serialized, hex-encoded data for a merkleblock.\n"
853+
" ...\n"
854+
"]\n"
855+
"\nExamples:\n"
856+
+ HelpExampleCli("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000")
857+
+ HelpExampleRpc("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000")
858+
);
859+
860+
LOCK(cs_main);
861+
862+
CBloomFilter filter;
863+
std::string strFilter = request.params[0].get_str();
864+
CDataStream ssBloomFilter(ParseHex(strFilter), SER_NETWORK, PROTOCOL_VERSION);
865+
ssBloomFilter >> filter;
866+
if (!filter.IsWithinSizeConstraints()) {
867+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Filter is not within size constraints");
868+
}
869+
filter.UpdateEmptyFull();
870+
871+
std::string strHash = request.params[1].get_str();
872+
uint256 hash(uint256S(strHash));
873+
874+
if (mapBlockIndex.count(hash) == 0) {
875+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
876+
}
877+
878+
int nCount = MAX_HEADERS_RESULTS;
879+
if (request.params.size() > 2)
880+
nCount = request.params[2].get_int();
881+
882+
if (nCount <= 0 || nCount > (int)MAX_HEADERS_RESULTS) {
883+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Count is out of range");
884+
}
885+
886+
CBlock block;
887+
CBlockIndex* pblockindex = mapBlockIndex[hash];
888+
889+
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) {
890+
throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
891+
}
892+
893+
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
894+
// Block not found on disk. This could be because we have the block
895+
// header in our index but don't have the block (for example if a
896+
// non-whitelisted node sends us an unrequested long chain of valid
897+
// blocks, we add the headers to our index, but don't accept the
898+
// block).
899+
throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
900+
}
901+
902+
UniValue arrMerkleBlocks(UniValue::VARR);
903+
904+
for (; pblockindex; pblockindex = chainActive.Next(pblockindex))
905+
{
906+
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
907+
// this shouldn't happen, we already checked pruning case earlier
908+
throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
909+
}
910+
CDataStream ssMerkleBlock(SER_NETWORK, PROTOCOL_VERSION);
911+
ssMerkleBlock << CMerkleBlock(block, filter);
912+
std::string strHex = HexStr(ssMerkleBlock);
913+
arrMerkleBlocks.push_back(strHex);
914+
if (--nCount <= 0)
915+
break;
916+
}
917+
return arrMerkleBlocks;
918+
}
919+
840920
UniValue getblock(const JSONRPCRequest& request)
841921
{
842922
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
@@ -1760,6 +1840,7 @@ static const CRPCCommand commands[] =
17601840
{ "blockchain", "getblockhash", &getblockhash, true, {"height"} },
17611841
{ "blockchain", "getblockheader", &getblockheader, true, {"blockhash","verbose"} },
17621842
{ "blockchain", "getblockheaders", &getblockheaders, true, {"blockhash","count","verbose"} },
1843+
{ "blockchain", "getmerkleblocks", &getmerkleblocks, true, {"filter","blockhash","count"} },
17631844
{ "blockchain", "getchaintips", &getchaintips, true, {"count","branchlen"} },
17641845
{ "blockchain", "getdifficulty", &getdifficulty, true, {} },
17651846
{ "blockchain", "getmempoolancestors", &getmempoolancestors, true, {"txid","verbose"} },

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
103103
{ "getblockheader", 1, "verbose" },
104104
{ "getblockheaders", 1, "count" },
105105
{ "getblockheaders", 2, "verbose" },
106+
{ "getmerkleblocks", 2, "count" },
106107
{ "gettransaction", 1, "include_watchonly" },
107108
{ "getrawtransaction", 1, "verbose" },
108109
{ "createrawtransaction", 0, "inputs" },

0 commit comments

Comments
 (0)