blockfilterindex.h
1 // Copyright (c) 2018-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #ifndef BITCOIN_INDEX_BLOCKFILTERINDEX_H 6 #define BITCOIN_INDEX_BLOCKFILTERINDEX_H 7 8 #include <attributes.h> 9 #include <flatfile.h> 10 #include <index/base.h> 11 #include <interfaces/chain.h> 12 #include <sync.h> 13 #include <uint256.h> 14 #include <util/hasher.h> 15 16 #include <cstddef> 17 #include <cstdint> 18 #include <functional> 19 #include <memory> 20 #include <optional> 21 #include <unordered_map> 22 #include <vector> 23 24 class BlockFilter; 25 class CBlockIndex; 26 enum class BlockFilterType : uint8_t; 27 28 static const char* const DEFAULT_BLOCKFILTERINDEX = "0"; 29 30 /** Interval between compact filter checkpoints. See BIP 157. */ 31 static constexpr int CFCHECKPT_INTERVAL = 1000; 32 33 /** 34 * BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of 35 * blocks by height. An index is constructed for each supported filter type with its own database 36 * (ie. filter data for different types are stored in separate databases). 37 * 38 * This index is used to serve BIP 157 net requests. 39 */ 40 class BlockFilterIndex final : public BaseIndex 41 { 42 private: 43 BlockFilterType m_filter_type; 44 std::unique_ptr<BaseIndex::DB> m_db; 45 46 FlatFilePos m_next_filter_pos; 47 std::unique_ptr<FlatFileSeq> m_filter_fileseq; 48 49 bool ReadFilterFromDisk(const FlatFilePos& pos, const uint256& hash, BlockFilter& filter) const; 50 size_t WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter); 51 52 Mutex m_cs_headers_cache; 53 /** cache of block hash to filter header, to avoid disk access when responding to getcfcheckpt. */ 54 std::unordered_map<uint256, uint256, BlockHasher> m_headers_cache GUARDED_BY(m_cs_headers_cache); 55 56 // Last computed header to avoid disk reads on every new block. 57 uint256 m_last_header{}; 58 59 bool AllowPrune() const override { return true; } 60 61 bool Write(const BlockFilter& filter, uint32_t block_height, const uint256& filter_header); 62 63 std::optional<uint256> ReadFilterHeader(int height, const uint256& expected_block_hash); 64 65 protected: 66 bool CustomInit(const std::optional<interfaces::BlockRef>& block) override; 67 68 bool CustomCommit(CDBBatch& batch) override; 69 70 bool CustomAppend(const interfaces::BlockInfo& block) override; 71 72 bool CustomRemove(const interfaces::BlockInfo& block) override; 73 74 BaseIndex::DB& GetDB() const LIFETIMEBOUND override { return *m_db; } 75 76 public: 77 /** Constructs the index, which becomes available to be queried. */ 78 explicit BlockFilterIndex(std::unique_ptr<interfaces::Chain> chain, BlockFilterType filter_type, 79 size_t n_cache_size, bool f_memory = false, bool f_wipe = false); 80 81 interfaces::Chain::NotifyOptions CustomOptions() override; 82 83 BlockFilterType GetFilterType() const { return m_filter_type; } 84 85 /** Get a single filter by block. */ 86 bool LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const; 87 88 /** Get a single filter header by block. */ 89 bool LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache); 90 91 /** Get a range of filters between two heights on a chain. */ 92 bool LookupFilterRange(int start_height, const CBlockIndex* stop_index, 93 std::vector<BlockFilter>& filters_out) const; 94 95 /** Get a range of filter hashes between two heights on a chain. */ 96 bool LookupFilterHashRange(int start_height, const CBlockIndex* stop_index, 97 std::vector<uint256>& hashes_out) const; 98 }; 99 100 /** 101 * Get a block filter index by type. Returns nullptr if index has not been initialized or was 102 * already destroyed. 103 */ 104 BlockFilterIndex* GetBlockFilterIndex(BlockFilterType filter_type); 105 106 /** Iterate over all running block filter indexes, invoking fn on each. */ 107 void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn); 108 109 /** 110 * Initialize a block filter index for the given type if one does not already exist. Returns true if 111 * a new index is created and false if one has already been initialized. 112 */ 113 bool InitBlockFilterIndex(std::function<std::unique_ptr<interfaces::Chain>()> make_chain, BlockFilterType filter_type, 114 size_t n_cache_size, bool f_memory = false, bool f_wipe = false); 115 116 /** 117 * Destroy the block filter index with the given type. Returns false if no such index exists. This 118 * just releases the allocated memory and closes the database connection, it does not delete the 119 * index data. 120 */ 121 bool DestroyBlockFilterIndex(BlockFilterType filter_type); 122 123 /** Destroy all open block filter indexes. */ 124 void DestroyAllBlockFilterIndexes(); 125 126 #endif // BITCOIN_INDEX_BLOCKFILTERINDEX_H