Inside Bitcoin
Opening the selected file…
Inside Bitcoin
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) 2012 The LevelDB Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file. See the AUTHORS file for names of contributors.5#include "table/filter_block.h"7#include "leveldb/filter_policy.h"8#include "util/coding.h"10namespace leveldb {12// See doc/table_format.md for an explanation of the filter block format.14// Generate new filter every 2KB of data15static const size_t kFilterBaseLg = 11;16static const size_t kFilterBase = 1 << kFilterBaseLg;18FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy)19: policy_(policy) {}21void FilterBlockBuilder::StartBlock(uint64_t block_offset) {22uint64_t filter_index = (block_offset / kFilterBase);23assert(filter_index >= filter_offsets_.size());24while (filter_index > filter_offsets_.size()) {25GenerateFilter();26}27}29void FilterBlockBuilder::AddKey(const Slice& key) {30Slice k = key;31start_.push_back(keys_.size());32keys_.append(k.data(), k.size());33}35Slice FilterBlockBuilder::Finish() {36if (!start_.empty()) {37GenerateFilter();38}40// Append array of per-filter offsets41const uint32_t array_offset = result_.size();42for (size_t i = 0; i < filter_offsets_.size(); i++) {43PutFixed32(&result_, filter_offsets_[i]);44}46PutFixed32(&result_, array_offset);47result_.push_back(kFilterBaseLg); // Save encoding parameter in result48return Slice(result_);49}51void FilterBlockBuilder::GenerateFilter() {52const size_t num_keys = start_.size();53if (num_keys == 0) {54// Fast path if there are no keys for this filter55filter_offsets_.push_back(result_.size());56return;57}59// Make list of keys from flattened key structure60start_.push_back(keys_.size()); // Simplify length computation61tmp_keys_.resize(num_keys);62for (size_t i = 0; i < num_keys; i++) {63const char* base = keys_.data() + start_[i];64size_t length = start_[i + 1] - start_[i];65tmp_keys_[i] = Slice(base, length);66}68// Generate filter for current set of keys and append to result_.69filter_offsets_.push_back(result_.size());70policy_->CreateFilter(&tmp_keys_[0], static_cast<int>(num_keys), &result_);72tmp_keys_.clear();73keys_.clear();74start_.clear();75}77FilterBlockReader::FilterBlockReader(const FilterPolicy* policy,78const Slice& contents)79: policy_(policy), data_(nullptr), offset_(nullptr), num_(0), base_lg_(0) {80size_t n = contents.size();81if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array82base_lg_ = contents[n - 1];83uint32_t last_word = DecodeFixed32(contents.data() + n - 5);84if (last_word > n - 5) return;85data_ = contents.data();86offset_ = data_ + last_word;87num_ = (n - 5 - last_word) / 4;88}90bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) {91uint64_t index = block_offset >> base_lg_;92if (index < num_) {93uint32_t start = DecodeFixed32(offset_ + index * 4);94uint32_t limit = DecodeFixed32(offset_ + index * 4 + 4);95if (start <= limit && limit <= static_cast<size_t>(offset_ - data_)) {96Slice filter = Slice(data_ + start, limit - start);97return policy_->KeyMayMatch(key, filter);98} else if (start == limit) {99// Empty filters do not match any keys100return false;101}102}103return true; // Errors are treated as potential matches104}106} // namespace leveldb
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.