Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2025-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_INDEX_DB_KEY_H6#define BITCOIN_INDEX_DB_KEY_H8#include <dbwrapper.h>9#include <interfaces/types.h>10#include <serialize.h>11#include <uint256.h>12#include <util/log.h>14#include <cstdint>15#include <ios>16#include <string>17#include <utility>19namespace index_util {20/*21* This file includes the logic for the db keys used by blockfilterindex and coinstatsindex.22* Index data is usually indexed by height, but in case of a reorg, entries of blocks no23* longer in the main chain will be copied to a hash index by which they can still be queried.24* Keys for the height index have the type [DB_BLOCK_HEIGHT, uint32 (BE)]. The height is represented25* as big-endian so that sequential reads of filters by height are fast.26* Keys for the hash index have the type [DB_BLOCK_HASH, uint256].27*/29inline constexpr uint8_t DB_BLOCK_HASH{'s'};30inline constexpr uint8_t DB_BLOCK_HEIGHT{'t'};32struct DBHeightKey {33int height;35explicit DBHeightKey(int height_in) : height(height_in) {}37template<typename Stream>38void Serialize(Stream& s) const39{40ser_writedata8(s, DB_BLOCK_HEIGHT);41ser_writedata32be(s, height);42}44template<typename Stream>45void Unserialize(Stream& s)46{47const uint8_t prefix{ser_readdata8(s)};48if (prefix != DB_BLOCK_HEIGHT) {49throw std::ios_base::failure("Invalid format for index DB height key");50}51height = ser_readdata32be(s);52}53};55struct DBHashKey {56uint256 hash;58explicit DBHashKey(const uint256& hash_in) : hash(hash_in) {}60SERIALIZE_METHODS(DBHashKey, obj) {61uint8_t prefix{DB_BLOCK_HASH};62READWRITE(prefix);63if (prefix != DB_BLOCK_HASH) {64throw std::ios_base::failure("Invalid format for index DB hash key");65}67READWRITE(obj.hash);68}69};71template <typename DBVal>72[[nodiscard]] static bool CopyHeightIndexToHashIndex(CDBIterator& db_it, CDBBatch& batch,73const std::string& index_name, int height)74{75DBHeightKey key(height);76db_it.Seek(key);78if (!db_it.GetKey(key) || key.height != height) {79LogError("unexpected key in %s: expected (%c, %d)",80index_name, DB_BLOCK_HEIGHT, height);81return false;82}84std::pair<uint256, DBVal> value;85if (!db_it.GetValue(value)) {86LogError("unable to read value in %s at key (%c, %d)",87index_name, DB_BLOCK_HEIGHT, height);88return false;89}91batch.Write(DBHashKey(value.first), value.second);92return true;93}95template <typename DBVal>96static bool LookUpOne(const CDBWrapper& db, const interfaces::BlockRef& block, DBVal& result)97{98// First check if the result is stored under the height index and the value99// there matches the block hash. This should be the case if the block is on100// the active chain.101std::pair<uint256, DBVal> read_out;102if (!db.Read(DBHeightKey(block.height), read_out)) {103return false;104}105if (read_out.first == block.hash) {106result = std::move(read_out.second);107return true;108}110// If value at the height index corresponds to an different block, the111// result will be stored in the hash index.112return db.Read(DBHashKey(block.hash), result);113}114} // namespace index_util116#endif // BITCOIN_INDEX_DB_KEY_H