Skip to content

Commit ff35105

Browse files
committed
init: Add CLI option to enable block filter index.
1 parent accc8b8 commit ff35105

File tree

5 files changed

+91
-0
lines changed

5 files changed

+91
-0
lines changed

src/blockfilter.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include <mutex>
6+
#include <sstream>
7+
58
#include <blockfilter.h>
69
#include <crypto/siphash.h>
710
#include <hash.h>
@@ -218,6 +221,40 @@ bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type
218221
return false;
219222
}
220223

224+
const std::vector<BlockFilterType>& AllBlockFilterTypes()
225+
{
226+
static std::vector<BlockFilterType> types;
227+
228+
static std::once_flag flag;
229+
std::call_once(flag, []() {
230+
types.reserve(g_filter_types.size());
231+
for (auto entry : g_filter_types) {
232+
types.push_back(entry.first);
233+
}
234+
});
235+
236+
return types;
237+
}
238+
239+
const std::string& ListBlockFilterTypes()
240+
{
241+
static std::string type_list;
242+
243+
static std::once_flag flag;
244+
std::call_once(flag, []() {
245+
std::stringstream ret;
246+
bool first = true;
247+
for (auto entry : g_filter_types) {
248+
if (!first) ret << ", ";
249+
ret << entry.second;
250+
first = false;
251+
}
252+
type_list = ret.str();
253+
});
254+
255+
return type_list;
256+
}
257+
221258
static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
222259
const CBlockUndo& block_undo)
223260
{

src/blockfilter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ const std::string& BlockFilterTypeName(BlockFilterType filter_type);
9696
/** Find a filter type by its human-readable name. */
9797
bool BlockFilterTypeByName(const std::string& name, BlockFilterType& filter_type);
9898

99+
/** Get a list of known filter types. */
100+
const std::vector<BlockFilterType>& AllBlockFilterTypes();
101+
102+
/** Get a comma-separated list of known filter type names. */
103+
const std::string& ListBlockFilterTypes();
104+
99105
/**
100106
* Complete block filter struct as defined in BIP 157. Serialization matches
101107
* payload of "cfilter" messages.

src/init.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <addrman.h>
1313
#include <amount.h>
1414
#include <banman.h>
15+
#include <blockfilter.h>
1516
#include <chain.h>
1617
#include <chainparams.h>
1718
#include <checkpoints.h>
@@ -20,6 +21,7 @@
2021
#include <fs.h>
2122
#include <httpserver.h>
2223
#include <httprpc.h>
24+
#include <index/blockfilterindex.h>
2325
#include <interfaces/chain.h>
2426
#include <index/txindex.h>
2527
#include <key.h>
@@ -189,6 +191,7 @@ void Interrupt()
189191
if (g_txindex) {
190192
g_txindex->Interrupt();
191193
}
194+
ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Interrupt(); });
192195
}
193196

194197
void Shutdown(InitInterfaces& interfaces)
@@ -220,6 +223,7 @@ void Shutdown(InitInterfaces& interfaces)
220223
if (peerLogic) UnregisterValidationInterface(peerLogic.get());
221224
if (g_connman) g_connman->Stop();
222225
if (g_txindex) g_txindex->Stop();
226+
ForEachBlockFilterIndex([](BlockFilterIndex& index) { index.Stop(); });
223227

224228
StopTorControl();
225229

@@ -234,6 +238,7 @@ void Shutdown(InitInterfaces& interfaces)
234238
g_connman.reset();
235239
g_banman.reset();
236240
g_txindex.reset();
241+
DestroyAllBlockFilterIndexes();
237242

238243
if (g_is_mempool_loaded && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
239244
DumpMempool();
@@ -404,6 +409,10 @@ void SetupServerArgs()
404409
hidden_args.emplace_back("-sysperms");
405410
#endif
406411
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
412+
gArgs.AddArg("-blockfilterindex=<type>",
413+
strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
414+
" If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
415+
false, OptionsCategory::OPTIONS);
407416

408417
gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", false, OptionsCategory::CONNECTION);
409418
gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION);
@@ -886,6 +895,7 @@ int nUserMaxConnections;
886895
int nFD;
887896
ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED);
888897
int64_t peer_connect_timeout;
898+
std::vector<BlockFilterType> g_enabled_filter_types;
889899

890900
} // namespace
891901

@@ -954,10 +964,29 @@ bool AppInitParameterInteraction()
954964
return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
955965
}
956966

967+
// parse and validate enabled filter types
968+
std::string blockfilterindex_value = gArgs.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX);
969+
if (blockfilterindex_value == "" || blockfilterindex_value == "1") {
970+
g_enabled_filter_types = AllBlockFilterTypes();
971+
} else if (blockfilterindex_value != "0") {
972+
const std::vector<std::string> names = gArgs.GetArgs("-blockfilterindex");
973+
g_enabled_filter_types.reserve(names.size());
974+
for (const auto& name : names) {
975+
BlockFilterType filter_type;
976+
if (!BlockFilterTypeByName(name, filter_type)) {
977+
return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));
978+
}
979+
g_enabled_filter_types.push_back(filter_type);
980+
}
981+
}
982+
957983
// if using block pruning, then disallow txindex
958984
if (gArgs.GetArg("-prune", 0)) {
959985
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX))
960986
return InitError(_("Prune mode is incompatible with -txindex."));
987+
if (!g_enabled_filter_types.empty()) {
988+
return InitError(_("Prune mode is incompatible with -blockfilterindex."));
989+
}
961990
}
962991

963992
// -bind and -whitebind can't be set when not listening
@@ -1448,6 +1477,13 @@ bool AppInitMain(InitInterfaces& interfaces)
14481477
nTotalCache -= nBlockTreeDBCache;
14491478
int64_t nTxIndexCache = std::min(nTotalCache / 8, gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxTxIndexCache << 20 : 0);
14501479
nTotalCache -= nTxIndexCache;
1480+
int64_t filter_index_cache = 0;
1481+
if (!g_enabled_filter_types.empty()) {
1482+
size_t n_indexes = g_enabled_filter_types.size();
1483+
int64_t max_cache = std::min(nTotalCache / 8, max_filter_index_cache << 20);
1484+
filter_index_cache = max_cache / n_indexes;
1485+
nTotalCache -= filter_index_cache * n_indexes;
1486+
}
14511487
int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache
14521488
nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache
14531489
nTotalCache -= nCoinDBCache;
@@ -1458,6 +1494,10 @@ bool AppInitMain(InitInterfaces& interfaces)
14581494
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
14591495
LogPrintf("* Using %.1f MiB for transaction index database\n", nTxIndexCache * (1.0 / 1024 / 1024));
14601496
}
1497+
for (BlockFilterType filter_type : g_enabled_filter_types) {
1498+
LogPrintf("* Using %.1f MiB for %s block filter index database\n",
1499+
filter_index_cache * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
1500+
}
14611501
LogPrintf("* Using %.1f MiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
14621502
LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
14631503

@@ -1645,6 +1685,11 @@ bool AppInitMain(InitInterfaces& interfaces)
16451685
g_txindex->Start();
16461686
}
16471687

1688+
for (const auto& filter_type : g_enabled_filter_types) {
1689+
InitBlockFilterIndex(filter_type, filter_index_cache, false, fReindex);
1690+
GetBlockFilterIndex(filter_type)->Start();
1691+
}
1692+
16481693
// ********************************************************* Step 9: load wallet
16491694
for (const auto& client : interfaces.chain_clients) {
16501695
if (!client->load()) {

src/txdb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ static const int64_t nMaxBlockDBCache = 2;
3737
// Unlike for the UTXO database, for the txindex scenario the leveldb cache make
3838
// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
3939
static const int64_t nMaxTxIndexCache = 1024;
40+
//! Max memory allocated to all block filter index caches combined in MiB.
41+
static const int64_t max_filter_index_cache = 1024;
4042
//! Max memory allocated to coin DB specific cache (MiB)
4143
static const int64_t nMaxCoinsDBCache = 8;
4244

src/validation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
118118
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
119119
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
120120
static const bool DEFAULT_TXINDEX = false;
121+
static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
121122
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
122123
/** Default for -persistmempool */
123124
static const bool DEFAULT_PERSIST_MEMPOOL = true;

0 commit comments

Comments
 (0)