Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Move bench files #8

Merged
merged 6 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

[![CI status](https://github.com/semiotic-ai/flat-files-decoder/workflows/ci/badge.svg)][gh-ci]

<!-- TODO: Seve please checkout if what I wrote makes sense -->
this crate is designed to decompress and decode headers from [binary files, which are called flat files,](https://github.com/streamingfast/firehose-ethereum/blob/develop/proto/sf/ethereum/type/v2/type.proto) generated from Firehose. Flat files store all information necessary to reconstruct the transaction and receipt tries. It also checks the validity of
receipt roots and transaction roots present in the block headers by recalculating them via the block body data. Details of the implementation can be found [here](https://github.com/streamingfast/dbin?tab=readme-ov-file)
this crate is designed to decompress and decode headers from [binary files, which are called flat files,](https://github.com/streamingfast/firehose-ethereum/blob/develop/proto/sf/ethereum/type/v2/type.proto) generated from Firehose. Flat files store all information necessary to reconstruct the transaction and receipt tries. It also checks the validity of receipt roots and transaction roots present in the block headers by recalculating them via the block body data. Details of the implementation can be found [here](https://github.com/streamingfast/dbin?tab=readme-ov-file).
This check ensures that receipt logs and transaction data stored in the flat files are internally consistent with the block headers also stored in the flat files.

This tool was first presented as a mean to enhance the performance and verifiability of The Graph protocol. However,
it turns out it could be used as a solution for EIP-4444 problem of full nodes stopping to provide historical data over one year.
The idea is that the flat files that this crate can decode could also be used as an archival format similar to era1 files, specially
if they can be verified.
The idea is that the flat files that this crate can decode could also be used as an archival format similar to era1 files if the
transaction and receipt data stored in the flat files can be verified to be part of the Ethereum canonical history.

For more information, read our ethresear.ch [here](https://ethresear.ch/t/using-the-graph-to-preserve-historical-data-and-enable-eip-4444/17318) and our pre-merge
solution implementation [here](https://github.com/semiotic-ai/header_accumulator) to see how we can verify that the flat files are consistent with Ethereum's canonical chain.

## Getting Started

Expand Down Expand Up @@ -66,17 +68,15 @@ This will store the block headers as json format in the output folder.
By passing `--headers-dir` a folder of assumed valid block headers can be provided to compare
with the input flat files. Valid headers can be pulled from the [sync committee subprotocol](https://github.com/ethereum/annotated-spec/blob/master/altair/sync-protocol.md) for post-merge data.

<!-- TODO: once the header_accumulator is made public, link it here -->
**NOTICE:**For pre-merge data another approach using [header accumulators](https://github.com/ethereum/portal-network-specs/blob/8ad5bc33cb0d4485d2eab73bf2decc43e7566a8f/history-network.md#the-header-accumulator) is necessary since
**NOTICE:**For pre-merge data another approach using the [header accumulator](https://github.com/ethereum/portal-network-specs/blob/8ad5bc33cb0d4485d2eab73bf2decc43e7566a8f/history-network.md#the-header-accumulator) is necessary since
sync committees will not provide these headers.

## Goals
<!-- TODO: Any other goals I should add? -->
We hope that flat files decoder will be able to handle
both post merge and pre merge data. Post-merge can be validated
using the Consensus Layer via the sync committee subprotocol. Pre-merge requires
headers accumulators and another step besides decoding the flat files is necessary.


Our goal is to provide The Graph's Indexers the tools to trustlessly share flat files with cryptographic guarantees
that the data in the flat files is part of the canonical history of the Ethereum blockchain,
enabling Indexers to quickly sync all historical data and begin serving data with minimal effort.

## Benchmarking
- Run `cargo bench` in the root directory of the project
- Benchmark results will be output to the terminal
Expand Down
37 changes: 36 additions & 1 deletion src/receipts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ use reth_primitives::proofs::ordered_trie_root_with_encoder;
use reth_rlp::Encodable;
use revm_primitives::B256;

const BYZANTINUM_FORK_BLOCK: u64 = 4_370_000;

/// Verifies the receipt root in a given block's header against a
/// computed receipt root from the block's body.
///
/// # Arguments
///
/// * `block` reference to the block which the root will be verified
pub fn check_receipt_root(block: &Block) -> Result<(), ReceiptError> {
let computed_root = calc_receipt_root(block)?;
let receipt_root = match block.header {
Expand All @@ -28,6 +36,14 @@ pub fn check_receipt_root(block: &Block) -> Result<(), ReceiptError> {
Ok(())
}

/// Calculates the trie receipt root of a given block recepits
///
/// It uses the traces to aggregate receipts from blocks and then
/// verifies them against the trie root present in the block header
pedrohba1 marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Arguments
///
/// * `block` reference to the block which the root will be verified
fn calc_receipt_root(block: &Block) -> Result<B256, ReceiptError> {
let mut receipts = Vec::new();

Expand All @@ -40,8 +56,26 @@ fn calc_receipt_root(block: &Block) -> Result<B256, ReceiptError> {
Ok(ordered_trie_root_with_encoder(&receipts, encoder))
}

/// Encodes full rceipts using [RLP serialization](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)
///
/// For blocks before the Byzantium fork, it uses a specific RLP encoding that includes the receipt's header length values, state root,
severiano-sisneros marked this conversation as resolved.
Show resolved Hide resolved
/// cumulative gas used, bloom filter, and logs.
/// For blocks at or after the Byzantium fork, it encodes the receipt's inner contents without the header.
///
/// This function is useful for computing the trie root hash which in reth needs to be rlp encoded.
///
/// # Arguments
///
/// * `block` reference to the [`Block`] where [`FullReceipt`] will be extracted from
///
/// # Returns
///
/// a function that takes a refenrece to a [`FullReceipt`],
/// and a mutable reference to a type implementing the [`BufMut`].
/// All the data from the receipts in written into the `BufMut` buffer

fn get_encoder(block: &Block) -> fn(&FullReceipt, &mut dyn BufMut) {
if block.number >= 4_370_000 {
if block.number >= BYZANTINUM_FORK_BLOCK {
|r: &FullReceipt, out: &mut dyn BufMut| r.receipt.encode_inner(out, false)
} else {
|r: &FullReceipt, out: &mut dyn BufMut| {
Expand All @@ -54,6 +88,7 @@ fn get_encoder(block: &Block) -> fn(&FullReceipt, &mut dyn BufMut) {
}
}

/// Encodes receipt header using [RLP serialization](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)
fn receipt_rlp_header(receipt: &FullReceipt) -> reth_rlp::Header {
let payload_length = receipt.state_root.as_slice().length()
+ receipt.receipt.receipt.cumulative_gas_used.length()
Expand Down
Loading