Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
suchapalaver committed Oct 29, 2024
1 parent ad65d08 commit 929ae2a
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 93 deletions.
61 changes: 13 additions & 48 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions crates/firehose-protos/src/ethereum_v2/eth_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,30 @@ impl Block {
.collect()
}

/// Calculates the trie root of the receipts for the current block.
///
/// This method aggregates and encodes receipts derived from transaction traces to compute
/// the Merkle trie root, which represents the receipt root of the block.
///
/// # Returns
///
/// A [`Result`] containing the calculated root as `B256` if successful, or a [`ProtosError`] if
/// an error occurs during receipt processing.
///
/// # Note
///
/// The root is computed based on receipts derived from transaction traces associated with the block.
pub fn receipt_root(&self) -> Result<B256, ProtosError> {
let receipts = self
.transaction_traces
.iter()
.map(FullReceipt::try_from)
.collect::<Result<Vec<_>, _>>()?;

let encoder = self.full_receipt_encoder();
Ok(ordered_trie_root_with_encoder(&receipts, encoder))
}

/// Checks if the transaction root matches the block header's transactions root.
/// Returns `true` if they match, `false` otherwise.
pub fn transaction_root_is_verified(&self) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion crates/flat-files-decoder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ prost.workspace = true
rand.workspace = true
rayon.workspace = true
reth-primitives.workspace = true
revm-primitives.workspace = true
reth-trie-common.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
simple-log.workspace = true
Expand Down
7 changes: 2 additions & 5 deletions crates/flat-files-decoder/benches/stream_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use std::{
};

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use decoder::{
dbin::{error::DbinFileError, DbinFile},
receipts::check_receipt_root,
};
use decoder::dbin::{error::DbinFileError, DbinFile};
use prost::Message;

const ITERS_PER_FILE: usize = 10;
Expand Down Expand Up @@ -138,7 +135,7 @@ fn read_decode_check_bench(c: &mut Criterion) {
)
.unwrap();
b.iter(|| {
black_box(check_receipt_root(&block)).unwrap();
black_box(block.receipt_root_is_verified());
});
}
}
Expand Down
166 changes: 166 additions & 0 deletions crates/flat-files-decoder/src/dbin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,169 @@ impl DbinFile {
Ok(content)
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;

#[test]
fn test_supported_version() {
// Create a DBIN file with version 0 (supported)
let version = 0x00; // Version 0
let content_type = b"ETH"; // Example content type
let content_version = b"00"; // Example content version

// Construct the DBIN file bytes for version 0
let dbin_bytes = [
b'd',
b'b',
b'i',
b'n', // Magic bytes
version, // File format version (0x00)
content_type[0], // First byte of content type
content_type[1], // Second byte of content type
content_type[2], // Third byte of content type
content_version[0], // First byte of content version
content_version[1], // Second byte of content version
]
.iter()
.copied()
.collect::<Vec<u8>>();

let mut cursor = Cursor::new(dbin_bytes);

let result = DbinFile::try_from_read(&mut cursor);
assert!(
result.is_ok(),
"Expected success for valid DBIN file with version 0"
);
}

#[test]
fn test_unsupported_version() {
// Create a DBIN file with an unsupported version (anything other than 0)
let unsupported_version = 0x01; // Version 1 is unsupported
let content_type = b"ETH"; // Example content type
let content_version = b"00"; // Example content version

// Construct the DBIN file bytes for version 1
let unsupported_dbin = [
b'd',
b'b',
b'i',
b'n', // Magic bytes
unsupported_version, // Version (0x01)
content_type[0], // First byte of content type
content_type[1], // Second byte of content type
content_type[2], // Third byte of content type
content_version[0], // First byte of content version
content_version[1], // Second byte of content version
]
.iter()
.copied()
.collect::<Vec<u8>>();

let mut cursor = Cursor::new(unsupported_dbin);

let result = DbinFile::try_from_read(&mut cursor);
assert!(
result.is_err(),
"Expected error for DBIN file with unsupported version"
);
assert_eq!(
result.err().unwrap().to_string(),
DbinFileError::UnsupportedDBINVersion.to_string()
);
}

#[test]
fn test_invalid_magic_bytes() {
let invalid_dbin = b"xxxx\x00ETH00"; // Invalid magic bytes
let mut cursor = Cursor::new(invalid_dbin);

let result = DbinFile::try_from_read(&mut cursor);
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
DbinFileError::StartOfNewDBINFile.to_string()
);
}

#[test]
fn test_read_valid_dbin_with_multiple_messages() {
let version = 0x00; // Version 0
let content_type = b"ETH"; // Example content type
let content_version = b"00"; // Example content version
let message1 = b"message1"; // Example message 1
let message2 = b"message2"; // Example message 2

// Construct a valid DBIN file with two messages
let mut dbin_bytes = vec![
b'd',
b'b',
b'i',
b'n', // Magic bytes
version, // File format version (0x00)
content_type[0], // First byte of content type
content_type[1], // Second byte of content type
content_type[2], // Third byte of content type
content_version[0], // First byte of content version
content_version[1], // Second byte of content version
];

// Append message 1 length (4 bytes) and message 1 content
dbin_bytes.extend_from_slice(&(message1.len() as u32).to_be_bytes());
dbin_bytes.extend_from_slice(message1);

// Append message 2 length (4 bytes) and message 2 content
dbin_bytes.extend_from_slice(&(message2.len() as u32).to_be_bytes());
dbin_bytes.extend_from_slice(message2);

let mut cursor = Cursor::new(dbin_bytes);

let result = DbinFile::try_from_read(&mut cursor);
assert!(
result.is_ok(),
"Expected success for valid DBIN file with multiple messages"
);
let dbin_file = result.unwrap();
assert_eq!(dbin_file.messages.len(), 2);
assert_eq!(dbin_file.messages[0], message1.to_vec());
assert_eq!(dbin_file.messages[1], message2.to_vec());
}

#[test]
fn test_read_zero_length_message() {
let version = 0x00;
let content_type = b"ETH";
let content_version = b"00";

// Construct a valid DBIN file with a zero-length message
let mut dbin_bytes = vec![
b'd',
b'b',
b'i',
b'n', // Magic bytes
version, // File format version (0x00)
content_type[0], // Content type
content_type[1],
content_type[2],
content_version[0], // Content version
content_version[1],
];

dbin_bytes.extend_from_slice(&(0 as u32).to_be_bytes());

let mut cursor = Cursor::new(dbin_bytes);

let result = DbinFile::try_from_read(&mut cursor);
assert!(
result.is_ok(),
"Expected success for valid DBIN file with zero-length message"
);
let dbin_file = result.unwrap();
assert_eq!(dbin_file.messages.len(), 1);
assert!(dbin_file.messages[0].is_empty());
}
}
Loading

0 comments on commit 929ae2a

Please sign in to comment.