Skip to main content

erigon_seg/
salt.rs

1//! Index salt handling for the `.kvei` existence filter.
2//!
3//! Erigon hashes each key as `murmur3.Sum128WithSeed(key, salt)` before adding it to
4//! the bloom filter, where `salt` is a per-snapshot 32-bit value (Erigon stores it in
5//! `salt-state.txt` / `salt-blocks.txt`). Without the right salt the filter cannot be
6//! used, so a reader must learn it — from the file, from the caller, or by brute force.
7
8use std::path::Path;
9
10/// How to obtain the `.kvei` index salt.
11#[derive(Debug, Clone, Copy)]
12#[non_exhaustive]
13pub enum Salt {
14    /// No salt: do not use the bloom filter. Lookups stay correct (exact `.bt` search),
15    /// just without the negative-lookup speedup.
16    None,
17    /// A known salt (e.g. from `salt-state.txt`, big-endian `u32`).
18    Known(u32),
19    /// Brute-force the salt by requiring a batch of real keys to all hit the bloom,
20    /// using `usize` worker threads. The ~1% per-key false-positive rate makes a wrong
21    /// salt passing every sampled key astronomically unlikely, so the first salt that
22    /// passes is the real one.
23    Find(usize),
24}
25
26/// Read an Erigon salt file (`salt-state.txt` / `salt-blocks.txt`): a 4-byte big-endian
27/// `u32`. Returns `None` if the file is missing or too short.
28pub fn salt_from_file(path: impl AsRef<Path>) -> Option<u32> {
29    let b = std::fs::read(path).ok()?;
30    (b.len() >= 4).then(|| u32::from_be_bytes(b[0..4].try_into().unwrap()))
31}