Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: implement AccessTuple conversion methods in firehose-protos #29

Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/firehose-protos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ doctest = false
path = "src/lib.rs"

[dependencies]
alloy-eip2930.workspace = true
alloy-primitives.workspace = true
ethportal-api.workspace = true
primitive-types.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions crates/firehose-protos/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ pub enum ProtosError {
#[error("GraffitiInvalid")]
GraffitiInvalid,

#[error("Invalid access tuple storage key: {0}")]
InvalidAccessTupleStorageKey(String),

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

Expand Down
86 changes: 86 additions & 0 deletions crates/firehose-protos/src/ethereum_v2/access.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use crate::error::ProtosError;

use super::AccessTuple;

use alloy_eip2930::AccessListItem;
use alloy_primitives::{hex, Address, B256};

impl TryFrom<&AccessTuple> for AccessListItem {
type Error = ProtosError;

fn try_from(tuple: &AccessTuple) -> Result<Self, Self::Error> {
let address = Address::from_slice(tuple.address.as_slice());

let storage_keys = tuple
.storage_keys
.iter()
.map(convert_to_b256)
.collect::<Result<Vec<B256>, ProtosError>>()?;

Ok(AccessListItem {
address,
storage_keys,
})
}
}

fn convert_to_b256(key: &Vec<u8>) -> Result<B256, ProtosError> {
let key_bytes: [u8; 32] = key
.as_slice()
.try_into()
.map_err(|_| ProtosError::InvalidAccessTupleStorageKey(hex::encode(key.clone())))?;
Ok(B256::from(key_bytes))
}

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

fn create_fake_access_tuple() -> AccessTuple {
AccessTuple {
address: vec![0x11; 20],
storage_keys: vec![vec![0xaa; 32], vec![0xbb; 32]],
}
}

#[test]
fn test_access_tuple_to_access_list_item_conversion() {
let fake_tuple = create_fake_access_tuple();

let access_list_item = AccessListItem::try_from(&fake_tuple).expect("Conversion failed");

assert_eq!(access_list_item.address, Address::from([0x11; 20]));
assert_eq!(
access_list_item.storage_keys.len(),
fake_tuple.storage_keys.len()
);
}

#[test]
fn test_access_tuple_with_empty_storage_keys() {
let fake_tuple = AccessTuple {
address: vec![0x11; 20],
storage_keys: vec![],
};

let access_list_item = AccessListItem::try_from(&fake_tuple).expect("Conversion failed");

assert_eq!(access_list_item.address, Address::from([0x11; 20]));
assert!(access_list_item.storage_keys.is_empty());
}

#[test]
fn test_access_tuple_storage_key_invalid_length() {
let fake_tuple = AccessTuple {
address: vec![0x11; 20],
storage_keys: vec![vec![0xaa; 31]],
};

let error = AccessListItem::try_from(&fake_tuple).unwrap_err();

assert!(matches!(
error,
ProtosError::InvalidAccessTupleStorageKey(_)
));
}
}
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 @@ -2,6 +2,7 @@
//! See the protobuffer definitions section of the README for more information.
//!

pub mod access;
pub mod eth_block;
pub mod log;
pub mod transaction;
Expand Down
29 changes: 3 additions & 26 deletions crates/flat-files-decoder/src/transactions/access_list.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,14 @@
use crate::transactions::error::TransactionError;
use alloy_eip2930::{AccessList, AccessListItem};
use alloy_primitives::{Address, B256};
use firehose_protos::ethereum_v2::AccessTuple;
use revm_primitives::hex;

pub(crate) fn compute_access_list(
access_list: &[AccessTuple],
) -> Result<AccessList, TransactionError> {
let access_list_items: Vec<AccessListItem> = access_list
let access_list_items = access_list
.iter()
.map(atuple_to_alist_item)
.collect::<Result<Vec<AccessListItem>, TransactionError>>(
)?;
.map(AccessListItem::try_from)
.collect::<Result<Vec<AccessListItem>, _>>()?;

Ok(AccessList(access_list_items))
}

fn atuple_to_alist_item(tuple: &AccessTuple) -> Result<AccessListItem, TransactionError> {
let address: Address = Address::from_slice(tuple.address.as_slice());
let storage_keys = tuple
.storage_keys
.iter()
.map(|key| {
let key_bytes: [u8; 32] = key
.as_slice()
.try_into()
.map_err(|_| TransactionError::InvalidStorageKey(hex::encode(key.clone())))?;
Ok(B256::from(key_bytes))
})
.collect::<Result<Vec<B256>, TransactionError>>()?;

Ok(AccessListItem {
address,
storage_keys,
})
}
3 changes: 3 additions & 0 deletions crates/flat-files-decoder/src/transactions/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::transactions::signature::InvalidSignatureError;
use crate::transactions::tx_type::TransactionTypeError;
use firehose_protos::error::ProtosError;
use thiserror::Error;

#[derive(Error, Debug)]
Expand All @@ -26,4 +27,6 @@ pub enum TransactionError {
MissingMaxFeePerGas,
#[error("Missing Header")]
MissingHeader,
#[error("Protos Error: {0}")]
ProtosError(#[from] ProtosError),
}
Loading