From be1d324298b6a1e20f8b17aff34f95206304117b Mon Sep 17 00:00:00 2001 From: Roy <42067944+royvardhan@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:15:42 +0530 Subject: [PATCH] feat: use TestAuthorization and skip decoding of eip7702 tx (#1785) --- .../revme/src/cmd/statetest/models/eip7702.rs | 122 ------------------ bins/revme/src/cmd/statetest/models/mod.rs | 59 +++++---- bins/revme/src/cmd/statetest/runner.rs | 16 ++- 3 files changed, 43 insertions(+), 154 deletions(-) delete mode 100644 bins/revme/src/cmd/statetest/models/eip7702.rs diff --git a/bins/revme/src/cmd/statetest/models/eip7702.rs b/bins/revme/src/cmd/statetest/models/eip7702.rs deleted file mode 100644 index 50883a2cb3..0000000000 --- a/bins/revme/src/cmd/statetest/models/eip7702.rs +++ /dev/null @@ -1,122 +0,0 @@ -use alloy_rlp::{Decodable, Error as RlpError, Header}; -use revm::{ - primitives::{Bytes, TxKind, U256}, - specification::{ - eip2930::AccessList, - eip7702::{Signature, SignedAuthorization}, - }, -}; - -use std::vec::Vec; - -/// TODO remove it when new tests are generated that has a Authorization json field. -/// [EIP-7702 Set Code Transaction](https://eips.ethereum.org/EIPS/eip-7702) -/// -/// Set EOA account code for one transaction -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TxEip7702 { - /// Added as EIP-155: Simple replay attack protection - pub chain_id: u64, - /// A scalar value equal to the number of transactions sent by the sender; formally Tn. - pub nonce: u64, - /// A scalar value equal to the number of - /// Wei to be paid per unit of gas for all computation - /// costs incurred as a result of the execution of this transaction; formally Tp. - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - pub gas_limit: u64, - /// A scalar value equal to the maximum - /// amount of gas that should be used in executing - /// this transaction. This is paid up-front, before any - /// computation is done and may not be increased - /// later; formally Tg. - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - /// - /// This is also known as `GasFeeCap` - pub max_fee_per_gas: u128, - /// Max Priority fee that transaction is paying - /// - /// As ethereum circulation is around 120mil eth as of 2022 that is around - /// 120000000000000000000000000 wei we are safe to use u128 as its max number is: - /// 340282366920938463463374607431768211455 - /// - /// This is also known as `GasTipCap` - pub max_priority_fee_per_gas: u128, - /// The 160-bit address of the message call’s recipient or, for a contract creation - /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. - pub to: TxKind, - /// A scalar value equal to the number of Wei to - /// be transferred to the message call’s recipient or, - /// in the case of contract creation, as an endowment - /// to the newly created account; formally Tv. - pub value: U256, - /// The accessList specifies a list of addresses and storage keys; - /// these addresses and storage keys are added into the `accessed_addresses` - /// and `accessed_storage_keys` global sets (introduced in EIP-2929). - /// A gas cost is charged, though at a discount relative to the cost of - /// accessing outside the list. - pub access_list: AccessList, - /// Authorizations are used to temporarily set the code of its signer to - /// the code referenced by `address`. These also include a `chain_id` (which - /// can be set to zero and not evaluated) as well as an optional `nonce`. - pub authorization_list: Vec, - /// Input has two uses depending if the transaction `to` field is [`TxKind::Create`] or - /// [`TxKind::Call`]. - /// - /// Input as init code, or if `to` is [`TxKind::Create`]: An unlimited size byte array - /// specifying the EVM-code for the account initialisation procedure `CREATE` - /// - /// Input as data, or if `to` is [`TxKind::Call`]: An unlimited size byte array specifying the - /// input data of the message call, formally Td. - pub input: Bytes, - pub signature: Signature, -} - -impl TxEip7702 { - /// Decodes the inner [`TxEip7702`] fields from RLP bytes. - /// - /// NOTE: This assumes a RLP header has already been decoded, and _just_ decodes the following - /// RLP fields in the following order: - /// - /// - `chain_id` - /// - `nonce` - /// - `gas_price` - /// - `gas_limit` - /// - `to` - /// - `value` - /// - `data` (`input`) - /// - `access_list` - /// - `authorization_list` - fn decode_inner(buf: &mut &[u8]) -> alloy_rlp::Result { - Ok(Self { - chain_id: Decodable::decode(buf)?, - nonce: Decodable::decode(buf)?, - max_priority_fee_per_gas: Decodable::decode(buf)?, - max_fee_per_gas: Decodable::decode(buf)?, - gas_limit: Decodable::decode(buf)?, - to: Decodable::decode(buf)?, - value: Decodable::decode(buf)?, - input: Decodable::decode(buf)?, - access_list: Decodable::decode(buf)?, - authorization_list: Decodable::decode(buf)?, - signature: Signature::decode_rlp_vrs(buf)?, - }) - } - - pub fn decode(data: &mut &[u8]) -> alloy_rlp::Result { - // decode the list header for the rest of the transaction - let header = Header::decode(data)?; - if !header.list { - return Err(RlpError::Custom( - "typed tx fields must be encoded as a list", - )); - } - let tx = TxEip7702::decode_inner(data)?; - Ok(tx) - } -} diff --git a/bins/revme/src/cmd/statetest/models/mod.rs b/bins/revme/src/cmd/statetest/models/mod.rs index 97959b27d8..d3c46ec898 100644 --- a/bins/revme/src/cmd/statetest/models/mod.rs +++ b/bins/revme/src/cmd/statetest/models/mod.rs @@ -1,14 +1,16 @@ mod deserializer; -mod eip7702; mod spec; use deserializer::*; -pub use eip7702::TxEip7702; + pub use spec::SpecName; use revm::{ primitives::{Address, Bytes, HashMap, B256, U256}, - specification::{eip2930::AccessList, eip7702::AuthorizationList}, + specification::{ + eip2930::AccessList, + eip7702::{Authorization, Parity, RecoveredAuthorization, Signature}, + }, }; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -52,26 +54,6 @@ pub struct Test { pub txbytes: Option, } -impl Test { - pub fn eip7702_authorization_list( - &self, - ) -> Result, alloy_rlp::Error> { - let Some(txbytes) = self.txbytes.as_ref() else { - return Ok(None); - }; - - if txbytes.first() == Some(&0x04) { - let mut txbytes = &txbytes[1..]; - let tx = TxEip7702::decode(&mut txbytes)?; - return Ok(Some( - AuthorizationList::Signed(tx.authorization_list).into_recovered(), - )); - } - - Ok(None) - } -} - #[derive(Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct TxPartIndices { @@ -130,16 +112,15 @@ pub struct TransactionParts { #[serde(default)] pub access_lists: Vec>, - #[serde(default)] - pub authorization_list: Vec, + pub authorization_list: Option>, #[serde(default)] pub blob_versioned_hashes: Vec, pub max_fee_per_blob_gas: Option, } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy)] #[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct Authorization { +pub struct TestAuthorization { chain_id: U256, address: Address, nonce: U256, @@ -149,6 +130,30 @@ pub struct Authorization { signer: Option
, } +impl TestAuthorization { + pub fn signature(&self) -> Signature { + let v = u64::try_from(self.v).unwrap_or(u64::MAX); + let parity = Parity::try_from(v).unwrap_or(Parity::Eip155(36)); + Signature::from_rs_and_parity(self.r, self.s, parity).unwrap() + } + + pub fn into_recovered(self) -> RecoveredAuthorization { + let authorization = Authorization { + chain_id: self.chain_id, + address: self.address, + nonce: u64::try_from(self.nonce).unwrap(), + }; + let authority = self + .signature() + .recover_address_from_prehash(&authorization.signature_hash()) + .ok(); + RecoveredAuthorization::new_unchecked( + authorization.into_signed(self.signature()), + authority, + ) + } +} + #[cfg(test)] mod tests { diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index c6adcd186a..83b6a0a48f 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -12,7 +12,7 @@ use revm::{ inspectors::TracerEip3155, interpreter::analysis::to_analysed, primitives::{keccak256, Bytes, TxKind, B256}, - specification::hardfork::SpecId, + specification::{eip7702::AuthorizationList, hardfork::SpecId}, wiring::{ block::calc_excess_blob_gas, default::EnvWiring, @@ -378,10 +378,16 @@ pub fn execute_test_suite( .and_then(Option::as_deref) .cloned() .unwrap_or_default(); - let Ok(auth_list) = test.eip7702_authorization_list() else { - continue; - }; - env.tx.authorization_list = auth_list; + + env.tx.authorization_list = + unit.transaction + .authorization_list + .as_ref() + .map(|auth_list| { + AuthorizationList::Recovered( + auth_list.iter().map(|auth| auth.into_recovered()).collect(), + ) + }); let to = match unit.transaction.to { Some(add) => TxKind::Call(add),