Skip to content

Commit

Permalink
ccc performance optimization (privacy-scaling-explorations#970)
Browse files Browse the repository at this point in the history
* construct Address direct

* aggressive inline hotspot

* cache key

* don't sort for from_rws_with_mock_state_roots

* mark possible optimization

* wrap error string with arc

* Revert "wrap error string with arc"

This reverts commit ad05aff.

* exclude original_rws for release build

* [wip] reduce clone in ccc path (privacy-scaling-explorations#973)

* estimate_circuit_capacity take BlockTrace ownership

* Convert ExecutionResult with explicit clone

* add block_trace_to_witness_block

* construct from ref

* sync default mod

* fix order

* clippy

* assertion

* dirty fix

* extract common

* clippy && fmt

* fix clippy

* async drop (privacy-scaling-explorations#981)

* skip small drop

* add comments

* fix typo

---------

Co-authored-by: Zhang Zhuo <[email protected]>
  • Loading branch information
lightsing and lispc authored Oct 9, 2023
1 parent 54cae8c commit 43817d3
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 265 deletions.
24 changes: 17 additions & 7 deletions bus-mapping/src/circuit_input_builder/l2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ fn dump_code_db(cdb: &CodeDB) {
}

impl CircuitInputBuilder {
fn apply_l2_trace(&mut self, block_trace: &BlockTrace, is_last: bool) -> Result<(), Error> {
fn apply_l2_trace(&mut self, block_trace: BlockTrace, is_last: bool) -> Result<(), Error> {
log::trace!(
"apply_l2_trace start, block num {:?}, is_last {is_last}",
block_trace.header.number
Expand All @@ -214,12 +214,12 @@ impl CircuitInputBuilder {
dump_code_db(&self.code_db);
}

let eth_block = EthBlock::from(&block_trace);
let geth_trace: Vec<eth_types::GethExecTrace> = block_trace
.execution_results
.iter()
.into_iter()
.map(From::from)
.collect();
let eth_block: EthBlock = block_trace.clone().into();
assert_eq!(
self.block.chain_id, block_trace.chain_id,
"unexpected chain id in new block_trace"
Expand All @@ -241,6 +241,16 @@ impl CircuitInputBuilder {
// note the actions when `handle_rwc_reversion` argument (the 4th one)
// is true is executing outside this closure
self.handle_block_inner(&eth_block, &geth_trace, false, is_last)?;
// TODO: remove this when GethExecStep don't contains heap data
// send to another thread to drop the heap data
// here we use a magic number from benchmark to decide whether to
// spawn-drop or not
if !geth_trace.is_empty() && geth_trace[0].struct_logs.len() > 2000 {
std::thread::spawn(move || {
std::mem::drop(eth_block);
std::mem::drop(geth_trace);
});
}
log::debug!("apply_l2_trace done for block {:?}", block_num);
//self.sdb.list_accounts();
Ok(())
Expand Down Expand Up @@ -286,7 +296,7 @@ impl CircuitInputBuilder {
/// Create a new CircuitInputBuilder from the given `l2_trace` and `circuits_params`
pub fn new_from_l2_trace(
circuits_params: CircuitsParams,
l2_trace: &BlockTrace,
l2_trace: BlockTrace,
more: bool,
light_mode: bool,
) -> Result<Self, Error> {
Expand Down Expand Up @@ -346,7 +356,7 @@ impl CircuitInputBuilder {

let mut code_db = CodeDB::new();
code_db.insert(Vec::new());
update_codedb(&mut code_db, &sdb, l2_trace)?;
update_codedb(&mut code_db, &sdb, &l2_trace)?;

let mut builder_block = circuit_input_builder::Block::from_headers(&[], circuits_params);
builder_block.chain_id = chain_id;
Expand All @@ -365,7 +375,7 @@ impl CircuitInputBuilder {
}

/// ...
pub fn add_more_l2_trace(&mut self, l2_trace: &BlockTrace, more: bool) -> Result<(), Error> {
pub fn add_more_l2_trace(&mut self, l2_trace: BlockTrace, more: bool) -> Result<(), Error> {
// update init state new data from storage
if let Some(mpt_init_state) = &mut self.mpt_init_state {
mpt_init_state.update_from_trace(
Expand Down Expand Up @@ -419,7 +429,7 @@ impl CircuitInputBuilder {
*self.sdb.get_storage_mut(&addr, &key).1 = val;
}

update_codedb(&mut self.code_db, &self.sdb, l2_trace)?;
update_codedb(&mut self.code_db, &self.sdb, &l2_trace)?;

self.apply_l2_trace(l2_trace, !more)?;
Ok(())
Expand Down
46 changes: 29 additions & 17 deletions eth-types/src/l2_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ pub struct BlockTrace {
}

impl From<BlockTrace> for EthBlock {
fn from(mut b: BlockTrace) -> Self {
fn from(b: BlockTrace) -> Self {
let mut txs = Vec::new();
for (idx, tx_data) in b.transactions.iter_mut().enumerate() {
for (idx, tx_data) in b.transactions.iter().enumerate() {
let tx_idx = Some(U64::from(idx));
let tx = tx_data.to_eth_tx(b.header.hash, b.header.number, tx_idx);
txs.push(tx)
Expand All @@ -50,6 +50,22 @@ impl From<BlockTrace> for EthBlock {
}
}

impl From<&BlockTrace> for EthBlock {
fn from(b: &BlockTrace) -> Self {
let mut txs = Vec::new();
for (idx, tx_data) in b.transactions.iter().enumerate() {
let tx_idx = Some(U64::from(idx));
let tx = tx_data.to_eth_tx(b.header.hash, b.header.number, tx_idx);
txs.push(tx)
}
EthBlock {
transactions: txs,
difficulty: 0.into(),
..b.header.clone()
}
}
}

/// l2 tx trace
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct TransactionTrace {
Expand Down Expand Up @@ -183,20 +199,16 @@ pub struct ExecutionResult {
pub exec_steps: Vec<ExecStep>,
}

impl From<&ExecutionResult> for GethExecTrace {
fn from(e: &ExecutionResult) -> Self {
let mut struct_logs = Vec::new();
for exec_step in &e.exec_steps {
let step = exec_step.into();
struct_logs.push(step)
}
impl From<ExecutionResult> for GethExecTrace {
fn from(e: ExecutionResult) -> Self {
let struct_logs = e.exec_steps.into_iter().map(GethExecStep::from).collect();
GethExecTrace {
l1_fee: e.l1_fee.as_u64(),
gas: Gas(e.gas),
failed: e.failed,
return_value: e.return_value.clone(),
return_value: e.return_value,
struct_logs,
account_after: e.account_after.clone(),
account_after: e.account_after,
}
}
}
Expand All @@ -221,11 +233,11 @@ pub struct ExecStep {
pub extra_data: Option<ExtraData>,
}

impl From<&ExecStep> for GethExecStep {
fn from(e: &ExecStep) -> Self {
let stack = e.stack.clone().map_or_else(Stack::new, Stack::from);
let storage = e.storage.clone().map_or_else(Storage::empty, Storage::from);
let memory = e.memory.clone().map_or_else(Memory::default, Memory::from);
impl From<ExecStep> for GethExecStep {
fn from(e: ExecStep) -> Self {
let stack = e.stack.map_or_else(Stack::new, Stack::from);
let storage = e.storage.map_or_else(Storage::empty, Storage::from);
let memory = e.memory.map_or_else(Memory::default, Memory::from);

GethExecStep {
pc: ProgramCounter(e.pc as usize),
Expand All @@ -235,7 +247,7 @@ impl From<&ExecStep> for GethExecStep {
gas_cost: GasCost(e.gas_cost),
refund: Gas(e.refund),
depth: e.depth as u16,
error: e.error.clone(),
error: e.error,
stack,
memory,
storage,
Expand Down
2 changes: 1 addition & 1 deletion external-tracer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub fn trace(config: &TraceConfig) -> Result<Vec<GethExecTrace>, Error> {

Ok(block_trace
.execution_results
.iter()
.into_iter()
.map(From::from)
.collect::<Vec<_>>())
}
3 changes: 2 additions & 1 deletion mock/src/test_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ impl<const NACC: usize, const NTX: usize> TestContext<NACC, NTX> {
#[cfg(feature = "scroll")]
let geth_traces = block_trace
.execution_results
.iter()
.clone()
.into_iter()
.map(From::from)
.collect::<Vec<_>>();

Expand Down
6 changes: 3 additions & 3 deletions prover/src/inner/prover/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr};
use zkevm_circuits::witness::Block;

impl<C: TargetCircuit> Prover<C> {
pub fn mock_prove_target_circuit(block_trace: &BlockTrace) -> anyhow::Result<()> {
Self::mock_prove_target_circuit_batch(&[block_trace.clone()])
pub fn mock_prove_target_circuit(block_trace: BlockTrace) -> anyhow::Result<()> {
Self::mock_prove_target_circuit_batch(vec![block_trace])
}

pub fn mock_prove_target_circuit_batch(block_traces: &[BlockTrace]) -> anyhow::Result<()> {
pub fn mock_prove_target_circuit_batch(block_traces: Vec<BlockTrace>) -> anyhow::Result<()> {
let witness_block = block_traces_to_witness_block(block_traces)?;
Self::mock_prove_witness_block(&witness_block)
}
Expand Down
2 changes: 1 addition & 1 deletion prover/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ pub fn chunk_trace_to_witness_block(mut chunk_trace: Vec<BlockTrace>) -> Result<
// Check if the trace exceeds the circuit capacity.
check_batch_capacity(&mut chunk_trace)?;

block_traces_to_witness_block(&chunk_trace)
block_traces_to_witness_block(chunk_trace)
}

// Return the output dir.
Expand Down
23 changes: 8 additions & 15 deletions prover/src/zkevm/capacity_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,6 @@ pub struct CircuitCapacityChecker {
pub builder_ctx: Option<(CodeDB, StateDB, Option<ZktrieState>)>,
}

// Currently TxTrace is same as BlockTrace, with "transactions" and "executionResults" should be of
// len 1, "storageProofs" should contain "slot touched" during when executing this tx.
pub type TxTrace = BlockTrace;

impl Default for CircuitCapacityChecker {
fn default() -> Self {
Self::new()
Expand Down Expand Up @@ -162,10 +158,8 @@ impl CircuitCapacityChecker {
}
pub fn estimate_circuit_capacity(
&mut self,
txs: &[TxTrace],
trace: BlockTrace,
) -> Result<RowUsage, anyhow::Error> {
log::debug!("estimate_circuit_capacity with txs num {}", txs.len());
assert!(!txs.is_empty());
let (mut estimate_builder, codedb_prev) =
if let Some((code_db, sdb, mpt_state)) = self.builder_ctx.take() {
// here we create a new builder for another (sealed) witness block
Expand All @@ -175,13 +169,13 @@ impl CircuitCapacityChecker {
// changed but we may not update it in light mode)
let mut builder_block =
circuit_input_builder::Block::from_headers(&[], get_super_circuit_params());
builder_block.chain_id = txs[0].chain_id;
builder_block.start_l1_queue_index = txs[0].start_l1_queue_index;
builder_block.chain_id = trace.chain_id;
builder_block.start_l1_queue_index = trace.start_l1_queue_index;
builder_block.prev_state_root = mpt_state
.as_ref()
.map(|state| state.root())
.map(|root| H256(*root))
.unwrap_or(txs[0].header.state_root)
.unwrap_or(trace.header.state_root)
.to_word();
// notice the trace has included all code required for builidng witness block,
// so we do not need to pick them from previous one, but we still keep the
Expand All @@ -196,22 +190,21 @@ impl CircuitCapacityChecker {
} else {
CircuitInputBuilder::new(sdb, CodeDB::new(), &builder_block)
};
builder.add_more_l2_trace(&txs[0], txs.len() > 1)?;
builder.add_more_l2_trace(trace, false)?;
(builder, Some(code_db))
} else {
(
CircuitInputBuilder::new_from_l2_trace(
get_super_circuit_params(),
&txs[0],
txs.len() > 1,
trace,
false,
self.light_mode,
)?,
None,
)
};
let traces = &txs[1..];
let witness_block =
block_traces_to_witness_block_with_updated_state(traces, &mut estimate_builder)?;
block_traces_to_witness_block_with_updated_state(vec![], &mut estimate_builder)?;
let mut rows = calculate_row_usage_of_witness_block(&witness_block)?;

let mut code_db = codedb_prev.unwrap_or_else(CodeDB::new);
Expand Down
24 changes: 16 additions & 8 deletions prover/src/zkevm/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ mod l1_builder;
use l1_builder as builder;
mod super_circuit;
pub use self::builder::{
block_traces_to_witness_block, block_traces_to_witness_block_with_updated_state,
calculate_row_usage_of_trace, calculate_row_usage_of_witness_block, check_batch_capacity,
get_super_circuit_params, validite_block_traces,
block_trace_to_witness_block, block_traces_to_witness_block,
block_traces_to_witness_block_with_updated_state, calculate_row_usage_of_trace,
calculate_row_usage_of_witness_block, check_batch_capacity, get_super_circuit_params,
validite_block_traces,
};
pub use super_circuit::SuperCircuit;

Expand Down Expand Up @@ -52,19 +53,21 @@ pub trait TargetCircuit {
where
Self: Sized,
{
Self::from_block_traces(&[]).unwrap().0
Self::from_block_traces(vec![]).unwrap().0
}

/// Build the inner circuit and the instances from a traces
fn from_block_trace(block_trace: &BlockTrace) -> anyhow::Result<(Self::Inner, Vec<Vec<Fr>>)>
fn from_block_trace(block_trace: BlockTrace) -> anyhow::Result<(Self::Inner, Vec<Vec<Fr>>)>
where
Self: Sized,
{
Self::from_block_traces(std::slice::from_ref(block_trace))
Self::from_block_traces(vec![block_trace])
}

/// Build the inner circuit and the instances from a list of traces
fn from_block_traces(block_traces: &[BlockTrace]) -> anyhow::Result<(Self::Inner, Vec<Vec<Fr>>)>
fn from_block_traces(
block_traces: Vec<BlockTrace>,
) -> anyhow::Result<(Self::Inner, Vec<Vec<Fr>>)>
where
Self: Sized,
{
Expand All @@ -79,7 +82,12 @@ pub trait TargetCircuit {
where
Self: Sized;

fn estimate_rows(block_traces: &[BlockTrace]) -> anyhow::Result<usize> {
fn estimate_block_rows(block_trace: BlockTrace) -> anyhow::Result<usize> {
let witness_block = block_trace_to_witness_block(block_trace)?;
Ok(Self::estimate_rows_from_witness_block(&witness_block))
}

fn estimate_rows(block_traces: Vec<BlockTrace>) -> anyhow::Result<usize> {
let witness_block = block_traces_to_witness_block(block_traces)?;
Ok(Self::estimate_rows_from_witness_block(&witness_block))
}
Expand Down
8 changes: 6 additions & 2 deletions prover/src/zkevm/circuit/l1_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@ pub fn check_batch_capacity(_block_traces: &mut Vec<BlockTrace>) -> Result<()> {
unimplemented!("Must build with feature scroll")
}

pub fn block_traces_to_witness_block(_block_traces: &[BlockTrace]) -> Result<Block<Fr>> {
pub fn block_trace_to_witness_block(_block_traces: BlockTrace) -> Result<Block<Fr>> {
unimplemented!("Must build with feature scroll")
}

pub fn block_traces_to_witness_block(_block_traces: Vec<BlockTrace>) -> Result<Block<Fr>> {
unimplemented!("Must build with feature scroll")
}

pub fn block_traces_to_witness_block_with_updated_state(
_block_traces: &[BlockTrace],
_block_traces: Vec<BlockTrace>,
_builder: &mut CircuitInputBuilder,
_light_mode: bool,
) -> Result<Block<Fr>> {
Expand Down
Loading

0 comments on commit 43817d3

Please sign in to comment.