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

feat(anvil): Core types migration #6808

Merged
merged 35 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b219141
here we go again
Evalir Jan 15, 2024
f825beb
wip: storage
Evalir Jan 15, 2024
a9f3543
chore: migrate executor, fmt
Evalir Jan 15, 2024
13a5576
wip
Evalir Jan 15, 2024
ced4cdc
chore: roughly only signers left
Evalir Jan 16, 2024
183fded
feat: migrate proof, bar trie stuff
Evalir Jan 16, 2024
44c0c7d
chore: onto tests
Evalir Jan 16, 2024
beaa32f
chore: passing most tests
Evalir Jan 17, 2024
ab04832
chore: fix impersonate
Evalir Jan 17, 2024
8221afe
chore: op tests passing
Evalir Jan 17, 2024
309859e
txenvelope
Evalir Jan 17, 2024
44c3c6f
chore: some fixes, typed data
Evalir Jan 18, 2024
b575796
feat(`anvil`): remove old ethers-dependent anvil core types (#6842)
Evalir Jan 19, 2024
76294bc
Merge branch 'master' into evalir/migrate-base-anvil
Evalir Jan 19, 2024
1c3119a
chore: update alloy, cleanup
Evalir Jan 19, 2024
60b166b
chore: fix tests
Evalir Jan 19, 2024
5253f94
chore: rename to sign
Evalir Jan 19, 2024
18bad4b
chore: fmt
Evalir Jan 19, 2024
ff6c4cd
chore: cleanup
Evalir Jan 19, 2024
a71abeb
docs
Evalir Jan 19, 2024
394d2ce
chore: more cleanup
Evalir Jan 19, 2024
2765391
clippy/fmt
Evalir Jan 19, 2024
2d4a1d2
chore: remove ethers from anvil-core, rm fastrlp
Evalir Jan 19, 2024
96e973e
chore: remove fastrlp from exceptions in deny.toml
Evalir Jan 19, 2024
607e53d
chore: rename and cleanup
Evalir Jan 19, 2024
51a4ada
directly use type to decode
Evalir Jan 19, 2024
b776b58
address review comments
Evalir Jan 22, 2024
e1fc95b
Merge branch 'master' into evalir/migrate-base-anvil
onbjerg Jan 22, 2024
a75cee0
feat: onbjerg nits
Evalir Jan 22, 2024
8d8951c
chore: fix deny check
Evalir Jan 22, 2024
c67f393
Merge branch 'master' into evalir/migrate-base-anvil
Evalir Jan 24, 2024
85db6d4
bump alloy
Evalir Jan 24, 2024
ede4871
chore: add to_ethers ext trait for wallets
Evalir Jan 25, 2024
64b77ad
Merge branch 'master' into evalir/migrate-base-anvil
Evalir Jan 25, 2024
07fb76d
chore: update deps, revert changed typed-data tests, set chain id as …
Evalir Jan 25, 2024
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
Prev Previous commit
Next Next commit
chore: some fixes, typed data
  • Loading branch information
Evalir committed Jan 18, 2024
commit 44c3c6f4898cf8b09026360402470457eaaca2b4
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/anvil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ alloy-network.workspace = true
alloy-rlp.workspace = true
alloy-signer = { workspace = true, features = ["eip712", "mnemonic"] }
alloy-sol-types = { workspace = true, features = ["std"] }
alloy-dyn-abi = { workspace = true, features = ["std", "eip712"] }
alloy-rpc-types.workspace = true
alloy-rpc-trace-types.workspace = true
alloy-providers.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/anvil/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ alloy-rlp.workspace = true
alloy-eips.workspace = true
alloy-network = { workspace = true, features = ["k256"] }
alloy-consensus.workspace = true
alloy-dyn-abi = { workspace = true, features = ["std", "eip712"] }
ethers-core = { workspace = true, features = ["optimism"] }
# theses are not used by anvil-core, but are required by ethers, because pulled in via foundry-common
ethers-contract = { workspace = true, features = ["optimism"] }
Expand Down
7 changes: 3 additions & 4 deletions crates/anvil/core/src/eth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use alloy_rpc_types::{
state::StateOverride,
BlockId, BlockNumberOrTag as BlockNumber, CallRequest, Filter,
};
use ethers_core::types::transaction::eip712::TypedData;

pub mod alloy_block;
pub mod alloy_proof;
Expand Down Expand Up @@ -41,7 +40,7 @@ pub struct Params<T: Default> {
}

/// Represents ethereum JSON-RPC API
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "method", content = "params"))]
pub enum EthRequest {
Expand Down Expand Up @@ -158,7 +157,7 @@ pub enum EthRequest {

/// Signs data via [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md), and includes full support of arrays and recursive data structures.
#[cfg_attr(feature = "serde", serde(rename = "eth_signTypedData_v4"))]
EthSignTypedDataV4(Address, TypedData),
EthSignTypedDataV4(Address, alloy_dyn_abi::TypedData),

#[cfg_attr(feature = "serde", serde(rename = "eth_sendTransaction", with = "sequence"))]
EthSendTransaction(Box<EthTransactionRequest>),
Expand Down Expand Up @@ -736,7 +735,7 @@ pub enum EthPubSub {
}

/// Container type for either a request or a pub sub
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum EthRpcCall {
Expand Down
120 changes: 61 additions & 59 deletions crates/anvil/core/src/eth/transaction/alloy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::eth::{
transaction::optimism::{DepositTransaction, DepositTransactionRequest},
utils::eip_to_revm_access_list,
};
use alloy_consensus::{ReceiptWithBloom, TxEip1559, TxEip2930, TxLegacy, TxEnvelope};
use alloy_consensus::{ReceiptWithBloom, TxEip1559, TxEip2930, TxEnvelope, TxLegacy};
use alloy_network::{Signed, Transaction, TxKind};
use alloy_primitives::{Address, Bloom, Bytes, Log, Signature, TxHash, B256, U256, U64};
use alloy_rlp::{Decodable, Encodable};
Expand Down Expand Up @@ -691,10 +691,10 @@ impl TypedTransaction {
pub fn r#type(&self) -> Option<u8> {
match self {
TypedTransaction::Enveloped(tx) => match tx {
TxEnvelope::Legacy(tx) => None,
TxEnvelope::TaggedLegacy(tx) => Some(0),
TxEnvelope::Eip2930(tx) => Some(1),
TxEnvelope::Eip1559(tx) => Some(2),
TxEnvelope::Legacy(_) => None,
TxEnvelope::TaggedLegacy(_) => Some(0),
TxEnvelope::Eip2930(_) => Some(1),
TxEnvelope::Eip1559(_) => Some(2),
},
TypedTransaction::Deposit(_) => Some(0x7E),
}
Expand All @@ -708,58 +708,56 @@ impl TypedTransaction {
/// Returns a helper type that contains commonly used values as fields
pub fn essentials(&self) -> TransactionEssentials {
match self {
TypedTransaction::Enveloped(tx) => {
match tx {
TxEnvelope::Legacy(t) => TransactionEssentials {
kind: t.tx().to,
input: t.input.clone(),
nonce: U256::from(t.tx().nonce),
gas_limit: U256::from(t.tx().gas_limit),
gas_price: Some(U256::from(t.tx().gas_price)),
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
value: t.value,
chain_id: t.tx().chain_id,
access_list: Default::default(),
},
TxEnvelope::TaggedLegacy(t) => TransactionEssentials {
kind: t.tx().to,
input: t.input.clone(),
nonce: U256::from(t.tx().nonce),
gas_limit: U256::from(t.tx().gas_limit),
gas_price: Some(U256::from(t.tx().gas_price)),
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
value: t.value,
chain_id: t.tx().chain_id,
access_list: Default::default(),
},
TxEnvelope::Eip2930(t) => TransactionEssentials {
kind: t.tx().to,
input: t.input.clone(),
nonce: U256::from(t.tx().nonce),
gas_limit: U256::from(t.tx().gas_limit),
gas_price: Some(U256::from(t.tx().gas_price)),
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
value: t.value,
chain_id: Some(t.chain_id),
access_list: to_alloy_access_list(t.access_list.clone()),
},
TxEnvelope::Eip1559(t) => TransactionEssentials {
kind: t.to,
input: t.input.clone(),
nonce: U256::from(t.nonce),
gas_limit: U256::from(t.gas_limit),
gas_price: None,
max_fee_per_gas: Some(U256::from(t.max_fee_per_gas)),
max_priority_fee_per_gas: Some(U256::from(t.max_priority_fee_per_gas)),
value: t.value,
chain_id: Some(t.chain_id),
access_list: to_alloy_access_list(t.access_list.clone()),
},
}
}
TypedTransaction::Enveloped(tx) => match tx {
TxEnvelope::Legacy(t) => TransactionEssentials {
kind: t.tx().to,
input: t.input.clone(),
nonce: U256::from(t.tx().nonce),
gas_limit: U256::from(t.tx().gas_limit),
gas_price: Some(U256::from(t.tx().gas_price)),
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
value: t.value,
chain_id: t.tx().chain_id,
access_list: Default::default(),
},
TxEnvelope::TaggedLegacy(t) => TransactionEssentials {
kind: t.tx().to,
input: t.input.clone(),
nonce: U256::from(t.tx().nonce),
gas_limit: U256::from(t.tx().gas_limit),
gas_price: Some(U256::from(t.tx().gas_price)),
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
value: t.value,
chain_id: t.tx().chain_id,
access_list: Default::default(),
},
TxEnvelope::Eip2930(t) => TransactionEssentials {
kind: t.tx().to,
input: t.input.clone(),
nonce: U256::from(t.tx().nonce),
gas_limit: U256::from(t.tx().gas_limit),
gas_price: Some(U256::from(t.tx().gas_price)),
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
value: t.value,
chain_id: Some(t.chain_id),
access_list: to_alloy_access_list(t.access_list.clone()),
},
TxEnvelope::Eip1559(t) => TransactionEssentials {
kind: t.to,
input: t.input.clone(),
nonce: U256::from(t.nonce),
gas_limit: U256::from(t.gas_limit),
gas_price: None,
max_fee_per_gas: Some(U256::from(t.max_fee_per_gas)),
max_priority_fee_per_gas: Some(U256::from(t.max_priority_fee_per_gas)),
value: t.value,
chain_id: Some(t.chain_id),
access_list: to_alloy_access_list(t.access_list.clone()),
},
},
TypedTransaction::Deposit(t) => TransactionEssentials {
kind: t.kind,
input: t.input.clone(),
Expand Down Expand Up @@ -1151,7 +1149,9 @@ mod tests {
// random mainnet tx: https://etherscan.io/tx/0x86718885c4b4218c6af87d3d0b0d83e3cc465df2a05c048aa4db9f1a6f9de91f
let bytes = hex::decode("02f872018307910d808507204d2cb1827d0094388c818ca8b9251b393131c08a736a67ccb19297880320d04823e2701c80c001a0cf024f4815304df2867a1a74e9d2707b6abda0337d2d54a4438d453f4160f190a07ac0e6b3bc9395b5b9c8b9e6d77204a236577a5b18467b9175c01de4faa208d9").unwrap();

let Ok(TypedTransaction::Enveloped(TxEnvelope::Eip1559(tx))) = TypedTransaction::decode(&mut &bytes[..]) else {
let Ok(TypedTransaction::Enveloped(TxEnvelope::Eip1559(tx))) =
TypedTransaction::decode(&mut &bytes[..])
else {
panic!("decoding TypedTransaction failed");
};

Expand All @@ -1171,7 +1171,9 @@ mod tests {
fn can_recover_sender_not_normalized() {
let bytes = hex::decode("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap();

let Ok(TypedTransaction::Enveloped(TxEnvelope::Legacy(tx))) = TypedTransaction::decode(&mut &bytes[..]) else {
let Ok(TypedTransaction::Enveloped(TxEnvelope::Legacy(tx))) =
TypedTransaction::decode(&mut &bytes[..])
else {
panic!("decoding TypedTransaction failed");
};

Expand Down
56 changes: 29 additions & 27 deletions crates/anvil/core/src/eth/transaction/alloy_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,35 @@ pub fn to_alloy_transaction_with_hash_and_sender(
blob_versioned_hashes: vec![],
other: Default::default(),
},
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::TaggedLegacy(t)) => AlloyTransaction {
hash,
nonce: U64::from(t.nonce),
block_hash: None,
block_number: None,
transaction_index: None,
from,
to: None,
value: t.value,
gas_price: Some(U128::from(t.gas_price)),
max_fee_per_gas: Some(U128::from(t.gas_price)),
max_priority_fee_per_gas: Some(U128::from(t.gas_price)),
gas: U256::from(t.gas_limit),
input: t.input.clone(),
chain_id: t.chain_id.map(U64::from),
signature: Some(Signature {
r: t.signature().r(),
s: t.signature().s(),
v: U256::from(t.signature().v().y_parity_byte()),
y_parity: None,
}),
access_list: None,
transaction_type: None,
max_fee_per_blob_gas: None,
blob_versioned_hashes: vec![],
other: Default::default(),
},
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::TaggedLegacy(t)) => {
AlloyTransaction {
hash,
nonce: U64::from(t.nonce),
block_hash: None,
block_number: None,
transaction_index: None,
from,
to: None,
value: t.value,
gas_price: Some(U128::from(t.gas_price)),
max_fee_per_gas: Some(U128::from(t.gas_price)),
max_priority_fee_per_gas: Some(U128::from(t.gas_price)),
gas: U256::from(t.gas_limit),
input: t.input.clone(),
chain_id: t.chain_id.map(U64::from),
signature: Some(Signature {
r: t.signature().r(),
s: t.signature().s(),
v: U256::from(t.signature().v().y_parity_byte()),
y_parity: None,
}),
access_list: None,
transaction_type: None,
max_fee_per_blob_gas: None,
blob_versioned_hashes: vec![],
other: Default::default(),
}
}
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::Eip2930(t)) => AlloyTransaction {
hash,
nonce: U64::from(t.nonce),
Expand Down
23 changes: 19 additions & 4 deletions crates/anvil/src/eth/alloy_sign.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::eth::error::BlockchainError;

use alloy_network::{Signed, Transaction};
use alloy_primitives::{Address, Signature, U256};
use alloy_primitives::{Address, Signature, B256, U256};
use alloy_signer::{LocalWallet, Signer as AlloySigner, SignerSync as AlloySignerSync};
use alloy_sol_types::Eip712Domain;
use anvil_core::eth::transaction::{
Expand Down Expand Up @@ -31,6 +31,9 @@ pub trait Signer: Send + Sync {
payload: &Eip712Domain,
) -> Result<Signature, BlockchainError>;

/// Signs the given hash.
async fn sign_hash(&self, address: Address, hash: B256) -> Result<Signature, BlockchainError>;

/// signs a transaction request using the given account in request
fn sign_transaction(
&self,
Expand Down Expand Up @@ -79,6 +82,12 @@ impl Signer for DevSigner {
// Ok(signer.sign_typed_data(payload).await?)
}

async fn sign_hash(&self, address: Address, hash: B256) -> Result<Signature, BlockchainError> {
let signer = self.accounts.get(&address).ok_or(BlockchainError::NoSignerAvailable)?;

Ok(signer.sign_hash(hash).await?)
}

fn sign_transaction(
&self,
request: TypedTransactionRequest,
Expand Down Expand Up @@ -106,15 +115,21 @@ pub fn build_typed_transaction(
let tx = match request {
TypedTransactionRequest::Legacy(tx) => {
let sighash = tx.signature_hash();
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::Legacy(Signed::new_unchecked(tx, signature, sighash)))
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::Legacy(Signed::new_unchecked(
tx, signature, sighash,
)))
}
TypedTransactionRequest::EIP2930(tx) => {
let sighash = tx.signature_hash();
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::Eip2930(Signed::new_unchecked(tx, signature, sighash)))
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::Eip2930(
Signed::new_unchecked(tx, signature, sighash),
))
}
TypedTransactionRequest::EIP1559(tx) => {
let sighash = tx.signature_hash();
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::Eip1559(Signed::new_unchecked(tx, signature, sighash)))
TypedTransaction::Enveloped(alloy_consensus::TxEnvelope::Eip1559(
Signed::new_unchecked(tx, signature, sighash),
))
}
TypedTransactionRequest::Deposit(tx) => {
let DepositTransactionRequest {
Expand Down
21 changes: 13 additions & 8 deletions crates/anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ use crate::{
revm::primitives::Output,
ClientFork, LoggingManager, Miner, MiningMode, StorageInfo,
};
use alloy_consensus::{TxLegacy, TxEnvelope};
use alloy_network::{Signed, TxKind};
use alloy_consensus::TxEnvelope;
use alloy_dyn_abi::TypedData;
use alloy_network::TxKind;
use alloy_primitives::{Address, Bytes, TxHash, B256, B64, U256, U64};
use alloy_rlp::Decodable;
use alloy_rpc_trace_types::{
Expand Down Expand Up @@ -60,7 +61,6 @@ use anvil_core::{
},
};
use anvil_rpc::{error::RpcError, response::ResponseResult};
use ethers::types::transaction::eip712::TypedData;
use foundry_common::{provider::alloy::ProviderBuilder, types::ToEthers};
use foundry_evm::{
backend::DatabaseError,
Expand Down Expand Up @@ -831,12 +831,17 @@ impl EthApi {
/// Signs data via [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md), and includes full support of arrays and recursive data structures.
///
/// Handler for ETH RPC call: `eth_signTypedData_v4`
pub async fn sign_typed_data_v4(&self, _address: Address, _data: &TypedData) -> Result<String> {
pub async fn sign_typed_data_v4(&self, address: Address, data: &TypedData) -> Result<String> {
node_info!("eth_signTypedData_v4");
todo!()
// let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
// let signature = alloy_primitives::hex::encode(signer.sign_typed_data(address,
// data).await?.as_bytes()); Ok(format!("0x{signature}"))
let signer = self.get_signer(address).ok_or(BlockchainError::NoSignerAvailable)?;
let signature = signer
.sign_hash(
address,
data.eip712_signing_hash().map_err(|_| BlockchainError::NoSignerAvailable)?,
)
.await?;
let signature = alloy_primitives::hex::encode(signature.as_bytes());
Ok(format!("0x{signature}"))
}

/// The sign method calculates an Ethereum specific signature
Expand Down
Loading