Skip to content

Commit

Permalink
refac: rm 2930 and 7702 - use alloy-rs/eips (#1181)
Browse files Browse the repository at this point in the history
* refac(alloy-eips): use alloy-rs/eips for 2930 and 7702

* fix: rev

* reintroduce k256 to eips + fmt nits

* nit: README.md

* bump eips

* bump eips
  • Loading branch information
yash-atreya authored Aug 28, 2024
1 parent e1489b7 commit 7968af7
Show file tree
Hide file tree
Showing 12 changed files with 24 additions and 604 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ alloy-rlp = { version = "0.3", default-features = false }

alloy-chains = { version = "0.1.18", default-features = false }

# eips
alloy-eip2930 = { version = "0.1.0", default-features = false }
alloy-eip7702 = { version = "0.1.0", default-features = false }

# ethereum
ethereum_ssz_derive = "0.7.1"
ethereum_ssz = "0.7.1"
Expand Down
2 changes: 1 addition & 1 deletion crates/alloy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,9 @@ arbitrary = [
k256 = [
"alloy-core/k256",
"alloy-consensus?/k256",
"alloy-eips?/k256",
"alloy-network?/k256",
"alloy-rpc-types?/k256",
"alloy-eips?/k256",
]
kzg = ["alloy-consensus?/kzg", "alloy-rpc-types?/kzg"]
eip712 = [
Expand Down
6 changes: 1 addition & 5 deletions crates/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,7 @@ default = ["std"]
std = ["alloy-eips/std", "c-kzg?/std"]
k256 = ["alloy-primitives/k256", "alloy-eips/k256"]
kzg = ["dep:c-kzg", "alloy-eips/kzg", "std"]
arbitrary = [
"std",
"dep:arbitrary",
"alloy-eips/arbitrary",
]
arbitrary = ["std", "dep:arbitrary", "alloy-eips/arbitrary"]
serde = [
"dep:serde",
"alloy-primitives/serde",
Expand Down
30 changes: 12 additions & 18 deletions crates/eips/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ rustdoc-args = ["--cfg", "docsrs"]
workspace = true

[dependencies]
# eips
alloy-eip2930.workspace = true
alloy-eip7702.workspace = true

alloy-primitives = { workspace = true, features = ["rlp"] }
alloy-rlp = { workspace = true, features = ["derive"] }

Expand All @@ -43,9 +47,6 @@ ethereum_ssz = { workspace = true, optional = true }
# arbitrary
arbitrary = { workspace = true, features = ["derive"], optional = true }

# for signed authorization list arbitrary
k256 = { workspace = true, optional = true }
rand = { workspace = true, optional = true }

[dev-dependencies]
alloy-primitives = { workspace = true, features = [
Expand All @@ -58,29 +59,22 @@ serde_json.workspace = true

[features]
default = ["std", "kzg-sidecar"]
std = [
"alloy-primitives/std",
"alloy-rlp/std",
"serde?/std",
"c-kzg?/std",
"once_cell?/std",
]
serde = [
"dep:alloy-serde",
"dep:serde",
"alloy-primitives/serde",
"c-kzg?/serde",
]
std = ["alloy-primitives/std", "alloy-rlp/std",
"serde?/std", "c-kzg?/std", "once_cell?/std"]
serde = ["dep:alloy-serde", "dep:serde", "alloy-primitives/serde",
"c-kzg?/serde", "alloy-eip2930/serde", "alloy-eip7702/serde"]
kzg = ["kzg-sidecar", "sha2", "dep:derive_more", "dep:c-kzg", "dep:once_cell"]
kzg-sidecar = ["sha2"]
k256 = ["alloy-eip7702/k256"]
sha2 = ["dep:sha2"]
k256 = ["alloy-primitives/k256", "dep:k256"]
ssz = ["std", "dep:ethereum_ssz", "dep:ethereum_ssz_derive"]
arbitrary = [
"std",
"kzg-sidecar",
"dep:arbitrary",
"dep:rand",
"alloy-primitives/arbitrary",
"alloy-serde?/arbitrary",
"alloy-eip2930/arbitrary",
"alloy-eip7702/arbitrary",
"alloy-eip7702/k256",
]
2 changes: 2 additions & 0 deletions crates/eips/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Ethereum Improvement Proprosal (EIP) implementations.

Contains constants, helpers, and basic data structures for consensus EIPs.

EIPs 2930 and 7702 are re-exported from [alloy-rs/eips](https://github.com/alloy-rs/eips).

## Current support

- [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)
Expand Down
208 changes: 2 additions & 206 deletions crates/eips/src/eip2930.rs
Original file line number Diff line number Diff line change
@@ -1,206 +1,2 @@
//! [EIP-2930] types.
//!
//! [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};

use alloy_primitives::{Address, B256, U256};
use alloy_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper};
use core::{mem, ops::Deref};
/// A list of addresses and storage keys that the transaction plans to access.
/// Accesses outside the list are possible, but become more expensive.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, RlpDecodable, RlpEncodable)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", 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<B256>,
}

impl AccessListItem {
/// Calculates a heuristic for the in-memory size of the [AccessListItem].
#[inline]
pub fn size(&self) -> usize {
mem::size_of::<Address>() + self.storage_keys.capacity() * mem::size_of::<B256>()
}
}

/// AccessList as defined in EIP-2930
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, RlpDecodableWrapper, RlpEncodableWrapper)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AccessList(pub Vec<AccessListItem>);

impl From<Vec<AccessListItem>> for AccessList {
fn from(list: Vec<AccessListItem>) -> Self {
Self(list)
}
}

impl From<AccessList> for Vec<AccessListItem> {
fn from(this: AccessList) -> Self {
this.0
}
}

impl Deref for AccessList {
type Target = Vec<AccessListItem>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl AccessList {
/// Converts the list into a vec, expected by revm
pub fn flattened(&self) -> Vec<(Address, Vec<U256>)> {
self.flatten().collect()
}

/// Consumes the type and converts the list into a vec, expected by revm
pub fn into_flattened(self) -> Vec<(Address, Vec<U256>)> {
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<Item = (Address, Vec<U256>)> {
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<Item = (Address, Vec<U256>)> + '_ {
self.0.iter().map(|item| {
(
item.address,
item.storage_keys.iter().map(|slot| U256::from_be_bytes(slot.0)).collect(),
)
})
}

/// Returns the position of the given address in the access list, if present.
fn index_of_address(&self, address: Address) -> Option<usize> {
self.iter().position(|item| item.address == address)
}

/// Checks if a specific storage slot within an account is present in the access list.
///
/// Returns a tuple with flags for the presence of the account and the slot.
pub fn contains_storage(&self, address: Address, slot: B256) -> (bool, bool) {
self.index_of_address(address)
.map_or((false, false), |idx| (true, self.contains_storage_key_at_index(slot, idx)))
}

/// Checks if the access list contains the specified address.
pub fn contains_address(&self, address: Address) -> bool {
self.iter().any(|item| item.address == address)
}

/// Checks if the storage keys at the given index within an account are present in the access
/// list.
fn contains_storage_key_at_index(&self, slot: B256, index: usize) -> bool {
self.get(index).map_or(false, |entry| {
entry.storage_keys.iter().any(|storage_key| *storage_key == slot)
})
}

/// Adds an address to the access list and returns `true` if the operation results in a change,
/// indicating that the address was not previously present.
pub fn add_address(&mut self, address: Address) -> bool {
!self.contains_address(address) && {
self.0.push(AccessListItem { address, storage_keys: Vec::new() });
true
}
}

/// Calculates a heuristic for the in-memory size of the [AccessList].
#[inline]
pub fn size(&self) -> usize {
// take into account capacity
self.0.iter().map(AccessListItem::size).sum::<usize>()
+ self.0.capacity() * mem::size_of::<AccessListItem>()
}
}

/// Access list with gas used appended.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", 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,
}

/// `AccessListResult` for handling errors from `eth_createAccessList`
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct AccessListResult {
/// List with accounts accessed during transaction.
pub access_list: AccessList,
/// Estimated gas used with access list.
pub gas_used: U256,
/// Optional error message if the transaction failed.
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Option::is_none"))]
pub error: Option<String>,
}

impl AccessListResult {
/// Ensures the result is OK, returning [`AccessListWithGasUsed`] if so, or an error message if
/// not.
pub fn ensure_ok(self) -> Result<AccessListWithGasUsed, String> {
match self.error {
Some(err) => Err(err),
None => {
Ok(AccessListWithGasUsed { access_list: self.access_list, gas_used: self.gas_used })
}
}
}

/// Checks if there is an error in the result.
#[inline]
pub const fn is_err(&self) -> bool {
self.error.is_some()
}
}

#[cfg(all(test, feature = "serde"))]
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::<AccessList>(&json).unwrap();
assert_eq!(list, list2);
}

#[test]
fn access_list_with_gas_used() {
let list = AccessListResult {
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),
error: None,
};
let json = serde_json::to_string(&list).unwrap();
let list2 = serde_json::from_str(&json).unwrap();
assert_eq!(list, list2);
}
}
//! Re-export the EIP-2930 types.
pub use alloy_eip2930::*;
2 changes: 2 additions & 0 deletions crates/eips/src/eip7702.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//! Re-export the EIP-7702 types.
pub use alloy_eip7702::*;
Loading

0 comments on commit 7968af7

Please sign in to comment.