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

refac: rm 2930 and 7702 - use alloy-rs/eips #1181

Merged
merged 7 commits into from
Aug 28, 2024
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
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",
yash-atreya marked this conversation as resolved.
Show resolved Hide resolved
"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
yash-atreya marked this conversation as resolved.
Show resolved Hide resolved
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