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

Commit

Permalink
root/super circuit multiple chunk mock test
Browse files Browse the repository at this point in the history
  • Loading branch information
hero78119 committed Feb 29, 2024
1 parent 1ca62a0 commit 1008eb3
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 81 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/main-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,16 @@ jobs:
sudo chmod +x /usr/bin/solc
- name: Update ERC20 git submodule
run: git submodule update --init --recursive --checkout integration-tests/contracts/vendor/openzeppelin-contracts
- name: Run root test
uses: actions-rs/cargo@v1
with:
command: test
args: --package zkevm-circuits --lib -- root_circuit::test::test_root_circuit_multiple_chunk --exact --ignored
- name: Run heavy tests # heavy tests are run serially to avoid OOM
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --release --all --all-features --exclude integration-tests --exclude circuit-benchmarks serial_ -- --ignored --test-threads 1

build:
needs: [skip_check]
if: |
Expand Down
11 changes: 2 additions & 9 deletions bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl FeatureConfig {
const RW_BUFFER_SIZE: usize = 30;

/// Circuit Setup Parameters
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FixedCParams {
///
pub total_chunks: usize,
Expand Down Expand Up @@ -557,13 +557,9 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
self.chunk_ctx.end_copy_index = next_copy_index;
self.cur_chunk_mut().ctx = self.chunk_ctx.clone();
if to_next {
// here use `-1` to include previous set
// add `-1` to include previous set and deal with transaction cross-chunk case
self.chunk_ctx
.bump(self.block_ctx.rwc.0, next_tx_index - 1, next_copy_index);
// println!("bump last_call {:?}", last_call);
if last_call.is_none() {
panic!("??")
}
self.cur_chunk_mut().prev_last_call = last_call;
}
}
Expand All @@ -577,12 +573,10 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
..ExecStep::default()
};
self.gen_chunk_associated_steps(&mut begin_chunk, RW::READ, tx);
println!("in set begin chunk {:?}", begin_chunk);
self.chunks[self.chunk_ctx.idx].begin_chunk = Some(begin_chunk);
}

fn set_end_chunk(&mut self, next_step: &ExecStep, tx: Option<&Transaction>) {
println!("before self.block_ctx.rwc.0 {}", self.block_ctx.rwc.0);
// println!("next step {:?}", next_step);
let mut end_chunk = ExecStep {
exec_state: ExecState::EndChunk,
Expand All @@ -594,7 +588,6 @@ impl<'a, C: CircuitsParams> CircuitInputBuilder<C> {
};
self.gen_chunk_associated_steps(&mut end_chunk, RW::WRITE, tx);
self.gen_chunk_padding(&mut end_chunk);
println!("after self.block_ctx.rwc.0 {}", self.block_ctx.rwc.0);
self.chunks[self.chunk_ctx.idx].end_chunk = Some(end_chunk);
}

Expand Down
3 changes: 2 additions & 1 deletion circuit-benchmarks/src/super_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ mod tests {
max_evm_rows: 0,
max_keccak_rows: 0,
};
let (_, circuit, instance, _) =
let (_, mut circuits, mut instances, _) =
SuperCircuit::build(block, circuits_params, Fr::from(0x100)).unwrap();
let (circuit, instance) = (circuits.remove(0), instances.remove(0));
let instance_refs: Vec<&[Fr]> = instance.iter().map(|v| &v[..]).collect();

// Bench setup generation
Expand Down
5 changes: 4 additions & 1 deletion testool/src/statetest/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,13 @@ pub fn run_test(
max_evm_rows: 0,
max_keccak_rows: 0,
};
let (k, circuit, instance, _builder) =
let (k, mut circuits, mut instances, _builder) =
SuperCircuit::<Fr>::build(geth_data, circuits_params, Fr::from(0x100)).unwrap();
builder = _builder;

let circuit = circuits.remove(0);
let instance = instances.remove(0);

let prover = MockProver::run(k, &circuit, instance).unwrap();
prover
.verify()
Expand Down
1 change: 1 addition & 0 deletions zkevm-circuits/src/evm_circuit/execution/end_chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ mod test {
.params({
FixedCParams {
total_chunks,
max_evm_rows: 1 << 12,
max_rws: total_rws / total_chunks,
max_txs: 2,
..Default::default()
Expand Down
77 changes: 47 additions & 30 deletions zkevm-circuits/src/root_circuit/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,70 +20,87 @@ use rand::rngs::OsRng;

#[ignore = "Due to high memory requirement"]
#[test]
fn test_root_circuit() {
let (params, protocol, proof, instance, rwtable_columns) = {
fn test_root_circuit_multiple_chunk() {
let (params, protocol, proofs, instances, rwtable_columns) = {
// Preprocess
const TEST_MOCK_RANDOMNESS: u64 = 0x100;
let circuits_params = FixedCParams {
total_chunks: 1,
total_chunks: 3,
max_txs: 1,
max_withdrawals: 5,
max_calldata: 32,
max_rws: 256,
max_rws: 100,
max_copy_rows: 256,
max_exp_steps: 256,
max_bytecode: 512,
max_evm_rows: 0,
max_evm_rows: 1 << 12,
max_keccak_rows: 0,
};
let (k, circuit, instance, _) =
let (k, circuits, instances, _) =
SuperCircuit::<_>::build(block_1tx(), circuits_params, TEST_MOCK_RANDOMNESS.into())
.unwrap();
assert!(!circuits.is_empty());
assert!(circuits.len() == instances.len());

// get chronological_rwtable and byaddr_rwtable columns index
let mut cs = ConstraintSystem::default();
let config = SuperCircuit::configure_with_params(&mut cs, circuit.params());
let config = SuperCircuit::configure_with_params(&mut cs, circuits[0].params());
let rwtable_columns = config.get_rwtable_columns();

let params = ParamsKZG::<Bn256>::setup(k, OsRng);
let pk = keygen_pk(&params, keygen_vk(&params, &circuit).unwrap(), &circuit).unwrap();
let pk = keygen_pk(
&params,
keygen_vk(&params, &circuits[0]).unwrap(),
&circuits[0],
)
.unwrap();
let protocol = compile(
&params,
pk.get_vk(),
Config::kzg()
.with_num_instance(instance.iter().map(|instance| instance.len()).collect()),
.with_num_instance(instances[0].iter().map(|instance| instance.len()).collect()),
);

// Create proof
let proof = {
let mut transcript = PoseidonTranscript::new(Vec::new());
create_proof::<KZGCommitmentScheme<_>, ProverGWC<_>, _, _, _, _>(
&params,
&pk,
&[circuit],
&[&instance.iter().map(Vec::as_slice).collect_vec()],
OsRng,
&mut transcript,
)
.unwrap();
transcript.finalize()
};

(params, protocol, proof, instance, rwtable_columns)
let proofs: Vec<Vec<u8>> = circuits
.into_iter()
.zip(instances.iter())
.map(|(circuit, instance)| {
// Create proof
let proof = {
let mut transcript = PoseidonTranscript::new(Vec::new());
create_proof::<KZGCommitmentScheme<_>, ProverGWC<_>, _, _, _, _>(
&params,
&pk,
&[circuit],
&[&instance.iter().map(Vec::as_slice).collect_vec()],
OsRng,
&mut transcript,
)
.unwrap();
transcript.finalize()
};
proof
})
.collect();
(params, protocol, proofs, instances, rwtable_columns)
};

let user_challenge = UserChallenge {
column_indexes: rwtable_columns,
num_challenges: 2, // alpha, gamma
};
let snark_witnesses: Vec<_> = proofs
.iter()
.zip(instances.iter())
.map(|(proof, instance)| {
SnarkWitness::new(&protocol, Value::known(instance), Value::known(proof))
})
.collect();

let root_circuit = RootCircuit::<Bn256, Gwc<_>>::new(
&params,
&protocol,
vec![SnarkWitness::new(
&protocol,
Value::known(&instance),
Value::known(&proof),
)],
snark_witnesses,
Some(&user_challenge),
)
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion zkevm-circuits/src/state_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ impl<F: Field> SubCircuit<F> for StateCircuit<F> {
/// Return the minimum number of rows required to prove the block
fn min_num_rows_block(_block: &witness::Block<F>, chunk: &Chunk<F>) -> (usize, usize) {
(
chunk.chrono_rws.0.values().flatten().count() + 1,
chunk.by_address_rws.0.values().flatten().count() + 1,
chunk.fixed_param.max_rws,
)
}
Expand Down
50 changes: 40 additions & 10 deletions zkevm-circuits/src/super_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ use halo2_proofs::{
circuit::{Layouter, SimpleFloorPlanner, Value},
plonk::{Any, Circuit, Column, ConstraintSystem, Error, Expression},
};
use itertools::Itertools;

use std::array;

Expand Down Expand Up @@ -560,8 +561,15 @@ impl<F: Field> SuperCircuit<F> {
geth_data: GethData,
circuits_params: FixedCParams,
mock_randomness: F,
) -> Result<(u32, Self, Vec<Vec<F>>, CircuitInputBuilder<FixedCParams>), bus_mapping::Error>
{
) -> Result<
(
u32,
Vec<Self>,
Vec<Vec<Vec<F>>>,
CircuitInputBuilder<FixedCParams>,
),
bus_mapping::Error,
> {
let block_data =
BlockData::new_from_geth_data_with_params(geth_data.clone(), circuits_params);
let builder = block_data
Expand All @@ -578,21 +586,43 @@ impl<F: Field> SuperCircuit<F> {
///
/// Also, return with it the minimum required SRS degree for the circuit and
/// the Public Inputs needed.
#[allow(clippy::type_complexity)]
pub fn build_from_circuit_input_builder(
builder: &CircuitInputBuilder<FixedCParams>,
mock_randomness: F,
) -> Result<(u32, Self, Vec<Vec<F>>), bus_mapping::Error> {
) -> Result<(u32, Vec<Self>, Vec<Vec<Vec<F>>>), bus_mapping::Error> {
let mut block = block_convert(builder).unwrap();
let chunk = chunk_convert(&block, builder).unwrap().remove(0);
let chunks = chunk_convert(&block, builder).unwrap();
block.randomness = mock_randomness;

let (_, rows_needed) = Self::min_num_rows_block(&block, &chunk);
let k = log2_ceil(Self::unusable_rows() + rows_needed);
let (rows_needed, circuit_instance_pairs): (Vec<usize>, Vec<(_, _)>) = chunks
.iter()
.map(|chunk| {
let (_, rows_needed) = Self::min_num_rows_block(&block, chunk);

let circuit = SuperCircuit::new_from_block(&block, chunk);
let instance = circuit.instance();
(rows_needed, (circuit, instance))
})
.unzip();

// assert all rows needed are equal
rows_needed
.iter()
.tuple_windows()
.for_each(|rows_needed: (&usize, &usize)| {
assert!(
rows_needed.0 == rows_needed.1,
"mismatched super_circuit rows_needed {:?} != {:?}",
rows_needed.0,
rows_needed.1
)
});

let k = log2_ceil(Self::unusable_rows() + rows_needed[0]);
log::debug!("super circuit uses k = {}", k);

let circuit = SuperCircuit::new_from_block(&block, &chunk);

let instance = circuit.instance();
Ok((k, circuit, instance))
let (circuits, instances) = circuit_instance_pairs.into_iter().unzip();
Ok((k, circuits, instances))
}
}
39 changes: 32 additions & 7 deletions zkevm-circuits/src/super_circuit/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,20 @@ fn super_circuit_degree() {
}

fn test_super_circuit(block: GethData, circuits_params: FixedCParams, mock_randomness: Fr) {
let (k, circuit, instance, _) =
let (k, circuits, instances, _) =
SuperCircuit::<Fr>::build(block, circuits_params, mock_randomness).unwrap();
let prover = MockProver::run(k, &circuit, instance).unwrap();
let res = prover.verify();
if let Err(err) = res {
error!("Verification failures: {:#?}", err);
panic!("Failed verification");
}
circuits
.into_iter()
.zip(instances.into_iter())
.enumerate()
.for_each(|(i, (circuit, instance))| {
let prover = MockProver::run(k, &circuit, instance).unwrap();
let res = prover.verify();
if let Err(err) = res {
error!("{}th supercircuit Verification failures: {:#?}", i, err);
panic!("Failed verification");
}
});
}

pub(crate) fn block_1tx() -> GethData {
Expand Down Expand Up @@ -193,6 +199,25 @@ fn serial_test_super_circuit_2tx_2max_tx() {
test_super_circuit(block, circuits_params, Fr::from(TEST_MOCK_RANDOMNESS));
}

#[ignore]
#[test]
fn serial_test_multi_chunk_super_circuit_2tx_2max_tx() {
let block = block_2tx();
let circuits_params = FixedCParams {
total_chunks: 4,
max_txs: 2,
max_withdrawals: 5,
max_calldata: 32,
max_rws: 90,
max_copy_rows: 256,
max_exp_steps: 256,
max_bytecode: 512,
max_evm_rows: 0,
max_keccak_rows: 0,
};
test_super_circuit(block, circuits_params, Fr::from(TEST_MOCK_RANDOMNESS));
}

#[ignore]
#[test]
fn test_rw_table_commitment() {
Expand Down
Loading

0 comments on commit 1008eb3

Please sign in to comment.