Skip to content

Commit

Permalink
feat: retrace in BuilderClient::gen_inputs (#1260)
Browse files Browse the repository at this point in the history
* retrace in BuilderClient::gen_inputs

* keep old

* retrace tx

* add gate to rpc-legacy-tracer

* fix typo

* refactor

* default retrace
  • Loading branch information
lightsing authored May 14, 2024
1 parent 85c773e commit 844ea50
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 37 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions bus-mapping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license.workspace = true

[dependencies]
eth-types = { path = "../eth-types" }
external-tracer = { path="../external-tracer" }
gadgets = { path = "../gadgets" }
mpt-zktrie = {path = "../zktrie"}
mock = { path = "../mock", optional = true }
Expand Down Expand Up @@ -53,3 +54,4 @@ rpc-legacy-tracer = []
# For the trace obtained from erigon node, refund field is missed
# and must be rebuild
fix-refund = ["rpc-legacy-tracer"]
retrace-tx = []
190 changes: 154 additions & 36 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ pub use execution::{
};
use hex::decode_to_slice;

use eth_types::{sign_types::get_dummy_tx, utils::hash_code_keccak};
use eth_types::{
geth_types::{Account, BlockConstants},
sign_types::get_dummy_tx,
utils::hash_code_keccak,
};
use ethers_core::utils::keccak256;
use external_tracer::TraceConfig;
pub use input_state_ref::CircuitInputStateRef;
use itertools::Itertools;
use log::warn;
Expand Down Expand Up @@ -1318,30 +1323,38 @@ impl<P: JsonRpcClient> BuilderClient<P> {
> {
let (mut eth_block, mut geth_traces, history_hashes, prev_state_root) =
self.get_block(block_num).await?;
//let access_set = Self::get_state_accesses(&eth_block, &geth_traces)?;
let (proofs, codes) = self.get_pre_state(geth_traces.iter())?;
let proofs = self.complete_prestate(&eth_block, proofs).await?;
let (state_db, code_db) = Self::build_state_code_db(proofs, codes);
if eth_block.transactions.len() > self.circuits_params.max_txs {
log::error!(
"max_txs too small: {} < {} for block {}",
self.circuits_params.max_txs,
eth_block.transactions.len(),
eth_block.number.unwrap_or_default()
);
eth_block
.transactions
.truncate(self.circuits_params.max_txs);
geth_traces.truncate(self.circuits_params.max_txs);
}
let builder = self.gen_inputs_from_state(
state_db,
code_db,
&eth_block,
&geth_traces,
history_hashes,
prev_state_root,
)?;

let builder = if cfg!(feature = "retrace-tx") {
let trace_config = self
.get_trace_config(&eth_block, geth_traces.iter(), false)
.await?;

self.trace_to_builder(&eth_block, &trace_config)?
} else {
let (proofs, codes) = self.get_pre_state(geth_traces.iter())?;
let proofs = self.complete_prestate(&eth_block, proofs).await?;
let (state_db, code_db) = Self::build_state_code_db(proofs, codes);
if eth_block.transactions.len() > self.circuits_params.max_txs {
log::error!(
"max_txs too small: {} < {} for block {}",
self.circuits_params.max_txs,
eth_block.transactions.len(),
eth_block.number.unwrap_or_default()
);
eth_block
.transactions
.truncate(self.circuits_params.max_txs);
geth_traces.truncate(self.circuits_params.max_txs);
}
self.gen_inputs_from_state(
state_db,
code_db,
&eth_block,
&geth_traces,
history_hashes,
prev_state_root,
)?
};
Ok((builder, eth_block))
}

Expand Down Expand Up @@ -1378,7 +1391,7 @@ impl<P: JsonRpcClient> BuilderClient<P> {

let mut tx: eth_types::Transaction = self.cli.get_tx_by_hash(tx_hash).await?;
tx.transaction_index = Some(0.into());
let geth_trace = if cfg!(features = "rpc-legacy-tracer") {
let geth_trace = if cfg!(feature = "rpc-legacy-tracer") {
self.cli.trace_tx_by_hash_legacy(tx_hash).await
} else {
self.cli.trace_tx_by_hash(tx_hash).await
Expand All @@ -1390,17 +1403,122 @@ impl<P: JsonRpcClient> BuilderClient<P> {

eth_block.transactions = vec![tx.clone()];

let (proofs, codes) = self.get_pre_state(std::iter::once(&geth_trace))?;
let proofs = self.complete_prestate(&eth_block, proofs).await?;
let (state_db, code_db) = Self::build_state_code_db(proofs, codes);
let builder = self.gen_inputs_from_state(
state_db,
code_db,
&eth_block,
&[geth_trace],
Default::default(),
Default::default(),
let builder = if cfg!(feature = "retrace-tx") {
let trace_config = self
.get_trace_config(&eth_block, iter::once(&geth_trace), true)
.await?;

self.trace_to_builder(&eth_block, &trace_config)?
} else {
let (proofs, codes) = self.get_pre_state(iter::once(&geth_trace))?;
let proofs = self.complete_prestate(&eth_block, proofs).await?;
let (state_db, code_db) = Self::build_state_code_db(proofs, codes);
self.gen_inputs_from_state(
state_db,
code_db,
&eth_block,
&[geth_trace],
Default::default(),
Default::default(),
)?
};

Ok(builder)
}

async fn get_trace_config(
&self,
eth_block: &EthBlock,
geth_traces: impl Iterator<Item = &GethExecTrace>,
complete_prestate: bool,
) -> Result<TraceConfig, Error> {
let (proofs, codes) = self.get_pre_state(geth_traces)?;
let proofs = if complete_prestate {
self.complete_prestate(eth_block, proofs).await?
} else {
proofs
};
Ok(TraceConfig {
chain_id: self.chain_id,
history_hashes: vec![eth_block.parent_hash.to_word()],
block_constants: BlockConstants {
coinbase: eth_block.author.unwrap(),
timestamp: eth_block.timestamp,
number: eth_block.number.unwrap(),
difficulty: eth_block.difficulty,
gas_limit: eth_block.gas_limit,
base_fee: eth_block.base_fee_per_gas.unwrap(),
},
accounts: proofs
.into_iter()
.map(|proof| {
let acc = Account {
address: proof.address,
nonce: proof.nonce,
balance: proof.balance,
code: codes
.get(&proof.address)
.cloned()
.unwrap_or_default()
.into(),
storage: proof
.storage_proof
.into_iter()
.map(|proof| (proof.key, proof.value))
.collect(),
};
(proof.address, acc)
})
.collect(),
transactions: eth_block
.transactions
.iter()
.map(geth_types::Transaction::from)
.collect(),
logger_config: Default::default(),
chain_config: None,
#[cfg(feature = "scroll")]
l1_queue_index: 0,
})
}

#[cfg(feature = "scroll")]
fn trace_to_builder(
&self,
_eth_block: &EthBlock,
trace_config: &TraceConfig,
) -> Result<CircuitInputBuilder, Error> {
let block_trace = external_tracer::l2trace(trace_config)?;
let mut builder = CircuitInputBuilder::new_from_l2_trace(
self.circuits_params,
block_trace,
false,
false,
)?;
builder
.finalize_building()
.expect("could not finalize building block");
Ok(builder)
}

#[cfg(not(feature = "scroll"))]
fn trace_to_builder(
&self,
eth_block: &EthBlock,
trace_config: &TraceConfig,
) -> Result<CircuitInputBuilder, Error> {
let geth_traces = external_tracer::trace(trace_config)?;
let geth_data = geth_types::GethData {
chain_id: trace_config.chain_id,
history_hashes: trace_config.history_hashes.clone(),
geth_traces: geth_traces.clone(),
accounts: trace_config.accounts.values().cloned().collect(),
eth_block: eth_block.clone(),
};
let block_data =
crate::mock::BlockData::new_from_geth_data_with_params(geth_data, self.circuits_params);
let mut builder = block_data.new_circuit_input_builder();
builder.handle_block(eth_block, &geth_traces)?;
Ok(builder)
}
}
4 changes: 3 additions & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ rand_core = "0.6.4"
mock = { path = "../mock" }

[features]
default = ["circuits"]
default = ["circuits", "retrace-tx"]
rpc = []
circuit_input_builder = []
circuits = []
mock_prover = []
scroll= ["bus-mapping/scroll", "eth-types/scroll", "mock/scroll", "zkevm-circuits/scroll"]
fix-refund = ["bus-mapping/fix-refund"]
rpc-legacy-tracer = ["bus-mapping/rpc-legacy-tracer"]
retrace-tx = ["bus-mapping/retrace-tx"]

0 comments on commit 844ea50

Please sign in to comment.