diff options
Diffstat (limited to 'src/rpc/blockchain.cpp')
-rw-r--r-- | src/rpc/blockchain.cpp | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 1c20feba12..e3fab44719 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -7,13 +7,14 @@ #include <amount.h> #include <base58.h> +#include <blockfilter.h> #include <chain.h> #include <chainparams.h> -#include <checkpoints.h> #include <coins.h> #include <consensus/validation.h> #include <core_io.h> #include <hash.h> +#include <index/blockfilterindex.h> #include <index/txindex.h> #include <key_io.h> #include <policy/feerate.h> @@ -29,6 +30,7 @@ #include <txmempool.h> #include <util/strencodings.h> #include <util/system.h> +#include <util/validation.h> #include <validation.h> #include <validationinterface.h> #include <versionbitsinfo.h> @@ -378,7 +380,9 @@ static UniValue getdifficulty(const JSONRPCRequest& request) static std::string EntryDescriptionString() { - return " \"size\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n" + return " \"vsize\" : n, (numeric) virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.\n" + " \"size\" : n, (numeric) (DEPRECATED) same as vsize. Only returned if bitcoind is started with -deprecatedrpc=size\n" + " size will be completely removed in v0.20.\n" " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n" " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority (DEPRECATED)\n" " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" @@ -416,7 +420,8 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool fees.pushKV("descendant", ValueFromAmount(e.GetModFeesWithDescendants())); info.pushKV("fees", fees); - info.pushKV("size", (int)e.GetTxSize()); + info.pushKV("vsize", (int)e.GetTxSize()); + if (IsDeprecatedRPCEnabled("size")) info.pushKV("size", (int)e.GetTxSize()); info.pushKV("fee", ValueFromAmount(e.GetFee())); info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee())); info.pushKV("time", e.GetTime()); @@ -1007,7 +1012,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request) // too low to be a block time (corresponds to timestamp from Sep 2001). if (heightParam > 1000000000) { // Add a 2 hour buffer to include blocks which might have had old timestamps - CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW); + CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0); if (!pindex) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp."); } @@ -1483,6 +1488,8 @@ static UniValue getchaintips(const JSONRPCRequest& request) UniValue MempoolInfoToJSON(const CTxMemPool& pool) { + // Make sure this call is atomic in the pool. + LOCK(pool.cs); UniValue ret(UniValue::VOBJ); ret.pushKV("loaded", pool.IsLoaded()); ret.pushKV("size", (int64_t)pool.size()); @@ -1581,15 +1588,15 @@ static UniValue invalidateblock(const JSONRPCRequest& request) uint256 hash(ParseHashV(request.params[0], "blockhash")); CValidationState state; + CBlockIndex* pblockindex; { LOCK(cs_main); - CBlockIndex* pblockindex = LookupBlockIndex(hash); + pblockindex = LookupBlockIndex(hash); if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - - InvalidateBlock(state, Params(), pblockindex); } + InvalidateBlock(state, Params(), pblockindex); if (state.IsValid()) { ActivateBestChain(state, Params()); @@ -2295,6 +2302,85 @@ UniValue scantxoutset(const JSONRPCRequest& request) return result; } +static UniValue getblockfilter(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { + throw std::runtime_error( + RPCHelpMan{"getblockfilter", + "\nRetrieve a BIP 157 content filter for a particular block.\n", + { + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hash of the block"}, + {"filtertype", RPCArg::Type::STR, /*default*/ "basic", "The type name of the filter"}, + }, + RPCResult{ + "{\n" + " \"filter\" : (string) the hex-encoded filter data\n" + " \"header\" : (string) the hex-encoded filter header\n" + "}\n" + }, + RPCExamples{ + HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") + } + }.ToString() + ); + } + + uint256 block_hash = ParseHashV(request.params[0], "blockhash"); + std::string filtertype_name = "basic"; + if (!request.params[1].isNull()) { + filtertype_name = request.params[1].get_str(); + } + + BlockFilterType filtertype; + if (!BlockFilterTypeByName(filtertype_name, filtertype)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown filtertype"); + } + + BlockFilterIndex* index = GetBlockFilterIndex(filtertype); + if (!index) { + throw JSONRPCError(RPC_MISC_ERROR, "Index is not enabled for filtertype " + filtertype_name); + } + + const CBlockIndex* block_index; + bool block_was_connected; + { + LOCK(cs_main); + block_index = LookupBlockIndex(block_hash); + if (!block_index) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + } + block_was_connected = block_index->IsValid(BLOCK_VALID_SCRIPTS); + } + + bool index_ready = index->BlockUntilSyncedToCurrentChain(); + + BlockFilter filter; + uint256 filter_header; + if (!index->LookupFilter(block_index, filter) || + !index->LookupFilterHeader(block_index, filter_header)) { + int err_code; + std::string errmsg = "Filter not found."; + + if (!block_was_connected) { + err_code = RPC_INVALID_ADDRESS_OR_KEY; + errmsg += " Block was not connected to active chain."; + } else if (!index_ready) { + err_code = RPC_MISC_ERROR; + errmsg += " Block filters are still in the process of being indexed."; + } else { + err_code = RPC_INTERNAL_ERROR; + errmsg += " This error is unexpected and indicates index corruption."; + } + + throw JSONRPCError(err_code, errmsg); + } + + UniValue ret(UniValue::VOBJ); + ret.pushKV("filter", HexStr(filter.GetEncodedFilter())); + ret.pushKV("header", filter_header.GetHex()); + return ret; +} + // clang-format off static const CRPCCommand commands[] = { // category name actor (function) argNames @@ -2322,6 +2408,7 @@ static const CRPCCommand commands[] = { "blockchain", "preciousblock", &preciousblock, {"blockhash"} }, { "blockchain", "scantxoutset", &scantxoutset, {"action", "scanobjects"} }, + { "blockchain", "getblockfilter", &getblockfilter, {"blockhash", "filtertype"} }, /* Not shown in help */ { "hidden", "invalidateblock", &invalidateblock, {"blockhash"} }, |