Skip to content

Commit

Permalink
refactor(decoder): move receipt log conversions to firehose-protos
Browse files Browse the repository at this point in the history
  • Loading branch information
suchapalaver committed Oct 25, 2024
1 parent 07e4c8d commit 5caf784
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 118 deletions.
152 changes: 76 additions & 76 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions crates/firehose-protos/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ pub enum ProtosError {
#[error("GraffitiInvalid")]
GraffitiInvalid,

#[error("Invalid log address: {0}")]
InvalidLogAddress(String),

#[error("Invalid log topic: {0}")]
InvalidLogTopic(String),

#[error("KzgCommitmentInvalid")]
KzgCommitmentInvalid,

Expand Down
157 changes: 157 additions & 0 deletions crates/firehose-protos/src/ethereum_v2/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use alloy_primitives::{hex, Address, Bytes, B256};
use reth_primitives::LogData;

use crate::error::ProtosError;

use super::Log;

impl TryFrom<&Log> for alloy_primitives::Log {
type Error = ProtosError;

fn try_from(log: &Log) -> Result<Self, Self::Error> {
let address = Address::try_from(log)?;
let topics = log.to_topics()?;
let log_data = Bytes::copy_from_slice(log.data.as_slice());
let data = LogData::new_unchecked(topics, log_data);

Ok(alloy_primitives::Log { address, data })
}
}

impl TryFrom<&Log> for Address {
type Error = ProtosError;

fn try_from(log: &Log) -> Result<Self, Self::Error> {
let slice: [u8; 20] = log
.address
.as_slice()
.try_into()
.map_err(|_| Self::Error::InvalidLogAddress(hex::encode(log.address.clone())))?;
Ok(Address::from(slice))
}
}

impl Log {
fn to_topics(&self) -> Result<Vec<B256>, ProtosError> {
fn to_b256(slice: &[u8]) -> Result<B256, ProtosError> {
B256::try_from(slice).map_err(|_| ProtosError::InvalidLogTopic(hex::encode(slice)))
}

self.topics
.iter()
.map(Vec::as_slice)
.map(to_b256)
.collect::<Result<Vec<_>, _>>()
}
}

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

fn create_mock_log_with(address: Vec<u8>, data: Vec<u8>, topics: Vec<Vec<u8>>) -> Log {
Log {
address,
data,
topics,
..Default::default()
}
}

fn create_mock_log() -> Log {
create_mock_log_with(
vec![0x11; 20],
vec![0xde, 0xad, 0xbe, 0xef],
vec![vec![0xff; 32], vec![0xaa; 32]],
)
}

#[test]
fn test_log_to_alloy_log_conversion() {
let mock_log = create_mock_log();

let alloy_log = alloy_primitives::Log::try_from(&mock_log).expect("Conversion failed");

assert_eq!(alloy_log.address, Address::from([0x11; 20]));
assert_eq!(alloy_log.data.data.as_ref(), mock_log.data.as_slice());
assert_eq!(alloy_log.data.topics().len(), mock_log.topics.len());
}

#[test]
fn test_log_to_address_conversion() {
let mock_log = create_mock_log();

let address = Address::try_from(&mock_log).expect("Conversion failed");

assert_eq!(address, Address::from([0x11; 20]));
}

#[test]
fn test_log_to_topics_conversion() {
let mock_log = create_mock_log();

let topics = mock_log.to_topics().expect("Conversion to topics failed");

assert_eq!(topics.len(), 2);
assert_eq!(topics[0], B256::from([0xff; 32]));
assert_eq!(topics[1], B256::from([0xaa; 32]));
}

#[test]
fn test_log_address_conversion_invalid_length() {
let mock_log = Log {
address: vec![0x12; 18],
data: vec![],
topics: vec![],
..Default::default()
};

let error = Address::try_from(&mock_log).unwrap_err();

assert!(matches!(error, ProtosError::InvalidLogAddress(_)));
}

#[test]
fn test_log_to_topics_conversion_invalid_topic_length() {
let mock_log = Log {
address: vec![],
data: vec![],
topics: vec![vec![0xaa; 31]],
..Default::default()
};

let error = mock_log.to_topics().unwrap_err();

assert!(matches!(error, ProtosError::InvalidLogTopic(_)));
}

#[test]
fn test_log_data_creation() {
let mock_log = Log {
address: vec![0x11; 20],
data: vec![0xde, 0xad, 0xbe, 0xef],
topics: vec![vec![0xff; 32], vec![0xaa; 32]],
..Default::default()
};

let alloy_log = alloy_primitives::Log::try_from(&mock_log).expect("Conversion failed");
let log_data = alloy_log.data;

assert_eq!(log_data.data.as_ref(), mock_log.data.as_slice());
assert_eq!(log_data.topics().len(), mock_log.topics.len());
}

#[test]
fn test_log_with_empty_data() {
let mock_log = Log {
data: vec![],
..create_mock_log()
};

let alloy_log = alloy_primitives::Log::try_from(&mock_log).expect("Conversion failed");

assert_eq!(alloy_log.address, Address::from([0x11; 20]));
assert_eq!(alloy_log.data.data.as_ref(), mock_log.data.as_slice());
assert_eq!(alloy_log.data.topics().len(), mock_log.topics.len());
}
}
1 change: 1 addition & 0 deletions crates/firehose-protos/src/ethereum_v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//!

pub mod eth_block;
pub mod log;
pub mod transaction;

tonic::include_proto!("sf.ethereum.r#type.v2");
3 changes: 3 additions & 0 deletions crates/flat-files-decoder/src/receipts/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::transactions::tx_type::TransactionTypeError;
use firehose_protos::error::ProtosError;
use thiserror::Error;

#[derive(Error, Debug)]
Expand All @@ -19,4 +20,6 @@ pub enum ReceiptError {
MissingRoot,
#[error("Missing receipt")]
MissingReceipt,
#[error("Protos error: {0}")]
ProtosError(#[from] ProtosError),
}
39 changes: 0 additions & 39 deletions crates/flat-files-decoder/src/receipts/logs.rs

This file was deleted.

1 change: 0 additions & 1 deletion crates/flat-files-decoder/src/receipts/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pub mod error;
pub mod logs;
pub mod receipt;

use crate::receipts::error::ReceiptError;
Expand Down
8 changes: 6 additions & 2 deletions crates/flat-files-decoder/src/receipts/receipt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::receipts::error::ReceiptError;
use crate::receipts::logs::map_logs;
use crate::transactions::tx_type::map_tx_type;
use alloy_primitives::{Bloom, FixedBytes};
use firehose_protos::ethereum_v2::TransactionTrace;
Expand All @@ -21,7 +20,12 @@ impl TryFrom<&TransactionTrace> for FullReceipt {
Some(receipt) => receipt,
None => return Err(ReceiptError::MissingReceipt),
};
let logs: Vec<Log> = map_logs(&trace_receipt.logs)?;
let logs = trace_receipt
.logs
.iter()
.map(Log::try_from)
.collect::<Result<Vec<_>, _>>()?;

let cumulative_gas_used = trace_receipt.cumulative_gas_used;

let receipt = Receipt {
Expand Down

0 comments on commit 5caf784

Please sign in to comment.