IBC#023: Bitcoin Core Initialization, Step 8— Starting Indexers
Transactions, Block Filters and Coin Statistics Indexes
Hello everyone and welcome to this new episode of Inside Bitcoin Code.
A special welcome to the new people that recently subscribed to this newsletter, I hope that you will enjoy what I write. A small suggestion for you: if you know nothing about coding, start reading the posts from Learn2Code to get some basic knowledge before diving in the real deal.
A huge thanks to each of the 146 subscribers of this newsletter and to those who decided to contribute with some sats to this project. It means the world to me!
Last episode was focused on cache memory allocation. Today we are going to move to step 8 of the initialization of Bitcoin Core. [Code Link]
Let’s start!
Transaction Index
We have now reached Step 8 of the node initialization. The goal of this step is to start the indexers, specialized databases that provide fast lookups for different types of blockchain data, such as all the raw transactions.
First of all, the code checks if the -txindex input was set to 1. If so, Bitcoin Core builds a complete transaction index to allow a user to access any transaction with commands like getrawtransaction. This is useful if the node needs to be used for development or chain analysis.
A TxIndex object is built passing the Chain interface through function MakeChain(), the size of the allocated cache for the transaction index, a bool hard-coded to false that signals the type of memory to be used and the do_reindex bool1.
if (args.GetBoolArg(”-txindex”, DEFAULT_TXINDEX)) {
g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), index_cache_sizes.tx_index, false, do_reindex);
node.indexes.emplace_back(g_txindex.get());
}In the end, the g_txindex pointer is added to the node.indexes vector.
Block Filter Index
Then, an index is created for each filter_type enabled. Block filters are compact representations of blocks, following BIP1582, which allow wallets to determine whether a block contains any transactions involving a user’s keys in a more private manner.
for (const auto& filter_type : g_enabled_filter_types) {
InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, index_cache_sizes.filter_index, false, do_reindex);
node.indexes.emplace_back(GetBlockFilterIndex(filter_type));
}Each filter_type is initialized through the InitBlockFilterIndex() function and is then added to the node.indexes vector. The function takes as input a so-called Lambda Function3, which allows for more flexibility, creating the Chain interface only when needed.
Coin Statistics Index
The last index to be initialized is the coin statistics index, a database that stores information about the UTXO set, like the total amount, the unspendable UTXOs, the total coinbase, etc.
The program checks if -coinstatsidex has been set to 1, and, if so, it builds a CoinStatsIndex object in the same fashion as the previous indexes.
if (args.GetBoolArg(”-coinstatsindex”, DEFAULT_COINSTATSINDEX)) {
g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, do_reindex);
node.indexes.emplace_back(g_coin_stats_index.get());
}This index, too is then added to the node.indexes vector.
Final Initialization
Finally, all the indexes added to the node.indexes vector are initialized in a for loop by calling the Init() function.
// Init indexes
for (auto index : node.indexes) if (!index->Init()) return false;If one of the them fails to initialize correctly, the function closes returning false.
Let’s keep in touch:
Check out my writings on btc++ insider edition
Try my new app Sats Tracker, an expense tracker app for people living in the Bitcoin standard.
Zap me a coffee and leave me a message: tuma@wallet.yakihonne.com
IBC#021: Re-indexing


