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: roughly only signers left
  • Loading branch information
Evalir committed Jan 16, 2024
commit ced4cdcd5c20df661834497430349e708875abfa
4 changes: 3 additions & 1 deletion crates/anvil/core/src/eth/transaction/alloy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use alloy_consensus::{ReceiptWithBloom, TxEip1559, TxEip2930, TxLegacy};
use alloy_network::{Signed, Transaction, TxKind};
use alloy_primitives::{Address, Bloom, Bytes, Log, Signature, TxHash, B256, U256};
use alloy_rlp::{Decodable, Encodable};
use alloy_rpc_types::{request::TransactionRequest, AccessList, CallRequest};
use alloy_rpc_types::{
request::TransactionRequest, AccessList, CallRequest, Transaction as AlloyTransaction,
};
use foundry_evm::traces::CallTraceNode;
use revm::{
interpreter::InstructionResult,
Expand Down
125 changes: 125 additions & 0 deletions crates/anvil/core/src/eth/transaction/alloy_compat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use crate::eth::utils::from_eip_to_alloy_access_list;
use alloy_primitives::{Address, B256, U128, U256, U64};
use alloy_rpc_types::{Signature, Transaction as AlloyTransaction};

use super::alloy::{MaybeImpersonatedTransaction, TypedTransaction};

impl From<MaybeImpersonatedTransaction> for AlloyTransaction {
fn from(value: MaybeImpersonatedTransaction) -> Self {
let hash = value.hash();
let sender = value.recover().unwrap_or_default();
to_alloy_transaction_with_hash_and_sender(value.transaction, hash, sender)
}
}

pub fn to_alloy_transaction_with_hash_and_sender(
transaction: TypedTransaction,
hash: B256,
from: Address,
) -> AlloyTransaction {
match transaction {
TypedTransaction::Legacy(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::EIP2930(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: Some(U64::from(t.chain_id)),
signature: Some(Signature {
r: t.signature().r(),
s: t.signature().s(),
v: U256::from(t.signature().v().y_parity_byte()),
y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())),
}),
access_list: Some(from_eip_to_alloy_access_list(t.access_list.clone()).0),
transaction_type: Some(U64::from(1)),
max_fee_per_blob_gas: None,
blob_versioned_hashes: vec![],
other: Default::default(),
},
TypedTransaction::EIP1559(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: None,
max_fee_per_gas: Some(U128::from(t.max_fee_per_gas)),
max_priority_fee_per_gas: Some(U128::from(t.max_priority_fee_per_gas)),
gas: U256::from(t.gas_limit),
input: t.input.clone(),
chain_id: Some(U64::from(t.chain_id)),
signature: Some(Signature {
r: t.signature().r(),
s: t.signature().s(),
v: U256::from(t.signature().v().y_parity_byte()),
y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())),
}),
access_list: Some(from_eip_to_alloy_access_list(t.access_list.clone()).0),
transaction_type: Some(U64::from(2)),
max_fee_per_blob_gas: None,
blob_versioned_hashes: vec![],
other: Default::default(),
},
TypedTransaction::Deposit(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: None,
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
gas: U256::from(t.gas_limit),
input: t.input.clone().0.into(),
chain_id: t.chain_id().map(U64::from),
signature: None,
access_list: None,
transaction_type: None,
max_fee_per_blob_gas: None,
blob_versioned_hashes: vec![],
other: Default::default(),
},
}
}
1 change: 1 addition & 0 deletions crates/anvil/core/src/eth/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use revm::{
use std::ops::Deref;

pub mod alloy;
pub mod alloy_compat;
/// compatibility with `ethers-rs` types
mod ethers_compat;
pub mod optimism;
Expand Down
18 changes: 16 additions & 2 deletions crates/anvil/core/src/eth/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use alloy_eips::eip2930::AccessListItem as AlloyEipAccessListItem;
use alloy_eips::eip2930::{
AccessList as AlloyEipAccessList, AccessListItem as AlloyEipAccessListItem,
};
use alloy_primitives::{Address, U256};
use alloy_rpc_types::AccessListItem as AlloyAccessListItem;
use alloy_rpc_types::{AccessList as AlloyAccessList, AccessListItem as AlloyAccessListItem};
use ethers_core::{
types::transaction::eip2930::AccessListItem,
utils::{
Expand Down Expand Up @@ -35,6 +37,18 @@ pub fn alloy_to_revm_access_list(list: Vec<AlloyAccessListItem>) -> Vec<(Address
.collect()
}

pub fn from_eip_to_alloy_access_list(list: AlloyEipAccessList) -> AlloyAccessList {
AlloyAccessList(
list.0
.into_iter()
.map(|item| AlloyAccessListItem {
address: item.address,
storage_keys: item.storage_keys.into_iter().map(|k| k.into()).collect(),
})
.collect(),
)
}

/// Translates a vec of [AlloyEipAccessListItem] to a revm style Access List.
pub fn eip_to_revm_access_list(list: Vec<AlloyEipAccessListItem>) -> Vec<(Address, Vec<U256>)> {
list.into_iter()
Expand Down
107 changes: 55 additions & 52 deletions crates/anvil/src/eth/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ use alloy_rpc_types::{
use alloy_transport::TransportErrorKind;
use anvil_core::{
eth::{
block::BlockInfo,
alloy_block::BlockInfo,
transaction::{
alloy::{PendingTransaction, TypedTransaction as AlloyTypedTransaction},
alloy::{
PendingTransaction, TypedTransaction as AlloyTypedTransaction,
TypedTransactionRequest as AlloyTypedTransactionRequest,
},
call_to_internal_tx_request, to_alloy_proof, to_ethers_signature,
EthTransactionRequest, LegacyTransaction, TransactionKind, TypedTransaction,
TypedTransactionRequest,
EthTransactionRequest, TransactionKind, TypedTransaction, TypedTransactionRequest,
},
EthRequest,
},
Expand All @@ -61,7 +63,7 @@ use anvil_core::{
},
};
use anvil_rpc::{error::RpcError, response::ResponseResult};
use ethers::{types::transaction::eip712::TypedData, utils::rlp};
use ethers::types::transaction::eip712::TypedData;
use foundry_common::{
provider::alloy::ProviderBuilder,
types::{ToAlloy, ToEthers},
Expand Down Expand Up @@ -901,39 +903,39 @@ impl EthApi {
.map(|a| a.to_ethers())
})?
.to_alloy();

let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
let request = self.build_typed_tx_request(request, nonce)?;
// if the sender is currently impersonated we need to "bypass" signing
let pending_transaction = if self.is_impersonated(from) {
let bypass_signature = self.backend.cheats().bypass_signature();
let transaction =
sign::build_typed_transaction(request, to_ethers_signature(bypass_signature))?;
self.ensure_typed_transaction_supported(&transaction)?;
trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
PendingTransaction::with_impersonated(transaction, from)
} else {
let transaction = self.sign_request(&from, request)?;
self.ensure_typed_transaction_supported(&transaction)?;
PendingTransaction::new(transaction)?
};

// pre-validate
self.backend.validate_pool_transaction(&pending_transaction).await?;

let requires = required_marker(nonce, on_chain_nonce, from);
let provides = vec![to_marker(nonce.to::<u64>(), from)];
debug_assert!(requires != provides);

self.add_pending_transaction(pending_transaction, requires, provides)
todo!();
// let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
// let request = self.build_typed_tx_request(request, nonce)?;
// // if the sender is currently impersonated we need to "bypass" signing
// let pending_transaction = if self.is_impersonated(from) {
// let bypass_signature = self.backend.cheats().bypass_signature();
// let transaction =
// sign::build_typed_transaction(request, to_ethers_signature(bypass_signature))?;
// self.ensure_typed_transaction_supported(&transaction)?;
// trace!(target : "node", ?from, "eth_sendTransaction: impersonating");
// PendingTransaction::with_impersonated(transaction, from)
// } else {
// let transaction = self.sign_request(&from, request)?;
// self.ensure_typed_transaction_supported(&transaction)?;
// PendingTransaction::new(transaction)?
// };

// // pre-validate
// self.backend.validate_pool_transaction(&pending_transaction).await?;

// let requires = required_marker(nonce, on_chain_nonce, from);
// let provides = vec![to_marker(nonce.to::<u64>(), from)];
// debug_assert!(requires != provides);

// self.add_pending_transaction(pending_transaction, requires, provides)
}

/// Sends signed transaction, returning its hash.
///
/// Handler for ETH RPC call: `eth_sendRawTransaction`
pub async fn send_raw_transaction(&self, tx: Bytes) -> Result<TxHash> {
node_info!("eth_sendRawTransaction");
let data = tx.as_ref();
let mut data = tx.as_ref();
if data.is_empty() {
return Err(BlockchainError::EmptyRawTransactionData);
}
Expand Down Expand Up @@ -1115,7 +1117,7 @@ impl EthApi {
let mut tx = self.pool.get_transaction(hash).map(|pending| {
let from = *pending.sender();
let mut tx = transaction_build(
Some(pending.hash()),
Some(*pending.hash()),
pending.transaction,
None,
None,
Expand Down Expand Up @@ -1996,29 +1998,30 @@ impl EthApi {
request: EthTransactionRequest,
) -> Result<TxHash> {
node_info!("eth_sendUnsignedTransaction");
Err(BlockchainError::RpcUnimplemented)
// either use the impersonated account of the request's `from` field
let from = request.from.ok_or(BlockchainError::NoSignerAvailable)?.to_alloy();
// let from = request.from.ok_or(BlockchainError::NoSignerAvailable)?.to_alloy();

let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;
// let (nonce, on_chain_nonce) = self.request_nonce(&request, from).await?;

let request = self.build_typed_tx_request(request, nonce)?;
// let request = self.build_typed_tx_request(request, nonce)?;

let bypass_signature = self.backend.cheats().bypass_signature();
let transaction =
sign::build_typed_transaction(request, to_ethers_signature(bypass_signature))?;
// let bypass_signature = self.backend.cheats().bypass_signature();
// let transaction =
// sign::build_typed_transaction(request, to_ethers_signature(bypass_signature))?;

self.ensure_typed_transaction_supported(&transaction)?;
// self.ensure_typed_transaction_supported(&transaction)?;

let pending_transaction =
PendingTransaction::with_impersonated(transaction, from.to_ethers());
// let pending_transaction =
// PendingTransaction::with_impersonated(transaction, from);

// pre-validate
self.backend.validate_pool_transaction(&pending_transaction).await?;
// // pre-validate
Evalir marked this conversation as resolved.
Show resolved Hide resolved
// self.backend.validate_pool_transaction(&pending_transaction).await?;

let requires = required_marker(nonce, on_chain_nonce, from);
let provides = vec![to_marker(nonce.to::<u64>(), from)];
// let requires = required_marker(nonce, on_chain_nonce, from);
// let provides = vec![to_marker(nonce.to::<u64>(), from)];

self.add_pending_transaction(pending_transaction, requires, provides)
// self.add_pending_transaction(pending_transaction, requires, provides)
}

/// Returns the number of transactions currently pending for inclusion in the next block(s), as
Expand Down Expand Up @@ -2057,12 +2060,12 @@ impl EthApi {
// not in sequence. The transaction nonce is an incrementing number for each transaction
// with the same From address.
for pending in self.pool.ready_transactions() {
let entry = inspect.pending.entry(pending.pending_transaction.sender()).or_default();
let entry = inspect.pending.entry(*pending.pending_transaction.sender()).or_default();
let key = pending.pending_transaction.nonce().to_string();
entry.insert(key, convert(pending));
}
for queued in self.pool.pending_transactions() {
let entry = inspect.pending.entry(queued.pending_transaction.sender()).or_default();
let entry = inspect.pending.entry(*queued.pending_transaction.sender()).or_default();
let key = queued.pending_transaction.nonce().to_string();
entry.insert(key, convert(queued));
}
Expand Down Expand Up @@ -2095,12 +2098,12 @@ impl EthApi {
}

for pending in self.pool.ready_transactions() {
let entry = content.pending.entry(pending.pending_transaction.sender()).or_default();
let entry = content.pending.entry(*pending.pending_transaction.sender()).or_default();
let key = pending.pending_transaction.nonce().to_string();
entry.insert(key, convert(pending));
}
for queued in self.pool.pending_transactions() {
let entry = content.pending.entry(queued.pending_transaction.sender()).or_default();
let entry = content.pending.entry(*queued.pending_transaction.sender()).or_default();
let key = queued.pending_transaction.nonce().to_string();
entry.insert(key, convert(queued));
}
Expand Down Expand Up @@ -2389,7 +2392,7 @@ impl EthApi {
}

/// Returns the priority of the transaction based on the current `TransactionOrder`
fn transaction_priority(&self, tx: &TypedTransaction) -> TransactionPriority {
fn transaction_priority(&self, tx: &AlloyTypedTransaction) -> TransactionPriority {
self.transaction_order.read().priority(tx)
}

Expand Down Expand Up @@ -2470,7 +2473,7 @@ impl EthApi {
let tx = block.transactions.get(info.transaction_index as usize)?.clone();

let tx = transaction_build(
Some(info.transaction_hash.to_alloy()),
Some(info.transaction_hash),
tx,
Some(&block),
Some(info),
Expand Down
Loading
Loading