The ffmpeg for Ethereum historical archives.
Brandon is a standalone Rust toolkit for reading, verifying, converting, and exploring Ethereum historical archives.
Instead of exposing archive internals, Brandon lets you work with Ethereum concepts—blocks, slots, epochs, headers, receipts, and states—through simple, UNIX-friendly commands.
It was built out of frustration with having to run an entire consensus client just to inspect a single historical block.
From crates.io
cargo install brandonFrom source:
git clone https://github.com/galadd/brandon.git
cd brandon
cargo install --path .Prebuilt binaries are available on the releases page.
- ✓ Stream ERA/ERA1 archives without loading entire files into memory
- ✓ Random-access blocks by slot
- ✓ Build new ERA archives
- ✓ Verify archive integrity and manifests
- ✓ Rebuild indexes and transform archives
- ✓ Zero-copy iteration over in-memory archives
- ✓ Client-agnostic design
- ✓ Structured JSON output
$ brandon info mainnet-00000-5ec1ffb8.era1
Format: ERA1
File size: 3.71 MiB (3891337)
Starting slot: 0
Slot range: 0..8191
Block count: 8191
State present: no
Total entries: 32770
Entry breakdown:
BlockAccumulator 1
BlockBody 8192
BlockIndex 1
CompressedHeader 8192
Receipts 8192
TotalDifficulty 8192
A researcher should be able to go from zero to answering a question about Ethereum history in under a minute.
cargo install brandon
brandon block 12345678 --json \
| jq '.proposer_index'No node to synchronize.
No consensus client.
No heavyweight SSZ libraries.
Just install Brandon and ask questions about Ethereum history.
Note
The command above represents Brandon's target user experience. Today, Brandon provides the archive manipulation foundation that future high-level commands will build upon.
Brandon is designed in layers.
Each layer builds on the previous one while keeping the core library lightweight and client-independent.
The format-agnostic foundation.
Current capabilities include:
- Reading ERA and ERA1 archives
- Streaming readers
- Random access by slot
- Archive verification
- Archive construction
- Archive conversion
- Zero-copy iteration
- Client interoperability
The library intentionally avoids depending on any particular Ethereum client implementation.
For example, the era1_to_era converter lets callers provide their own SSZ implementation rather than forcing one on downstream users.
Users shouldn't need to think about:
- entry types
- type codes
- archive offsets
- compression details
They should think about:
- blocks
- headers
- epochs
- slots
- receipts
- beacon states
The goal is to expose commands such as:
brandon block 12345678
brandon header 12345678
brandon receipts 12345678along with structured JSON output using Ethereum consensus terminology.
Working with historical Ethereum data shouldn't require downloading an archive first.
Future versions will support commands such as:
brandon fetch block 12345678Internally Brandon will:
- locate the appropriate archive
- download only the required byte ranges
- decompress the requested data
- decode it
- print the result
The user shouldn't need to know where the archive lives or that HTTP range requests are involved.
Eventually Brandon aims to become a searchable interface over Ethereum history.
Examples include:
brandon search --proposer 1234 ./archives/
brandon search --graffiti "rocketpool"
brandon search --execution-block 19000000One long-term goal is a single command capable of identifying almost anything.
$ curl https://example.com/archive.era \
| brandon inspect
Format: ERA
Epochs: 90–91
Blocks: 8192
Compressed: snappy
SHA256: ...Whether the input comes from:
- a local file
- a directory
- stdin
- a URL
Brandon should determine what it is automatically.
brandon info archive.era1
brandon info archive.era --jsonbrandon verify archive.era1
brandon verify archive.era1 \
--manifest checksums.txt# Read a single slot
brandon read archive.era1 --slot 42
# Stream every block
brandon read archive.era1 --all
# Read first 10 blocks
brandon read archive.era1 --count 10
# Extract blocks
brandon read archive.era1 \
--all \
--output-dir ./blocks
# Include beacon state
brandon read archive.era \
--all \
--state# Rebuild indexes
brandon convert reindex archive.era1 \
-o fixed.era1
# Remove receipts
brandon convert strip archive.era1 \
--strip-receipts \
-o slim.era1
# Headers only
brandon convert strip archive.era1 \
--strip-receipts \
--strip-bodies \
--strip-td \
-o headers.era1
# Split archive
brandon convert split archive.era1 \
--output-dir ./blocksbrandon build \
--blocks-dir ./compressed \
--output out.era
brandon build \
--blocks-dir ./compressed \
--state state.snappy \
--state-slot 8192 \
--output out.era[dependencies]
brandon = "0.1"use brandon::{EraReader, TypedEntry};
let file = std::fs::File::open("archive.era1")?;
let mut reader = EraReader::new(file);
while let Some(entry) = reader.next_entry()? {
match entry {
TypedEntry::Header { data } => {
println!("{}", data.len());
}
_ => {}
}
}use brandon::EraRandomReader;
let file = std::fs::File::open("archive.era1")?;
let mut reader = EraRandomReader::new(file)?;
if let Some(block) = reader.read_block_at_slot(42)? {
println!("{}", block.primary_data().len());
}use brandon::read::iter_blocks;
let bytes = std::fs::read("archive.era")?;
for block in iter_blocks(&bytes)? {
println!("{}", block.primary_data().len());
}| Format | Status | Description |
|---|---|---|
| e2store | ✅ Full | Container format |
| ERA1 | ✅ Full | Pre-merge execution history |
| ERA | ✅ Full | Post-merge consensus history |
| E2SS | 🟡 Structural | Execution state snapshots |
| E2HS | 🟡 Structural | Execution history with proofs |
| ERE | 🔜 Planned | Full execution history |
Full — Entry types recognized and verified against real archives.
Structural — Container supported; payload parsing not yet implemented.
cargo test
cargo fmt --check
cargo clippy --all-targets --all-features
cargo build --releaseLicensed under either
- MIT
- Apache-2.0
at your option.