Skip to content
This repository was archived by the owner on Jul 5, 2024. It is now read-only.

Commit 1ca62a0

Browse files
committed
add more tests related intermediate chunk and fixed bugs
1 parent 8aaaa0d commit 1ca62a0

File tree

14 files changed

+370
-274
lines changed

14 files changed

+370
-274
lines changed

bus-mapping/src/circuit_input_builder.rs

+80-33
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
357357
// Optain the first op of the next GethExecStep, for fixed case also lookahead
358358
let (mut cib, mut tx, mut tx_ctx) = (self.clone(), tx, tx_ctx);
359359
let mut cib_ref = cib.state_ref(&mut tx, &mut tx_ctx);
360-
let next_ops = if let Some((i, step)) = next_geth_step {
360+
let mut next_ops = if let Some((i, step)) = next_geth_step {
361361
log::trace!("chunk at {}th opcode {:?} ", i, step.op);
362362
gen_associated_ops(&step.op, &mut cib_ref, &geth_trace.struct_logs[i..])?.remove(0)
363363
} else {
@@ -368,10 +368,14 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
368368
let last_copy = self.block.copy_events.len();
369369
// Generate EndChunk and proceed to the next if it's not the last chunk
370370
// Set next step pre-state as end_chunk state
371-
self.set_end_chunk(&next_ops);
371+
self.set_end_chunk(&next_ops, Some(&tx));
372+
373+
// need to update next_ops.rwc to catch block_ctx.rwc in `set_end_chunk`
374+
next_ops.rwc = self.block_ctx.rwc;
375+
372376
// tx.id start from 1, so it's equivalent to `next_tx_index`
373377
self.commit_chunk_ctx(true, tx.id as usize, last_copy, last_call);
374-
self.set_begin_chunk(&next_ops);
378+
self.set_begin_chunk(&next_ops, Some(&tx));
375379

376380
Ok(())
377381
}
@@ -394,13 +398,12 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
394398
let mut tx_ctx = TransactionContext::new(eth_tx, geth_trace, is_last_tx)?;
395399

396400
let res = if !geth_trace.invalid {
397-
let mut last_call = None;
398-
399401
// Generate BeginTx step
400402
let begin_tx_step = gen_associated_steps(
401403
&mut self.state_ref(&mut tx, &mut tx_ctx),
402404
ExecState::BeginTx,
403405
)?;
406+
let mut last_call = Some(tx.calls().get(begin_tx_step.call_index).unwrap().clone());
404407
tx.steps_mut().push(begin_tx_step);
405408

406409
let mut trace = geth_trace.struct_logs.iter().enumerate().peekable();
@@ -416,9 +419,10 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
416419
// Proceed to the next step
417420
let (i, step) = trace.next().expect("Peeked step should exist");
418421
log::trace!(
419-
"handle {}th opcode {:?} rws = {:?}",
422+
"handle {}th opcode {:?} {:?} rws = {:?}",
420423
i,
421424
step.op,
425+
step,
422426
self.chunk_rws()
423427
);
424428
let exec_steps = gen_associated_ops(
@@ -466,9 +470,13 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
466470
Ok(res)
467471
}
468472

469-
// TODO Fix this, for current logic on processing `call` is incorrect
470-
// TODO re-design `gen_chunk_associated_steps` to separate RW
471-
fn gen_chunk_associated_steps(&mut self, step: &mut ExecStep, rw: RW) {
473+
// generate chunk related steps
474+
fn gen_chunk_associated_steps(
475+
&mut self,
476+
step: &mut ExecStep,
477+
rw: RW,
478+
tx: Option<&Transaction>,
479+
) {
472480
let STEP_STATE_LEN = 10;
473481
let mut dummy_tx = Transaction::default();
474482
let mut dummy_tx_ctx = TransactionContext::default();
@@ -483,12 +491,10 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
483491

484492
let tags = {
485493
let state = self.state_ref(&mut dummy_tx, &mut dummy_tx_ctx);
486-
let last_call = state
487-
.block
488-
.txs
489-
.last()
490-
.map(|tx| tx.calls[0].clone())
491-
.unwrap_or_else(Call::default);
494+
let last_call = tx
495+
.map(|tx| tx.calls()[step.call_index].clone())
496+
.or_else(|| state.block.txs.last().map(|tx| tx.calls[0].clone()))
497+
.unwrap();
492498
[
493499
(StepStateField::CodeHash, last_call.code_hash.to_word()),
494500
(StepStateField::CallID, Word::from(last_call.call_id)),
@@ -551,24 +557,44 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
551557
self.chunk_ctx.end_copy_index = next_copy_index;
552558
self.cur_chunk_mut().ctx = self.chunk_ctx.clone();
553559
if to_next {
560+
// here use `-1` to include previous set
554561
self.chunk_ctx
555-
.bump(self.block_ctx.rwc.0, next_tx_index, next_copy_index);
562+
.bump(self.block_ctx.rwc.0, next_tx_index - 1, next_copy_index);
563+
// println!("bump last_call {:?}", last_call);
564+
if last_call.is_none() {
565+
panic!("??")
566+
}
556567
self.cur_chunk_mut().prev_last_call = last_call;
557568
}
558569
}
559570

560-
fn set_begin_chunk(&mut self, first_step: &ExecStep) {
561-
let mut begin_chunk = first_step.clone();
562-
begin_chunk.exec_state = ExecState::BeginChunk;
563-
self.gen_chunk_associated_steps(&mut begin_chunk, RW::READ);
571+
fn set_begin_chunk(&mut self, first_step: &ExecStep, tx: Option<&Transaction>) {
572+
let mut begin_chunk = ExecStep {
573+
exec_state: ExecState::BeginChunk,
574+
rwc: first_step.rwc,
575+
gas_left: first_step.gas_left,
576+
call_index: first_step.call_index,
577+
..ExecStep::default()
578+
};
579+
self.gen_chunk_associated_steps(&mut begin_chunk, RW::READ, tx);
580+
println!("in set begin chunk {:?}", begin_chunk);
564581
self.chunks[self.chunk_ctx.idx].begin_chunk = Some(begin_chunk);
565582
}
566583

567-
fn set_end_chunk(&mut self, next_step: &ExecStep) {
568-
let mut end_chunk = next_step.clone();
569-
end_chunk.exec_state = ExecState::EndChunk;
570-
self.gen_chunk_associated_steps(&mut end_chunk, RW::WRITE);
584+
fn set_end_chunk(&mut self, next_step: &ExecStep, tx: Option<&Transaction>) {
585+
println!("before self.block_ctx.rwc.0 {}", self.block_ctx.rwc.0);
586+
// println!("next step {:?}", next_step);
587+
let mut end_chunk = ExecStep {
588+
exec_state: ExecState::EndChunk,
589+
rwc: next_step.rwc,
590+
rwc_inner_chunk: next_step.rwc_inner_chunk,
591+
gas_left: next_step.gas_left,
592+
call_index: next_step.call_index,
593+
..ExecStep::default()
594+
};
595+
self.gen_chunk_associated_steps(&mut end_chunk, RW::WRITE, tx);
571596
self.gen_chunk_padding(&mut end_chunk);
597+
println!("after self.block_ctx.rwc.0 {}", self.block_ctx.rwc.0);
572598
self.chunks[self.chunk_ctx.idx].end_chunk = Some(end_chunk);
573599
}
574600

@@ -578,8 +604,6 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
578604
let total_rws = end_rwc - 1;
579605
let max_rws = self.cur_chunk().fixed_param.max_rws;
580606

581-
// We need at least 1 extra row at offset 0 for chunk continuous
582-
// FIXME(Cecilia): adding + 1 fail some tests
583607
assert!(
584608
total_rws < max_rws,
585609
"total_rws <= max_rws, total_rws={}, max_rws={}",
@@ -707,17 +731,26 @@ impl CircuitInputBuilder<FixedCParams> {
707731
eth_block: &EthBlock,
708732
geth_traces: &[eth_types::GethExecTrace],
709733
) -> Result<CircuitInputBuilder<FixedCParams>, Error> {
710-
println!("--------------{:?}", self.circuits_params);
711734
// accumulates gas across all txs in the block
712735
let (last_step, last_call) = self.begin_handle_block(eth_block, geth_traces)?;
713-
let last_step = last_step.unwrap_or_default();
736+
// since there is no next step, we cook dummy next step from last step to reuse
737+
// existing field while update its `rwc`.
738+
let mut dummy_next_step = {
739+
let mut dummy_next_step = last_step.unwrap_or_default();
740+
// raise last step rwc to match with next step
741+
(0..dummy_next_step.rw_indices_len()).for_each(|_| {
742+
dummy_next_step.rwc.inc_pre();
743+
dummy_next_step.rwc_inner_chunk.inc_pre();
744+
});
745+
dummy_next_step
746+
};
714747

715748
assert!(self.circuits_params.max_rws().is_some());
716749

717750
let last_copy = self.block.copy_events.len();
718751

719752
// TODO figure out and resolve generic param type and move fixed_param set inside
720-
// commit_chunk_ctx After fixed, then we can set fixed_param on all chunks
753+
// commit_chunk_ctx. After fixed, then we can set fixed_param on all chunks
721754
(0..self.circuits_params.total_chunks()).for_each(|idx| {
722755
self.get_chunk_mut(idx).fixed_param = self.circuits_params;
723756
});
@@ -734,16 +767,29 @@ impl CircuitInputBuilder<FixedCParams> {
734767
last_call.clone(),
735768
);
736769
} else {
737-
// it doent matter what step was put to set_end_chunk/set_begin_chunk on no-used
738-
// chunks before end_block. Just need to make sure it's step lookup is consistency.
739-
self.set_end_chunk(&last_step);
770+
self.set_end_chunk(&dummy_next_step, None);
771+
740772
self.commit_chunk_ctx(
741773
true,
742774
eth_block.transactions.len(),
743775
last_copy,
744776
last_call.clone(),
745777
);
746-
self.set_begin_chunk(&last_step);
778+
// update dummy_next_step rwc to be used for next
779+
dummy_next_step.rwc = self.block_ctx.rwc;
780+
dummy_next_step.rwc_inner_chunk = self.chunk_ctx.rwc;
781+
self.set_begin_chunk(&dummy_next_step, None);
782+
dummy_next_step.rwc = self.block_ctx.rwc;
783+
dummy_next_step.rwc_inner_chunk = self.chunk_ctx.rwc;
784+
// update virtual step: end_block/padding so it can carry state context correctly
785+
// TODO: enhance virtual step updating mechanism by having `running_next_step`
786+
// defined in circuit_input_builder, so we dont need to
787+
self.block.end_block = dummy_next_step.clone();
788+
self.cur_chunk_mut().padding = {
789+
let mut padding = dummy_next_step.clone();
790+
padding.exec_state = ExecState::Padding;
791+
Some(padding)
792+
};
747793
}
748794
Ok::<(), Error>(())
749795
})?;
@@ -773,6 +819,7 @@ impl CircuitInputBuilder<FixedCParams> {
773819
fn set_end_block(&mut self) -> Result<(), Error> {
774820
let mut end_block = self.block.end_block.clone();
775821
end_block.rwc = self.block_ctx.rwc;
822+
end_block.exec_state = ExecState::EndBlock;
776823
end_block.rwc_inner_chunk = self.chunk_ctx.rwc;
777824

778825
let mut dummy_tx = Transaction::default();

integration-tests/src/integration_test_circuits.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ impl<C: SubCircuit<Fr> + Circuit<Fr>> IntegrationTest<C> {
369369
col1.iter().enumerate().zip_eq(col2.iter()).for_each(
370370
|((index, cellv1), cellv2)| {
371371
assert!(
372-
cellv1.eq(&cellv2),
372+
cellv1.eq(cellv2),
373373
"cellv1 {:?} != cellv2 {:?} on index {}",
374374
cellv1,
375375
cellv2,
@@ -407,7 +407,7 @@ impl<C: SubCircuit<Fr> + Circuit<Fr>> IntegrationTest<C> {
407407
col1.iter().enumerate().zip_eq(col2.iter()).for_each(
408408
|((index, cellv1), cellv2)| {
409409
assert!(
410-
cellv1.eq(&cellv2),
410+
cellv1.eq(cellv2),
411411
"cellv1 {:?} != cellv2 {:?} on index {}",
412412
cellv1,
413413
cellv2,

testool/src/statetest/executor.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,9 @@ pub fn run_test(
348348

349349
let block: Block<Fr> =
350350
zkevm_circuits::evm_circuit::witness::block_convert(&builder).unwrap();
351-
let chunk: Chunk<Fr> =
352-
zkevm_circuits::evm_circuit::witness::chunk_convert(&block, &builder)
353-
.unwrap()
354-
.remove(0);
355-
356-
CircuitTestBuilder::<1, 1>::new_from_block(block, chunk)
351+
let chunks: Vec<Chunk<Fr>> =
352+
zkevm_circuits::evm_circuit::witness::chunk_convert(&block, &builder).unwrap();
353+
CircuitTestBuilder::<1, 1>::new_from_block(block, chunks)
357354
.run_with_result()
358355
.map_err(|err| match err {
359356
CircuitTestError::VerificationFailed { reasons, .. } => {

zkevm-circuits/src/evm_circuit.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,9 @@ mod evm_circuit_stats {
638638
TestContext::<0, 0>::new(None, |_| {}, |_, _| {}, |b, _| b).unwrap(),
639639
)
640640
.block_modifier(Box::new(|_block, chunk| {
641-
chunk.fixed_param.max_evm_rows = (1 << 18) - 100
641+
chunk
642+
.iter_mut()
643+
.for_each(|chunk| chunk.fixed_param.max_evm_rows = (1 << 18) - 100);
642644
}))
643645
.run();
644646
}

0 commit comments

Comments
 (0)