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: retrace in BuilderClient::gen_inputs #1260

Merged
merged 9 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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"]
Loading