Skip to content
This repository was archived by the owner on Apr 18, 2025. It is now read-only.

Commit cefafc9

Browse files
authored
Refactor: BlockTrace struct (#1334)
* done * fix * block env from * refactor trace struct
1 parent b19a2f8 commit cefafc9

File tree

14 files changed

+463
-383
lines changed

14 files changed

+463
-383
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bus-mapping/src/circuit_input_builder/l2.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use crate::{
55
};
66
use eth_types::{
77
self,
8-
l2_types::{BlockTrace, StorageTrace},
8+
l2_types::{trace::collect_codes, BlockTrace, StorageTrace},
99
state_db::{self, CodeDB, StateDB},
10-
Address, EthBlock, ToWord, Word,
10+
Address, EthBlock, ToWord, Word, H256,
1111
};
1212
use ethers_core::types::Bytes;
1313
use mpt_zktrie::state::ZktrieState;
@@ -86,7 +86,7 @@ impl CircuitInputBuilder {
8686

8787
fn collect_storage_proofs(
8888
storage_trace: &StorageTrace,
89-
) -> impl Iterator<Item = (&Address, &Word, impl IntoIterator<Item = &[u8]>)> + Clone {
89+
) -> impl Iterator<Item = (&Address, &H256, impl IntoIterator<Item = &[u8]>)> + Clone {
9090
storage_trace.storage_proofs.iter().flat_map(|(k, kv_map)| {
9191
kv_map
9292
.iter()
@@ -161,12 +161,17 @@ impl CircuitInputBuilder {
161161
&l2_trace.storage_trace,
162162
)) {
163163
let ((addr, key), val) = parsed.map_err(Error::IoError)?;
164+
let key = key.to_word();
164165
*sdb.get_storage_mut(&addr, &key).1 = val.into();
165166
}
166167

167168
let mut code_db = CodeDB::new();
168169
code_db.insert(Vec::new());
169-
code_db.update_codedb(&sdb, &l2_trace)?;
170+
171+
let codes = collect_codes(&l2_trace, Some(&sdb))?;
172+
for (hash, code) in codes {
173+
code_db.insert_with_hash(hash, code);
174+
}
170175

171176
let mut builder_block = circuit_input_builder::Blocks::init(chain_id, circuits_params);
172177
builder_block.prev_state_root = old_root.to_word();
@@ -219,15 +224,16 @@ impl CircuitInputBuilder {
219224

220225
let new_storages = ZktrieState::parse_storage_from_proofs(
221226
Self::collect_storage_proofs(&l2_trace.storage_trace).filter(|(addr, key, _)| {
222-
let (existed, _) = self.sdb.get_committed_storage(addr, key);
227+
let key = key.to_word();
228+
let (existed, _) = self.sdb.get_committed_storage(addr, &key);
223229
!existed
224230
}),
225231
)
226232
.try_fold(
227233
HashMap::new(),
228234
|mut m, parsed| -> Result<HashMap<(Address, Word), Word>, Error> {
229235
let ((addr, key), val) = parsed.map_err(Error::IoError)?;
230-
m.insert((addr, key), val.into());
236+
m.insert((addr, key.to_word()), val.into());
231237
Ok(m)
232238
},
233239
)?;
@@ -236,7 +242,10 @@ impl CircuitInputBuilder {
236242
*self.sdb.get_storage_mut(&addr, &key).1 = val;
237243
}
238244

239-
self.code_db.update_codedb(&self.sdb, &l2_trace)?;
245+
let codes = collect_codes(&l2_trace, Some(&self.sdb))?;
246+
for (hash, code) in codes {
247+
self.code_db.insert_with_hash(hash, code);
248+
}
240249

241250
self.apply_l2_trace(l2_trace)?;
242251
Ok(())

eth-types/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ halo2curves.workspace = true
1212
log.workspace = true
1313
regex.workspace = true
1414
serde.workspace = true
15-
serde_json.workspace = true
15+
serde_json = { workspace = true, features = ["unbounded_depth"] }
16+
serde_stacker.workspace = true
1617
serde_with = "1.12"
1718
uint = "0.9.1"
1819
itertools.workspace = true

eth-types/src/l2_types.rs

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@
33
use crate::{
44
evm_types::{Gas, GasCost, OpcodeId, ProgramCounter},
55
EthBlock, GethCallTrace, GethExecError, GethExecStep, GethExecTrace, GethPrestateTrace, Hash,
6-
ToBigEndian, Transaction, Word, H256,
6+
ToBigEndian, Transaction, H256,
77
};
88
use ethers_core::types::{
99
transaction::eip2930::{AccessList, AccessListItem},
1010
Address, Bytes, U256, U64,
1111
};
12+
use itertools::Itertools;
1213
use serde::{Deserialize, Serialize};
1314
use std::collections::HashMap;
15+
use trace::collect_codes;
16+
17+
/// Trace related helpers
18+
pub mod trace;
1419

1520
#[cfg(feature = "enable-memory")]
1621
use crate::evm_types::Memory;
@@ -19,9 +24,64 @@ use crate::evm_types::Stack;
1924
#[cfg(feature = "enable-storage")]
2025
use crate::evm_types::Storage;
2126

27+
/// l2 block full trace
28+
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
29+
pub struct BlockTraceV2 {
30+
/// chain id
31+
#[serde(rename = "chainID", default)]
32+
pub chain_id: u64,
33+
/// coinbase's status AFTER execution
34+
pub coinbase: AccountProofWrapper,
35+
/// block
36+
pub header: EthBlock,
37+
/// txs
38+
pub transactions: Vec<TransactionTrace>,
39+
/// Accessed bytecodes with hashes
40+
pub codes: Vec<BytecodeTrace>,
41+
/// storage trace BEFORE execution
42+
#[serde(rename = "storageTrace")]
43+
pub storage_trace: StorageTrace,
44+
/// l1 tx queue
45+
#[serde(rename = "startL1QueueIndex", default)]
46+
pub start_l1_queue_index: u64,
47+
}
48+
49+
impl From<BlockTrace> for BlockTraceV2 {
50+
fn from(b: BlockTrace) -> Self {
51+
let codes = collect_codes(&b, None)
52+
.expect("collect codes should not fail")
53+
.into_iter()
54+
.map(|(hash, code)| BytecodeTrace {
55+
hash,
56+
code: code.into(),
57+
})
58+
.collect_vec();
59+
BlockTraceV2 {
60+
codes,
61+
chain_id: b.chain_id,
62+
coinbase: b.coinbase,
63+
header: b.header,
64+
transactions: b.transactions,
65+
storage_trace: b.storage_trace,
66+
start_l1_queue_index: b.start_l1_queue_index,
67+
}
68+
}
69+
}
70+
71+
/// Bytecode
72+
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
73+
pub struct BytecodeTrace {
74+
/// poseidon code hash
75+
pub hash: H256,
76+
/// bytecode
77+
pub code: Bytes,
78+
}
79+
2280
/// l2 block full trace
2381
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
2482
pub struct BlockTrace {
83+
/// Version string
84+
pub version: String,
2585
/// chain id
2686
#[serde(rename = "chainID", default)]
2787
pub chain_id: u64,
@@ -34,6 +94,9 @@ pub struct BlockTrace {
3494
/// execution results
3595
#[serde(rename = "executionResults")]
3696
pub execution_results: Vec<ExecutionResult>,
97+
/// Accessed bytecodes with hashes
98+
#[serde(default)]
99+
pub codes: Vec<BytecodeTrace>,
37100
/// storage trace BEFORE execution
38101
#[serde(rename = "storageTrace")]
39102
pub storage_trace: StorageTrace,
@@ -87,6 +150,30 @@ impl From<&BlockTrace> for EthBlock {
87150
}
88151
}
89152

153+
impl From<&BlockTraceV2> for revm_primitives::BlockEnv {
154+
fn from(block: &BlockTraceV2) -> Self {
155+
revm_primitives::BlockEnv {
156+
number: revm_primitives::U256::from(block.header.number.unwrap().as_u64()),
157+
coinbase: block.coinbase.address.unwrap().0.into(),
158+
timestamp: revm_primitives::U256::from_be_bytes(block.header.timestamp.to_be_bytes()),
159+
gas_limit: revm_primitives::U256::from_be_bytes(block.header.gas_limit.to_be_bytes()),
160+
basefee: revm_primitives::U256::from_be_bytes(
161+
block
162+
.header
163+
.base_fee_per_gas
164+
.unwrap_or_default()
165+
.to_be_bytes(),
166+
),
167+
difficulty: revm_primitives::U256::from_be_bytes(block.header.difficulty.to_be_bytes()),
168+
prevrandao: block
169+
.header
170+
.mix_hash
171+
.map(|h| revm_primitives::B256::from(h.to_fixed_bytes())),
172+
blob_excess_gas_and_price: None,
173+
}
174+
}
175+
}
176+
90177
impl From<&BlockTrace> for revm_primitives::BlockEnv {
91178
fn from(block: &BlockTrace) -> Self {
92179
revm_primitives::BlockEnv {
@@ -247,7 +334,7 @@ impl From<&TransactionTrace> for revm_primitives::TxEnv {
247334
/// account trie proof in storage proof
248335
pub type AccountTrieProofs = HashMap<Address, Vec<Bytes>>;
249336
/// storage trie proof in storage proof
250-
pub type StorageTrieProofs = HashMap<Address, HashMap<Word, Vec<Bytes>>>;
337+
pub type StorageTrieProofs = HashMap<Address, HashMap<H256, Vec<Bytes>>>;
251338

252339
/// storage trace
253340
#[derive(Deserialize, Serialize, Default, Debug, Clone)]
@@ -337,11 +424,11 @@ pub struct ExecStep {
337424
pub depth: isize,
338425
pub error: Option<GethExecError>,
339426
#[cfg(feature = "enable-stack")]
340-
pub stack: Option<Vec<Word>>,
427+
pub stack: Option<Vec<crate::Word>>,
341428
#[cfg(feature = "enable-memory")]
342-
pub memory: Option<Vec<Word>>,
429+
pub memory: Option<Vec<crate::Word>>,
343430
#[cfg(feature = "enable-storage")]
344-
pub storage: Option<HashMap<Word, Word>>,
431+
pub storage: Option<HashMap<crate::Word, crate::Word>>,
345432
#[serde(rename = "extraData")]
346433
pub extra_data: Option<ExtraData>,
347434
}
@@ -402,6 +489,8 @@ pub struct AccountProofWrapper {
402489
pub keccak_code_hash: Option<H256>,
403490
#[serde(rename = "poseidonCodeHash")]
404491
pub poseidon_code_hash: Option<H256>,
492+
#[serde(rename = "codeSize")]
493+
pub code_size: u64,
405494
pub storage: Option<StorageProofWrapper>,
406495
}
407496

@@ -412,3 +501,15 @@ pub struct StorageProofWrapper {
412501
pub key: Option<U256>,
413502
pub value: Option<U256>,
414503
}
504+
505+
#[ignore]
506+
#[test]
507+
fn test_block_trace_convert() {
508+
let trace_v1: BlockTrace =
509+
crate::utils::from_json_file("src/testdata/trace_v1_5224657.json").expect("should load");
510+
let trace_v2: BlockTraceV2 = trace_v1.into();
511+
let mut fd = std::fs::File::create("src/testdata/trace_v2_5224657.json").unwrap();
512+
serde_json::to_writer_pretty(&mut fd, &trace_v2).unwrap();
513+
// then we can use this command to compare the traces:
514+
// vimdiff <(jq -S "del(.executionResults)|del(.txStorageTraces)" src/testdata/trace_v1_5224657.json) <(jq -S . src/testdata/trace_v2_5224657.json)
515+
}

0 commit comments

Comments
 (0)