Skip to content

Commit

Permalink
chore: force merge with main
Browse files Browse the repository at this point in the history
  • Loading branch information
royvardhan committed Sep 18, 2024
1 parent 0c962fd commit a4c37c0
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 45 deletions.
122 changes: 122 additions & 0 deletions bins/revme/src/cmd/statetest/models/eip7702.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
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<SignedAuthorization>,
/// 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<Self> {
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<Self> {
// 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)
}
}
59 changes: 29 additions & 30 deletions bins/revme/src/cmd/statetest/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
mod deserializer;
mod eip7702;
mod spec;

use deserializer::*;
pub use eip7702::TxEip7702;
pub use spec::SpecName;

use revm::primitives::{
alloy_primitives::Parity, AccessList, Address, Authorization, Bytes, HashMap,
RecoveredAuthorization, Signature, B256, U256,
use revm::{
primitives::{Address, Bytes, HashMap, B256, U256},
specification::{eip2930::AccessList, eip7702::AuthorizationList},
};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
Expand Down Expand Up @@ -50,6 +52,26 @@ pub struct Test {
pub txbytes: Option<Bytes>,
}

impl Test {
pub fn eip7702_authorization_list(
&self,
) -> Result<Option<AuthorizationList>, 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 {
Expand Down Expand Up @@ -108,15 +130,16 @@ pub struct TransactionParts {

#[serde(default)]
pub access_lists: Vec<Option<AccessList>>,
pub authorization_list: Option<Vec<TestAuthorization>>,
#[serde(default)]
pub authorization_list: Vec<Authorization>,
#[serde(default)]
pub blob_versioned_hashes: Vec<B256>,
pub max_fee_per_blob_gas: Option<U256>,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct TestAuthorization {
pub struct Authorization {
chain_id: U256,
address: Address,
nonce: U256,
Expand All @@ -126,30 +149,6 @@ pub struct TestAuthorization {
signer: Option<Address>,
}

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 {

Expand Down
32 changes: 17 additions & 15 deletions bins/revme/src/cmd/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ use super::{
};
use indicatif::{ProgressBar, ProgressDrawTarget};
use revm::{
db::{EmptyDB, State},
bytecode::Bytecode,
database_interface::EmptyDB,
db::State,
inspector_handle_register,
inspectors::TracerEip3155,
interpreter::analysis::to_analysed,
primitives::{
calc_excess_blob_gas, keccak256, AuthorizationList, Bytecode, Bytes, EVMResultGeneric,
EnvWiring, EthereumWiring, ExecutionResult, HaltReason, SpecId, TxKind, B256,
primitives::{keccak256, Bytes, TxKind, B256},
specification::hardfork::SpecId,
wiring::{
block::calc_excess_blob_gas,
default::EnvWiring,
result::{EVMResultGeneric, ExecutionResult, HaltReason},
EthereumWiring,
},
Evm,
};
Expand Down Expand Up @@ -274,7 +280,7 @@ pub fn execute_test_suite(
for (address, info) in unit.pre {
let code_hash = keccak256(&info.code);
let bytecode = to_analysed(Bytecode::new_raw(info.code));
let acc_info = revm::primitives::AccountInfo {
let acc_info = revm::state::AccountInfo {
balance: info.balance,
code_hash,
code: Some(bytecode),
Expand Down Expand Up @@ -372,16 +378,10 @@ pub fn execute_test_suite(
.and_then(Option::as_deref)
.cloned()
.unwrap_or_default();

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 Ok(auth_list) = test.eip7702_authorization_list() else {
continue;
};
env.tx.authorization_list = auth_list;

let to = match unit.transaction.to {
Some(add) => TxKind::Call(add),
Expand Down Expand Up @@ -410,6 +410,7 @@ pub fn execute_test_suite(
.with_external_context(
TracerEip3155::new(Box::new(stderr())).without_summary(),
)
.with_spec_id(spec_id)
.append_handler_register(inspector_handle_register)
.build();

Expand Down Expand Up @@ -472,6 +473,7 @@ pub fn execute_test_suite(
.with_env(env.clone())
.reset_handler_with_external_context::<EthereumWiring<_, TracerEip3155>>()
.with_external_context(TracerEip3155::new(Box::new(stdout())).without_summary())
.with_spec_id(spec_id)
.append_handler_register(inspector_handle_register)
.build();
let _ = evm.transact_commit();
Expand Down

0 comments on commit a4c37c0

Please sign in to comment.