Skip to content

Commit ac00e0b

Browse files
authored
chore(anvil): use Block and Header from Alloy (#12533)
* chore(anvil): replace `PartialHeader` with `Header` from Alloy * chore(anvil): replace `Block` w/ Alloy's `Block`/`BlockBody` structs * fix: `BlockchainStorage` header init
1 parent eb76d29 commit ac00e0b

File tree

8 files changed

+96
-172
lines changed

8 files changed

+96
-172
lines changed

crates/anvil/core/src/eth/block.rs

Lines changed: 23 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
use super::transaction::{TransactionInfo, TypedReceipt};
2-
use alloy_consensus::{EMPTY_OMMER_ROOT_HASH, Header, proofs::calculate_transaction_root};
3-
use alloy_primitives::{Address, B64, B256, Bloom, Bytes, U256};
4-
use alloy_rlp::{RlpDecodable, RlpEncodable};
2+
use alloy_consensus::{
3+
BlockBody, EMPTY_OMMER_ROOT_HASH, Header, proofs::calculate_transaction_root,
4+
};
55

66
// Type alias to optionally support impersonated transactions
77
type Transaction = crate::eth::transaction::MaybeImpersonatedTransaction;
88

9+
/// Type alias for Ethereum Block with Anvil's transaction type
10+
pub type Block = alloy_consensus::Block<Transaction>;
11+
912
/// Container type that gathers all block data
1013
#[derive(Clone, Debug)]
1114
pub struct BlockInfo {
@@ -14,110 +17,28 @@ pub struct BlockInfo {
1417
pub receipts: Vec<TypedReceipt>,
1518
}
1619

17-
/// An Ethereum Block
18-
#[derive(Clone, Debug, PartialEq, Eq, RlpEncodable, RlpDecodable)]
19-
pub struct Block {
20-
pub header: Header,
21-
pub transactions: Vec<Transaction>,
22-
pub ommers: Vec<Header>,
23-
}
24-
25-
impl Block {
26-
/// Creates a new block.
27-
///
28-
/// Note: if the `impersonate-tx` feature is enabled this will also accept
29-
/// `MaybeImpersonatedTransaction`.
30-
pub fn new<T>(partial_header: PartialHeader, transactions: impl IntoIterator<Item = T>) -> Self
31-
where
32-
T: Into<Transaction>,
33-
{
34-
let transactions: Vec<_> = transactions.into_iter().map(Into::into).collect();
35-
let transactions_root = calculate_transaction_root(&transactions);
36-
37-
Self {
38-
header: Header {
39-
parent_hash: partial_header.parent_hash,
40-
beneficiary: partial_header.beneficiary,
41-
ommers_hash: EMPTY_OMMER_ROOT_HASH,
42-
state_root: partial_header.state_root,
43-
transactions_root,
44-
receipts_root: partial_header.receipts_root,
45-
logs_bloom: partial_header.logs_bloom,
46-
difficulty: partial_header.difficulty,
47-
number: partial_header.number,
48-
gas_limit: partial_header.gas_limit,
49-
gas_used: partial_header.gas_used,
50-
timestamp: partial_header.timestamp,
51-
extra_data: partial_header.extra_data,
52-
mix_hash: partial_header.mix_hash,
53-
withdrawals_root: partial_header.withdrawals_root,
54-
blob_gas_used: partial_header.blob_gas_used,
55-
excess_blob_gas: partial_header.excess_blob_gas,
56-
parent_beacon_block_root: partial_header.parent_beacon_block_root,
57-
nonce: partial_header.nonce,
58-
base_fee_per_gas: partial_header.base_fee,
59-
requests_hash: partial_header.requests_hash,
60-
},
61-
transactions,
62-
ommers: vec![],
63-
}
64-
}
65-
}
66-
67-
/// Partial header definition without ommers hash and transactions root
68-
#[derive(Clone, Debug, Default, PartialEq, Eq)]
69-
pub struct PartialHeader {
70-
pub parent_hash: B256,
71-
pub beneficiary: Address,
72-
pub state_root: B256,
73-
pub receipts_root: B256,
74-
pub logs_bloom: Bloom,
75-
pub difficulty: U256,
76-
pub number: u64,
77-
pub gas_limit: u64,
78-
pub gas_used: u64,
79-
pub timestamp: u64,
80-
pub extra_data: Bytes,
81-
pub mix_hash: B256,
82-
pub blob_gas_used: Option<u64>,
83-
pub excess_blob_gas: Option<u64>,
84-
pub parent_beacon_block_root: Option<B256>,
85-
pub nonce: B64,
86-
pub base_fee: Option<u64>,
87-
pub withdrawals_root: Option<B256>,
88-
pub requests_hash: Option<B256>,
89-
}
90-
91-
impl From<Header> for PartialHeader {
92-
fn from(value: Header) -> Self {
93-
Self {
94-
parent_hash: value.parent_hash,
95-
beneficiary: value.beneficiary,
96-
state_root: value.state_root,
97-
receipts_root: value.receipts_root,
98-
logs_bloom: value.logs_bloom,
99-
difficulty: value.difficulty,
100-
number: value.number,
101-
gas_limit: value.gas_limit,
102-
gas_used: value.gas_used,
103-
timestamp: value.timestamp,
104-
extra_data: value.extra_data,
105-
mix_hash: value.mix_hash,
106-
nonce: value.nonce,
107-
base_fee: value.base_fee_per_gas,
108-
blob_gas_used: value.blob_gas_used,
109-
excess_blob_gas: value.excess_blob_gas,
110-
parent_beacon_block_root: value.parent_beacon_block_root,
111-
requests_hash: value.requests_hash,
112-
withdrawals_root: value.withdrawals_root,
113-
}
114-
}
20+
/// Helper function to create a new block with Header and Anvil transactions
21+
///
22+
/// Note: if the `impersonate-tx` feature is enabled this will also accept
23+
/// `MaybeImpersonatedTransaction`.
24+
pub fn create_block<T>(mut header: Header, transactions: impl IntoIterator<Item = T>) -> Block
25+
where
26+
T: Into<Transaction>,
27+
{
28+
let transactions: Vec<_> = transactions.into_iter().map(Into::into).collect();
29+
let transactions_root = calculate_transaction_root(&transactions);
30+
31+
header.transactions_root = transactions_root;
32+
header.ommers_hash = EMPTY_OMMER_ROOT_HASH;
33+
34+
let body = BlockBody { transactions, ommers: Vec::new(), withdrawals: None };
35+
Block::new(header, body)
11536
}
11637

11738
#[cfg(test)]
11839
mod tests {
11940
use alloy_primitives::{
120-
b256,
41+
Address, B64, B256, Bloom, U256, b256,
12142
hex::{self, FromHex},
12243
};
12344
use alloy_rlp::Decodable;

crates/anvil/src/eth/api.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ impl EthApi {
920920
let block_request = self.block_request(Some(block_number.into())).await?;
921921
if let BlockRequest::Pending(txs) = block_request {
922922
let block = self.backend.pending_block(txs).await;
923-
return Ok(Some(U256::from(block.transactions.len())));
923+
return Ok(Some(U256::from(block.block.body.transactions.len())));
924924
}
925925
let block = self.backend.block_by_number(block_number).await?;
926926
let txs = block.map(|b| match b.transactions() {
@@ -1126,7 +1126,7 @@ impl EthApi {
11261126
}
11271127
while let Some(notification) = stream.next().await {
11281128
if let Some(block) = self.backend.get_block_by_hash(notification.hash)
1129-
&& block.transactions.iter().any(|tx| tx.hash() == hash)
1129+
&& block.body.transactions.iter().any(|tx| tx.hash() == hash)
11301130
&& let Some(receipt) = self.backend.transaction_receipt(hash).await?
11311131
{
11321132
return Ok(receipt);
@@ -3299,11 +3299,11 @@ impl EthApi {
32993299

33003300
let mut partial_block = self.backend.convert_block(block.clone());
33013301

3302-
let mut block_transactions = Vec::with_capacity(block.transactions.len());
3302+
let mut block_transactions = Vec::with_capacity(block.body.transactions.len());
33033303
let base_fee = self.backend.base_fee();
33043304

33053305
for info in transactions {
3306-
let tx = block.transactions.get(info.transaction_index as usize)?.clone();
3306+
let tx = block.body.transactions.get(info.transaction_index as usize)?.clone();
33073307

33083308
let tx = transaction_build(
33093309
Some(info.transaction_hash),

crates/anvil/src/eth/backend/db.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66
path::Path,
77
};
88

9-
use alloy_consensus::Header;
9+
use alloy_consensus::{BlockBody, Header};
1010
use alloy_primitives::{Address, B256, Bytes, U256, keccak256, map::HashMap};
1111
use alloy_rpc_types::BlockId;
1212
use anvil_core::eth::{
@@ -584,19 +584,18 @@ impl From<Block> for SerializableBlock {
584584
fn from(block: Block) -> Self {
585585
Self {
586586
header: block.header,
587-
transactions: block.transactions.into_iter().map(Into::into).collect(),
588-
ommers: block.ommers.into_iter().collect(),
587+
transactions: block.body.transactions.into_iter().map(Into::into).collect(),
588+
ommers: block.body.ommers.into_iter().collect(),
589589
}
590590
}
591591
}
592592

593593
impl From<SerializableBlock> for Block {
594594
fn from(block: SerializableBlock) -> Self {
595-
Self {
596-
header: block.header,
597-
transactions: block.transactions.into_iter().map(Into::into).collect(),
598-
ommers: block.ommers.into_iter().collect(),
599-
}
595+
let transactions = block.transactions.into_iter().map(Into::into).collect();
596+
let ommers = block.ommers;
597+
let body = BlockBody { transactions, ommers, withdrawals: None };
598+
Self::new(block.header, body)
600599
}
601600
}
602601

crates/anvil/src/eth/backend/executor.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
mem::inspector::AnvilInspector,
1515
};
1616
use alloy_consensus::{
17-
Receipt, ReceiptWithBloom, constants::EMPTY_WITHDRAWALS, proofs::calculate_receipt_root,
17+
Header, Receipt, ReceiptWithBloom, constants::EMPTY_WITHDRAWALS, proofs::calculate_receipt_root,
1818
};
1919
use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, eip7840::BlobParams};
2020
use alloy_evm::{
@@ -25,7 +25,7 @@ use alloy_evm::{
2525
use alloy_op_evm::OpEvm;
2626
use alloy_primitives::{B256, Bloom, BloomInput, Log};
2727
use anvil_core::eth::{
28-
block::{Block, BlockInfo, PartialHeader},
28+
block::{BlockInfo, create_block},
2929
transaction::{PendingTransaction, TransactionInfo, TypedReceipt, TypedTransaction},
3030
};
3131
use foundry_evm::{
@@ -243,10 +243,12 @@ impl<DB: Db + ?Sized, V: TransactionValidator> TransactionExecutor<'_, DB, V> {
243243

244244
let receipts_root = calculate_receipt_root(&receipts);
245245

246-
let partial_header = PartialHeader {
246+
let header = Header {
247247
parent_hash,
248+
ommers_hash: Default::default(),
248249
beneficiary,
249250
state_root: self.db.maybe_state_root().unwrap_or_default(),
251+
transactions_root: Default::default(), // Will be computed by create_block
250252
receipts_root,
251253
logs_bloom: bloom,
252254
difficulty,
@@ -257,15 +259,15 @@ impl<DB: Db + ?Sized, V: TransactionValidator> TransactionExecutor<'_, DB, V> {
257259
extra_data: Default::default(),
258260
mix_hash: mix_hash.unwrap_or_default(),
259261
nonce: Default::default(),
260-
base_fee,
262+
base_fee_per_gas: base_fee,
261263
parent_beacon_block_root: is_cancun.then_some(Default::default()),
262264
blob_gas_used: cumulative_blob_gas_used,
263265
excess_blob_gas,
264266
withdrawals_root: is_shanghai.then_some(EMPTY_WITHDRAWALS),
265267
requests_hash: is_prague.then_some(EMPTY_REQUESTS_HASH),
266268
};
267269

268-
let block = Block::new(partial_header, transactions);
270+
let block = create_block(header, transactions);
269271
let block = BlockInfo { block, transactions: transaction_infos, receipts };
270272
ExecutedTransactions { block, included, invalid }
271273
}

0 commit comments

Comments
 (0)