diff --git a/crates/rpc/rpc-types-compat/src/log.rs b/crates/rpc/rpc-types-compat/src/log.rs index f85dfc9be..fed647571 100644 --- a/crates/rpc/rpc-types-compat/src/log.rs +++ b/crates/rpc/rpc-types-compat/src/log.rs @@ -1,6 +1,7 @@ //! Compatibility functions for rpc `Log` type. /// Creates a new rpc Log from a primitive log type from DB +#[inline] pub fn from_primitive_log(log: reth_primitives::Log) -> reth_rpc_types::Log { reth_rpc_types::Log { address: log.address, @@ -14,3 +15,18 @@ pub fn from_primitive_log(log: reth_primitives::Log) -> reth_rpc_types::Log { removed: false, } } +/// Converts a primitive `AccessList` structure from the `reth_primitives` module into the +/// corresponding RPC type. +#[inline] +pub fn from_primitive_access_list(list: reth_primitives::AccessList) -> reth_rpc_types::AccessList { + let converted_list: Vec = list + .0 + .into_iter() + .map(|item| reth_rpc_types::AccessListItem { + address: item.address, + storage_keys: item.storage_keys, + }) + .collect(); + + reth_rpc_types::AccessList(converted_list) +} diff --git a/crates/rpc/rpc-types-compat/src/transaction/mod.rs b/crates/rpc/rpc-types-compat/src/transaction/mod.rs index 9f6a436b8..53ae7cd20 100644 --- a/crates/rpc/rpc-types-compat/src/transaction/mod.rs +++ b/crates/rpc/rpc-types-compat/src/transaction/mod.rs @@ -1,11 +1,10 @@ //! Compatibility functions for rpc `Transaction` type. mod signature; use reth_primitives::{ - AccessListItem, BlockNumber, Transaction as PrimitiveTransaction, - TransactionKind as PrimitiveTransactionKind, TransactionSignedEcRecovered, TxType, B256, U128, - U256, U64, + BlockNumber, Transaction as PrimitiveTransaction, TransactionKind as PrimitiveTransactionKind, + TransactionSignedEcRecovered, TxType, B256, U128, U256, U64, }; -use reth_rpc_types::{CallInput, CallRequest, Transaction}; +use reth_rpc_types::{AccessListItem, CallInput, CallRequest, Transaction}; use signature::from_primitive_signature; /// Create a new rpc transaction result for a mined transaction, using the given block hash, /// number, and tx index fields to populate the corresponding fields in the rpc result. diff --git a/crates/rpc/rpc-types/Cargo.toml b/crates/rpc/rpc-types/Cargo.toml index bb387fb6a..bd5875626 100644 --- a/crates/rpc/rpc-types/Cargo.toml +++ b/crates/rpc/rpc-types/Cargo.toml @@ -14,18 +14,21 @@ Reth RPC types # reth reth-primitives.workspace = true +# # ethereum +alloy-rlp = { workspace = true, features = ["arrayvec"] } + # misc -alloy-rlp.workspace = true thiserror.workspace = true itertools.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true jsonrpsee-types = { workspace = true, optional = true } + [features] default = ["jsonrpsee-types"] [dev-dependencies] # misc rand.workspace = true -similar-asserts = "1.4" +similar-asserts = "1.4" \ No newline at end of file diff --git a/crates/rpc/rpc-types/src/eth/call.rs b/crates/rpc/rpc-types/src/eth/call.rs index cfda456c4..f6073cb64 100644 --- a/crates/rpc/rpc-types/src/eth/call.rs +++ b/crates/rpc/rpc-types/src/eth/call.rs @@ -1,7 +1,7 @@ +//use crate::access_list::AccessList; use crate::BlockOverrides; use reth_primitives::{AccessList, Address, BlockId, Bytes, B256, U256, U64, U8}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; - /// Bundle of transactions #[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "camelCase")] diff --git a/crates/rpc/rpc-types/src/eth/transaction/access_list.rs b/crates/rpc/rpc-types/src/eth/transaction/access_list.rs new file mode 100644 index 000000000..a5a14ab86 --- /dev/null +++ b/crates/rpc/rpc-types/src/eth/transaction/access_list.rs @@ -0,0 +1,89 @@ +use reth_primitives::{Address, B256, U256}; +use serde::{Deserialize, Serialize}; + +/// A list of addresses and storage keys that the transaction plans to access. +/// Accesses outside the list are possible, but become more expensive. +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash, Default)] +#[serde(rename_all = "camelCase")] +pub struct AccessListItem { + /// Account addresses that would be loaded at the start of execution + pub address: Address, + /// Keys of storage that would be loaded at the start of execution + pub storage_keys: Vec, +} + +/// AccessList as defined in EIP-2930 +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash, Default)] +pub struct AccessList(pub Vec); + +impl AccessList { + /// Converts the list into a vec, expected by revm + pub fn flattened(&self) -> Vec<(Address, Vec)> { + self.flatten().collect() + } + + /// Consumes the type and converts the list into a vec, expected by revm + pub fn into_flattened(self) -> Vec<(Address, Vec)> { + self.into_flatten().collect() + } + + /// Consumes the type and returns an iterator over the list's addresses and storage keys. + pub fn into_flatten(self) -> impl Iterator)> { + self.0.into_iter().map(|item| { + ( + item.address, + item.storage_keys.into_iter().map(|slot| U256::from_be_bytes(slot.0)).collect(), + ) + }) + } + + /// Returns an iterator over the list's addresses and storage keys. + pub fn flatten(&self) -> impl Iterator)> + '_ { + self.0.iter().map(|item| { + ( + item.address, + item.storage_keys.iter().map(|slot| U256::from_be_bytes(slot.0)).collect(), + ) + }) + } +} + +/// Access list with gas used appended. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Default)] +#[serde(rename_all = "camelCase")] +pub struct AccessListWithGasUsed { + /// List with accounts accessed during transaction. + pub access_list: AccessList, + /// Estimated gas used with access list. + pub gas_used: U256, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn access_list_serde() { + let list = AccessList(vec![ + AccessListItem { address: Address::ZERO, storage_keys: vec![B256::ZERO] }, + AccessListItem { address: Address::ZERO, storage_keys: vec![B256::ZERO] }, + ]); + let json = serde_json::to_string(&list).unwrap(); + let list2 = serde_json::from_str::(&json).unwrap(); + assert_eq!(list, list2); + } + + #[test] + fn access_list_with_gas_used() { + let list = AccessListWithGasUsed { + access_list: AccessList(vec![ + AccessListItem { address: Address::ZERO, storage_keys: vec![B256::ZERO] }, + AccessListItem { address: Address::ZERO, storage_keys: vec![B256::ZERO] }, + ]), + gas_used: U256::from(100), + }; + let json = serde_json::to_string(&list).unwrap(); + let list2 = serde_json::from_str::(&json).unwrap(); + assert_eq!(list, list2); + } +} diff --git a/crates/rpc/rpc-types/src/eth/transaction/mod.rs b/crates/rpc/rpc-types/src/eth/transaction/mod.rs index 483524e2d..3f2bee65d 100644 --- a/crates/rpc/rpc-types/src/eth/transaction/mod.rs +++ b/crates/rpc/rpc-types/src/eth/transaction/mod.rs @@ -1,11 +1,13 @@ +pub use access_list::{AccessList, AccessListItem, AccessListWithGasUsed}; pub use common::TransactionInfo; pub use receipt::TransactionReceipt; pub use request::TransactionRequest; -use reth_primitives::{AccessListItem, Address, Bytes, B256, U128, U256, U64}; +use reth_primitives::{Address, Bytes, B256, U128, U256, U64}; use serde::{Deserialize, Serialize}; pub use signature::{Parity, Signature}; pub use typed::*; +mod access_list; mod common; mod receipt; mod request;