From f07feaaa5db658a5f171ff56c837e0efa3060ea5 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 8 Oct 2024 16:35:12 +0200 Subject: [PATCH] docs and cleanup --- crates/interpreter/src/gas/calc.rs | 4 +-- crates/revm/src/context/inner_evm_context.rs | 5 ++- crates/wiring/transaction/src/access_list.rs | 35 +++++++++++++++++++ crates/wiring/transaction/src/common.rs | 4 +++ crates/wiring/transaction/src/eip1559.rs | 10 ++++-- crates/wiring/transaction/src/eip2930.rs | 36 +++++--------------- crates/wiring/transaction/src/eip7702.rs | 15 ++++++++ crates/wiring/transaction/src/legacy.rs | 6 ++-- crates/wiring/transaction/src/lib.rs | 6 ++-- crates/wiring/transaction/src/transaction.rs | 32 +++++++---------- 10 files changed, 94 insertions(+), 59 deletions(-) create mode 100644 crates/wiring/transaction/src/access_list.rs diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 720683bbe9..b9af574a3b 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -2,7 +2,7 @@ use super::constants::*; use crate::{num_words, AccountLoad, Eip7702CodeLoad, SStoreResult, SelfDestructResult, StateLoad}; use primitives::U256; use specification::{eip7702, hardfork::SpecId}; -use transaction::eip2930::AccessListInterface; +use transaction::AccessListTrait; /// `const` Option `?`. macro_rules! tri { @@ -358,7 +358,7 @@ pub const fn memory_gas(num_words: u64) -> u64 { /// Initial gas that is deducted for transaction to be included. /// Initial gas contains initial stipend gas, gas for access list and input data. -pub fn validate_initial_tx_gas( +pub fn validate_initial_tx_gas( spec_id: SpecId, input: &[u8], is_create: bool, diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 88178cccb7..ae778e1947 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -1,9 +1,7 @@ -use derive_where::derive_where; -use transaction::eip2930::AccessListInterface; - use crate::{journaled_state::JournaledState, JournalCheckpoint}; use bytecode::{Bytecode, Eof, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; use database_interface::Database; +use derive_where::derive_where; use interpreter::{ gas, return_ok, AccountLoad, Eip7702CodeLoad, InstructionResult, InterpreterResult, SStoreResult, SelfDestructResult, StateLoad, @@ -15,6 +13,7 @@ use specification::hardfork::{ }; use state::Account; use std::{boxed::Box, sync::Arc}; +use transaction::AccessListTrait; use wiring::{ default::{AnalysisKind, CfgEnv, EnvWiring}, EvmWiring, Transaction, diff --git a/crates/wiring/transaction/src/access_list.rs b/crates/wiring/transaction/src/access_list.rs new file mode 100644 index 0000000000..5a83884c02 --- /dev/null +++ b/crates/wiring/transaction/src/access_list.rs @@ -0,0 +1,35 @@ +use primitives::{Address, B256}; + +/// Access list type is introduced in EIP-2930, and every +/// transaction after it contains access list. +/// +/// Note +/// +/// Iterator over access list returns account address and storage slot keys that +/// are warm loaded before transaction execution. +/// +/// Number of account and storage slots is used to calculate initial tx gas cost. +pub trait AccessListTrait { + /// Iterate over access list. + fn iter(&self) -> impl Iterator)>; + + /// Returns number of account and storage slots. + fn num_account_storages(&self) -> (usize, usize) { + let storage_num = self.iter().map(|i| i.1.count()).sum(); + let account_num = self.iter().count(); + + (account_num, storage_num) + } +} + +// TODO move to default context +use specification::eip2930::AccessList; + +impl AccessListTrait for AccessList { + fn iter(&self) -> impl Iterator)> { + self.0.iter().map(|item| { + let slots = item.storage_keys.iter().copied(); + (item.address, slots) + }) + } +} diff --git a/crates/wiring/transaction/src/common.rs b/crates/wiring/transaction/src/common.rs index eaade4b518..06fb0a2fe8 100644 --- a/crates/wiring/transaction/src/common.rs +++ b/crates/wiring/transaction/src/common.rs @@ -5,12 +5,16 @@ use primitives::{Address, Bytes, U256}; pub trait CommonTxFields { /// Caller aka Author aka transaction signer. fn caller(&self) -> Address; + /// The maximum amount of gas the transaction can use. fn gas_limit(&self) -> u64; + /// The value sent to the receiver of `TxKind::Call`. fn value(&self) -> U256; + /// Returns the input data of the transaction. fn input(&self) -> &Bytes; + /// The nonce of the transaction. fn nonce(&self) -> u64; } diff --git a/crates/wiring/transaction/src/eip1559.rs b/crates/wiring/transaction/src/eip1559.rs index 1cad032820..b797c520cc 100644 --- a/crates/wiring/transaction/src/eip1559.rs +++ b/crates/wiring/transaction/src/eip1559.rs @@ -1,5 +1,4 @@ -use super::eip2930::AccessListInterface; -use crate::CommonTxFields; +use crate::{AccessListTrait, CommonTxFields}; use primitives::TxKind; pub trait Eip1559Tx: Eip1559CommonTxFields { @@ -8,13 +7,18 @@ pub trait Eip1559Tx: Eip1559CommonTxFields { /// This trait is base for Eip1559, EIp4844 and Eip7702 transactions. pub trait Eip1559CommonTxFields: CommonTxFields { - type AccessList: AccessListInterface; + /// Access list type. + type AccessList: AccessListTrait; + /// Chain id became mandatory in all transaction after EIP-2930. fn chain_id(&self) -> u64; + /// Maximum fee per gas. fn max_fee_per_gas(&self) -> u128; + /// Maximum priority fee per gas. fn max_priority_fee_per_gas(&self) -> u128; + /// EIP-1559 access list. fn access_list(&self) -> &Self::AccessList; } diff --git a/crates/wiring/transaction/src/eip2930.rs b/crates/wiring/transaction/src/eip2930.rs index 5c937a4355..1513eefdfc 100644 --- a/crates/wiring/transaction/src/eip2930.rs +++ b/crates/wiring/transaction/src/eip2930.rs @@ -1,39 +1,19 @@ -use crate::CommonTxFields; -use primitives::{Address, TxKind, B256}; - -// TODO move to specs impl iterator trait -pub trait AccessListInterface { - fn iter(&self) -> impl Iterator)>; - - /// Not performant way to count number of account and storages. - fn num_account_storages(&self) -> (usize, usize) { - let storage_num = self.iter().map(|i| i.1.count()).sum(); - let account_num = self.iter().count(); - - (account_num, storage_num) - } -} +use crate::{AccessListTrait, CommonTxFields}; +use primitives::TxKind; +/// EIP-2930: Optional access lists pub trait Eip2930Tx: CommonTxFields { - type AccessList: AccessListInterface; + type AccessList: AccessListTrait; + /// The chain ID of the chain the transaction is intended for. fn chain_id(&self) -> u64; + /// The gas price of the transaction. fn gas_price(&self) -> u128; + /// The kind of transaction. fn kind(&self) -> TxKind; + /// The access list of the transaction. fn access_list(&self) -> &Self::AccessList; } - -// TODO move to default context -use specification::eip2930::AccessList; - -impl AccessListInterface for AccessList { - fn iter(&self) -> impl Iterator)> { - self.0.iter().map(|item| { - let slots = item.storage_keys.iter().copied(); - (item.address, slots) - }) - } -} diff --git a/crates/wiring/transaction/src/eip7702.rs b/crates/wiring/transaction/src/eip7702.rs index 0c3b920440..8e67bd909a 100644 --- a/crates/wiring/transaction/src/eip7702.rs +++ b/crates/wiring/transaction/src/eip7702.rs @@ -32,6 +32,9 @@ pub trait Authorization { /// /// Authority signature can be invalid, so this method returns None if the authority /// could not be recovered. + /// + /// Valid signature Parity should be 0 or 1 and + /// signature s-value should be less than SECP256K1N_HALF. fn authority(&self) -> Option
; /// Returns authorization the chain id. @@ -59,22 +62,34 @@ pub trait Authorization { use specification::eip7702::RecoveredAuthorization; impl Authorization for RecoveredAuthorization { + /// Authority address. Obtained by recovering of the signature. fn authority(&self) -> Option
{ self.authority() } + /// Returns authorization the chain id. fn chain_id(&self) -> U256 { self.inner().chain_id() } + /// Returns the nonce. + /// + /// # Note + /// + /// If nonce is not same as the nonce of the signer account, + /// authorization is skipped and considered invalidated. fn nonce(&self) -> u64 { self.inner().nonce() } + /// Returns the address that this account should delegate to. fn address(&self) -> Address { *self.inner().address() } + /// Returns true if the authorization is valid. + /// + /// Temporary method needed for older EIP spec and will removed in future fn is_invalid(&self) -> bool { use specification::{eip2::SECP256K1N_HALF, eip7702::Parity}; diff --git a/crates/wiring/transaction/src/legacy.rs b/crates/wiring/transaction/src/legacy.rs index f027d00ce1..3506141b1c 100644 --- a/crates/wiring/transaction/src/legacy.rs +++ b/crates/wiring/transaction/src/legacy.rs @@ -1,13 +1,15 @@ use crate::CommonTxFields; use primitives::TxKind; +/// Legacy transaction trait before introduction of EIP-2929 pub trait LegacyTx: CommonTxFields { - /// Legacy transaction kind + /// Transaction kind. fn kind(&self) -> TxKind; /// Chain Id is optional for legacy transactions + /// As it was introduced in EIP-155. fn chain_id(&self) -> Option; - /// Gas price for the transaction + /// Gas price for the transaction. fn gas_price(&self) -> u128; } diff --git a/crates/wiring/transaction/src/lib.rs b/crates/wiring/transaction/src/lib.rs index f54807b2d0..f418819496 100644 --- a/crates/wiring/transaction/src/lib.rs +++ b/crates/wiring/transaction/src/lib.rs @@ -2,9 +2,10 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(feature = "std"), no_std)] -// #[cfg(not(feature = "std"))] -// extern crate alloc as std; +#[cfg(not(feature = "std"))] +extern crate alloc as std; +mod access_list; mod common; pub mod eip1559; pub mod eip2930; @@ -14,6 +15,7 @@ pub mod legacy; pub mod transaction; pub mod transaction_type; +pub use access_list::AccessListTrait; pub use common::CommonTxFields; pub use eip1559::{Eip1559CommonTxFields, Eip1559Tx}; pub use eip2930::Eip2930Tx; diff --git a/crates/wiring/transaction/src/transaction.rs b/crates/wiring/transaction/src/transaction.rs index 83cd57df33..8f241b6e7d 100644 --- a/crates/wiring/transaction/src/transaction.rs +++ b/crates/wiring/transaction/src/transaction.rs @@ -1,6 +1,6 @@ use crate::{ - eip1559::Eip1559CommonTxFields, eip2930::AccessListInterface, CommonTxFields, Eip1559Tx, - Eip2930Tx, Eip4844Tx, Eip7702Tx, LegacyTx, TransactionType, + eip1559::Eip1559CommonTxFields, AccessListTrait, CommonTxFields, Eip1559Tx, Eip2930Tx, + Eip4844Tx, Eip7702Tx, LegacyTx, TransactionType, }; use core::cmp::min; use core::fmt::Debug; @@ -18,9 +18,10 @@ pub trait TransactionError: Debug + core::error::Error {} pub trait Transaction { /// An error that occurs when validating a transaction. type TransactionError: TransactionError; + /// Transaction type. type TransactionType: Into; - - type AccessList: AccessListInterface; + /// Access list type. + type AccessList: AccessListTrait; type Legacy: LegacyTx; type Eip2930: Eip2930Tx; @@ -32,26 +33,32 @@ pub trait Transaction { /// If transaction is Legacy, then `legacy()` should be called. fn tx_type(&self) -> Self::TransactionType; + /// Legacy transaction. fn legacy(&self) -> &Self::Legacy { unimplemented!("legacy tx not supported") } + /// EIP-2930 transaction. fn eip2930(&self) -> &Self::Eip2930 { unimplemented!("Eip2930 tx not supported") } + /// EIP-1559 transaction. fn eip1559(&self) -> &Self::Eip1559 { unimplemented!("Eip1559 tx not supported") } + /// EIP-4844 transaction. fn eip4844(&self) -> &Self::Eip4844 { unimplemented!("Eip4844 tx not supported") } + /// EIP-7702 transaction. fn eip7702(&self) -> &Self::Eip7702 { unimplemented!("Eip7702 tx not supported") } + /// Common fields for all transactions. fn common_fields(&self) -> &dyn CommonTxFields { match self.tx_type().into() { TransactionType::Legacy => self.legacy(), @@ -63,6 +70,7 @@ pub trait Transaction { } } + /// Maximum fee that can be paid for the transaction. fn max_fee(&self) -> u128 { match self.tx_type().into() { TransactionType::Legacy => self.legacy().gas_price(), @@ -99,6 +107,7 @@ pub trait Transaction { min(U256::from(max_fee), base_fee + U256::from(max_priority_fee)) } + /// Transaction kind. fn kind(&self) -> TxKind { let tx_type = self.tx_type().into(); match tx_type { @@ -124,18 +133,3 @@ pub trait Transaction { } } } - -pub trait TransactionExt { - fn effective_gas_price(&self, base_fee: U256) -> U256; -} - -// impl TransactionExt for Tx { -// fn effective_gas_price(&self, base_fee: U256) -> U256 { -// Transaction::effective_gas_price(self, base_fee) -// } - -// fn data(&self) -> &[u8] { -// self.common_fields().input().as_ref() -// } - -// }