From 02a2849cd729062df58f0f14d3665f3b333850d0 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Wed, 24 Apr 2024 19:02:09 -0400 Subject: [PATCH 01/31] Implement single-segment aggregations --- Cargo.toml | 6 +- .../src/fixed_recursive_verifier.rs | 176 +++++++++++++++++- evm_arithmetization/src/proof.rs | 53 ++++++ evm_arithmetization/tests/empty_txn_list.rs | 2 + evm_arithmetization/tests/log_opcode.rs | 3 + proof_gen/src/proof_gen.rs | 12 ++ 6 files changed, 244 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0277a2534..1ecfd3f1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,10 +21,10 @@ serde-big-array = "0.5.1" thiserror = "1.0.49" # plonky2-related dependencies -plonky2 = "0.2.2" +plonky2 = { git = "https://github.com/0xPolygonZero/plonky2.git", branch = "zkevm_no_dummy_segment" } plonky2_maybe_rayon = "0.2.0" -plonky2_util = "0.2.0" -starky = "0.4.0" +plonky2_util = { git = "https://github.com/0xPolygonZero/plonky2.git", branch = "zkevm_no_dummy_segment" } +starky = { git = "https://github.com/0xPolygonZero/plonky2.git", branch = "zkevm_no_dummy_segment" } [workspace.package] diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 562d039c9..b7412bf1e 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -187,7 +187,7 @@ where { pub circuit: CircuitData, lhs: AggregationChildTarget, - rhs: AggregationChildTarget, + rhs: AggregationChildWithDummyTarget, public_values: PublicValuesTarget, cyclic_vk: VerifierCircuitTarget, } @@ -220,7 +220,7 @@ where let cyclic_vk = buffer.read_target_verifier_circuit()?; let public_values = PublicValuesTarget::from_buffer(buffer)?; let lhs = AggregationChildTarget::from_buffer(buffer)?; - let rhs = AggregationChildTarget::from_buffer(buffer)?; + let rhs = AggregationChildWithDummyTarget::from_buffer(buffer)?; Ok(Self { circuit, lhs, @@ -272,6 +272,58 @@ impl AggregationChildTarget { } } +#[derive(Eq, PartialEq, Debug)] +struct AggregationChildWithDummyTarget { + is_agg: BoolTarget, + is_dummy: BoolTarget, + agg_proof: ProofWithPublicInputsTarget, + real_proof: ProofWithPublicInputsTarget, + dummy_proof: ProofWithPublicInputsTarget, +} + +impl AggregationChildWithDummyTarget { + fn to_buffer(&self, buffer: &mut Vec) -> IoResult<()> { + buffer.write_target_bool(self.is_agg)?; + buffer.write_target_bool(self.is_dummy)?; + buffer.write_target_proof_with_public_inputs(&self.agg_proof)?; + buffer.write_target_proof_with_public_inputs(&self.real_proof)?; + buffer.write_target_proof_with_public_inputs(&self.dummy_proof)?; + Ok(()) + } + + fn from_buffer(buffer: &mut Buffer) -> IoResult { + let is_agg = buffer.read_target_bool()?; + let is_dummy = buffer.read_target_bool()?; + let agg_proof = buffer.read_target_proof_with_public_inputs()?; + let real_proof = buffer.read_target_proof_with_public_inputs()?; + let dummy_proof = buffer.read_target_proof_with_public_inputs()?; + Ok(Self { + is_agg, + is_dummy, + agg_proof, + real_proof, + dummy_proof, + }) + } + + // `len_mem_cap` is the length of the Merkle + // caps for `MemBefore` and `MemAfter`. + fn public_values>( + &self, + builder: &mut CircuitBuilder, + len_mem_cap: usize, + ) -> PublicValuesTarget { + let agg_pv = + PublicValuesTarget::from_public_inputs(&self.agg_proof.public_inputs, len_mem_cap); + let real_pv = + PublicValuesTarget::from_public_inputs(&self.real_proof.public_inputs, len_mem_cap); + let dummy_pv = + PublicValuesTarget::from_public_inputs(&self.dummy_proof.public_inputs, len_mem_cap); + let segment_pv = PublicValuesTarget::select(builder, self.is_dummy, dummy_pv, real_pv); + PublicValuesTarget::select(builder, self.is_agg, agg_pv, segment_pv) + } +} + /// Data for the transaction aggregation circuit, which is used to compress two /// proofs into one. Each inner proof can be either a segment aggregation proof /// or another transaction aggregation proof. @@ -810,7 +862,7 @@ where let cyclic_vk = builder.add_verifier_data_public_inputs(); let lhs_segment = Self::add_segment_agg_child(&mut builder, root); - let rhs_segment = Self::add_segment_agg_child(&mut builder, root); + let rhs_segment = Self::add_segment_agg_child_with_dummy(&mut builder, root); let lhs_pv = lhs_segment.public_values(&mut builder, cap_before_len); let rhs_pv = rhs_segment.public_values(&mut builder, cap_before_len); @@ -892,9 +944,36 @@ where MemCapTarget::connect( &mut builder, public_values.mem_after.clone(), + rhs_pv.mem_after.clone(), + ); + MemCapTarget::connect(&mut builder, lhs_pv.mem_after, rhs_pv.mem_before.clone()); + + // If the rhs is a dummy, then the lhs must be a segment. + builder.mul_sub( + rhs_segment.is_dummy.target, + lhs_segment.is_agg.target, + rhs_segment.is_dummy.target, + ); + + // If the rhs is a dummy, then its PV after must be equal to its PV before. + TrieRootsTarget::assert_equal_if( + &mut builder, + rhs_segment.is_dummy, + rhs_pv.trie_roots_before, + rhs_pv.trie_roots_after, + ); + RegistersDataTarget::assert_equal_if( + &mut builder, + rhs_segment.is_dummy, + rhs_pv.registers_before, + rhs_pv.registers_after, + ); + MemCapTarget::assert_equal_if( + &mut builder, + rhs_segment.is_dummy, + rhs_pv.mem_before, rhs_pv.mem_after, ); - MemCapTarget::connect(&mut builder, lhs_pv.mem_after, rhs_pv.mem_before); // Pad to match the root circuit's degree. while log2_ceil(builder.num_gates()) < root.circuit.common.degree_bits() { @@ -1193,6 +1272,40 @@ where } } + fn add_segment_agg_child_with_dummy( + builder: &mut CircuitBuilder, + root: &RootCircuitData, + ) -> AggregationChildWithDummyTarget { + let common = &root.circuit.common; + let root_vk = builder.constant_verifier_data(&root.circuit.verifier_only); + let is_agg = builder.add_virtual_bool_target_safe(); + let agg_proof = builder.add_virtual_proof_with_pis(common); + let is_dummy = builder.add_virtual_bool_target_safe(); + let real_proof = builder.add_virtual_proof_with_pis(common); + let (dummy_proof, dummy_vk) = builder + .dummy_proof_and_vk::(common) + .expect("Failed to build dummy proof."); + + let segment_proof = builder.select_proof_with_pis(is_dummy, &dummy_proof, &real_proof); + let segment_vk = builder.select_verifier_data(is_dummy, &dummy_vk, &root_vk); + builder + .conditionally_verify_cyclic_proof::( + is_agg, + &agg_proof, + &segment_proof, + &segment_vk, + common, + ) + .expect("Failed to build cyclic recursion circuit"); + AggregationChildWithDummyTarget { + is_agg, + is_dummy, + agg_proof, + real_proof, + dummy_proof, + } + } + fn add_txn_agg_child( builder: &mut CircuitBuilder, segment_agg: &SegmentAggregationCircuitData, @@ -1603,6 +1716,7 @@ where lhs_public_values: PublicValues, rhs_is_agg: bool, + rhs_is_dummy: bool, rhs_proof: &ProofWithPublicInputs, rhs_public_values: PublicValues, ) -> anyhow::Result<(ProofWithPublicInputs, PublicValues)> { @@ -1616,12 +1730,22 @@ where lhs_proof, ); - Self::set_dummy_if_necessary( + let len_mem_cap = self + .segment_aggregation + .public_values + .mem_before + .mem_cap + .0 + .len(); + + Self::set_dummy_if_necessary_with_dummy( &self.segment_aggregation.rhs, rhs_is_agg, + rhs_is_dummy, &self.segment_aggregation.circuit, &mut agg_inputs, rhs_proof, + len_mem_cap, ); agg_inputs.set_verifier_data_target( @@ -1828,6 +1952,48 @@ where agg_inputs.set_proof_with_pis_target(&agg_child.proof, proof); } + /// TODO: Better comment. This function also takes care of the dummy PIs. + fn set_dummy_if_necessary_with_dummy( + agg_child: &AggregationChildWithDummyTarget, + is_agg: bool, + is_dummy: bool, + circuit: &CircuitData, + agg_inputs: &mut PartialWitness, + proof: &ProofWithPublicInputs, + len_mem_cap: usize, + ) { + agg_inputs.set_bool_target(agg_child.is_agg, is_agg); + agg_inputs.set_bool_target(agg_child.is_dummy, is_dummy); + if is_agg { + agg_inputs.set_proof_with_pis_target(&agg_child.agg_proof, proof); + } else { + Self::set_dummy_proof_with_cyclic_vk_pis( + circuit, + agg_inputs, + &agg_child.agg_proof, + proof, + ); + if is_dummy { + let lhs_pv = PublicValues::from_public_inputs(&proof.public_inputs, len_mem_cap); + let mut dummy_pv = lhs_pv.clone(); + dummy_pv.trie_roots_before = dummy_pv.trie_roots_after.clone(); + dummy_pv.registers_before = dummy_pv.registers_after.clone(); + dummy_pv.mem_before = dummy_pv.mem_after.clone(); + + let dummy_pv_targets = PublicValuesTarget::from_public_inputs( + &agg_child.dummy_proof.public_inputs, + len_mem_cap, + ); + + agg_inputs.set_proof_target(&agg_child.dummy_proof.proof, &proof.proof); + set_public_value_targets(agg_inputs, &dummy_pv_targets, &dummy_pv); + } else { + agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, proof); + } + } + agg_inputs.set_proof_with_pis_target(&agg_child.real_proof, proof); + } + /// Create a final block proof, once all transactions of a given block have /// been combined into a single aggregation proof. /// diff --git a/evm_arithmetization/src/proof.rs b/evm_arithmetization/src/proof.rs index be9a61f86..d707523ee 100644 --- a/evm_arithmetization/src/proof.rs +++ b/evm_arithmetization/src/proof.rs @@ -821,6 +821,24 @@ impl TrieRootsTarget { builder.connect(tr0.receipts_root[i], tr1.receipts_root[i]); } } + + /// If `condition`, asserts that `tr0 == tr1`. + pub(crate) fn assert_equal_if, const D: usize>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + tr0: Self, + tr1: Self, + ) { + for i in 0..8 { + builder.assert_equal_if(condition.target, tr0.state_root[i], tr1.state_root[i]); + builder.assert_equal_if( + condition.target, + tr0.transactions_root[i], + tr1.transactions_root[i], + ); + builder.assert_equal_if(condition.target, tr0.receipts_root[i], tr1.receipts_root[i]); + } + } } /// Circuit version of `BlockMetadata`. @@ -1178,6 +1196,23 @@ impl RegistersDataTarget { builder.connect(rd0.context, rd1.context); builder.connect(rd0.gas_used, rd1.gas_used); } + + /// If `condition`, asserts that `rd0 == rd1`. + pub(crate) fn assert_equal_if, const D: usize>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + rd0: Self, + rd1: Self, + ) { + builder.assert_equal_if(condition.target, rd0.program_counter, rd1.program_counter); + builder.assert_equal_if(condition.target, rd0.is_kernel, rd1.is_kernel); + builder.assert_equal_if(condition.target, rd0.stack_len, rd1.stack_len); + for i in 0..8 { + builder.assert_equal_if(condition.target, rd0.stack_top[i], rd1.stack_top[i]); + } + builder.assert_equal_if(condition.target, rd0.context, rd1.context); + builder.assert_equal_if(condition.target, rd0.gas_used, rd1.gas_used); + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -1245,4 +1280,22 @@ impl MemCapTarget { } } } + + /// If `condition`, asserts that `mc0 == mc1`. + pub(crate) fn assert_equal_if, const D: usize>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + mc0: Self, + mc1: Self, + ) { + for i in 0..mc0.mem_cap.0.len() { + for j in 0..NUM_HASH_OUT_ELTS { + builder.assert_equal_if( + condition.target, + mc0.mem_cap.0[i].elements[j], + mc1.mem_cap.0[i].elements[j], + ); + } + } + } } diff --git a/evm_arithmetization/tests/empty_txn_list.rs b/evm_arithmetization/tests/empty_txn_list.rs index 303183e35..976b45815 100644 --- a/evm_arithmetization/tests/empty_txn_list.rs +++ b/evm_arithmetization/tests/empty_txn_list.rs @@ -192,6 +192,7 @@ fn test_empty_txn_list() -> anyhow::Result<()> { &segment_proofs_data[0].proof_with_pis, segment_proofs_data[0].public_values.clone(), false, + false, &segment_proofs_data[1].proof_with_pis, segment_proofs_data[1].public_values.clone(), )?; @@ -203,6 +204,7 @@ fn test_empty_txn_list() -> anyhow::Result<()> { &segmented_agg_proof, segmented_agg_public_values, false, + false, &segment_proofs_data[2].proof_with_pis, segment_proofs_data[2].public_values.clone(), )?; diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index ce39e5fd4..1c5e29877 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -624,6 +624,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &segment_proofs_data_first[0].proof_with_pis, segment_proofs_data_first[0].public_values.clone(), false, + false, &segment_proofs_data_first[1].proof_with_pis, segment_proofs_data_first[1].public_values.clone(), )?; @@ -635,6 +636,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &segment_proofs_data_second[0].proof_with_pis, segment_proofs_data_second[0].public_values.clone(), false, + false, &segment_proofs_data_second[1].proof_with_pis, segment_proofs_data_second[1].public_values.clone(), )?; @@ -723,6 +725,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &segment_proofs_data[0].proof_with_pis, segment_proofs_data[0].public_values.clone(), false, + false, &segment_proofs_data[1].proof_with_pis, segment_proofs_data[1].public_values.clone(), )?; diff --git a/proof_gen/src/proof_gen.rs b/proof_gen/src/proof_gen.rs index 39075ab02..fb3799ca6 100644 --- a/proof_gen/src/proof_gen.rs +++ b/proof_gen/src/proof_gen.rs @@ -70,11 +70,22 @@ pub fn generate_segment_proof( /// Generates an aggregation proof from two child proofs. /// /// Note that the child proofs may be either transaction or aggregation proofs. +/// +/// If a transaction only contains a single segment, this function must still be +/// called to generate a `GeneratedSegmentAggProof`. In that case, you can set +/// `has_dummy` to `true`, and provide an arbitrary proof for the right child. pub fn generate_segment_agg_proof( p_state: &ProverState, lhs_child: &SegmentAggregatableProof, rhs_child: &SegmentAggregatableProof, + has_dummy: bool, ) -> ProofGenResult { + if has_dummy { + assert!( + !lhs_child.is_agg(), + "Cannot have a dummy segment with an aggregation." + ); + } let (intern, p_vals) = p_state .state .prove_segment_aggregation( @@ -82,6 +93,7 @@ pub fn generate_segment_agg_proof( lhs_child.intern(), lhs_child.public_values(), rhs_child.is_agg(), + has_dummy, rhs_child.intern(), rhs_child.public_values(), ) From 65d87716cd35c226e648ff333b90b9c4073ac845 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Thu, 25 Apr 2024 11:48:33 -0400 Subject: [PATCH 02/31] Change log test --- evm_arithmetization/tests/log_opcode.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 1c5e29877..7fa186d6c 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -473,12 +473,13 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &all_stark, &config, inputs_first, - max_cpu_len_log, + // We want only one segment. + 20, &mut timing, None, )?; - assert_eq!(segment_proofs_data_first.len(), 2); + assert_eq!(segment_proofs_data_first.len(), 1); // The gas used and transaction number are fed to the next transaction, so the // two proofs can be correctly aggregated. @@ -624,9 +625,9 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &segment_proofs_data_first[0].proof_with_pis, segment_proofs_data_first[0].public_values.clone(), false, - false, - &segment_proofs_data_first[1].proof_with_pis, - segment_proofs_data_first[1].public_values.clone(), + true, + &segment_proofs_data_first[0].proof_with_pis, + segment_proofs_data_first[0].public_values.clone(), )?; all_circuits.verify_segment_aggregation(&segment_agg_proof_first)?; From 6141e52dcffcebc9f1f7a962ef080a7a56ebb08e Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Thu, 25 Apr 2024 11:56:58 -0400 Subject: [PATCH 03/31] Don't generate dummy segment data --- evm_arithmetization/src/prover.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 12be79cc9..8cdc71527 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -545,13 +545,13 @@ pub fn generate_all_data_segments( } // We need at least two segments to prove a segment aggregation. - if all_seg_data.len() == 1 { - let dummy_seg = GenerationSegmentData { - registers_before: segment_data.registers_after, - ..segment_data - }; - all_seg_data.push(dummy_seg); - } + // if all_seg_data.len() == 1 { + // let dummy_seg = GenerationSegmentData { + // registers_before: segment_data.registers_after, + // ..segment_data + // }; + // all_seg_data.push(dummy_seg); + // } Ok(all_seg_data) } From b7c0fe05474745c741dde2d8cf4a12d2ad685ac6 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Thu, 25 Apr 2024 17:42:31 -0400 Subject: [PATCH 04/31] Fix dummy proof setting --- .../src/fixed_recursive_verifier.rs | 88 +++++++++++++++---- evm_arithmetization/src/proof.rs | 4 +- 2 files changed, 75 insertions(+), 17 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index b7412bf1e..dbe7c0e25 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -15,7 +15,7 @@ use plonky2::fri::oracle::PolynomialBatch; use plonky2::fri::FriParams; use plonky2::gates::constant::ConstantGate; use plonky2::gates::noop::NoopGate; -use plonky2::hash::hash_types::{MerkleCapTarget, RichField}; +use plonky2::hash::hash_types::{MerkleCapTarget, RichField, NUM_HASH_OUT_ELTS}; use plonky2::iop::challenger::RecursiveChallenger; use plonky2::iop::target::{BoolTarget, Target}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; @@ -1283,7 +1283,7 @@ where let is_dummy = builder.add_virtual_bool_target_safe(); let real_proof = builder.add_virtual_proof_with_pis(common); let (dummy_proof, dummy_vk) = builder - .dummy_proof_and_vk::(common) + .dummy_proof_and_vk_no_generator::(common) .expect("Failed to build dummy proof."); let segment_proof = builder.select_proof_with_pis(is_dummy, &dummy_proof, &real_proof); @@ -1738,13 +1738,15 @@ where .0 .len(); + let real_rhs_proof = if rhs_is_dummy { lhs_proof } else { rhs_proof }; + Self::set_dummy_if_necessary_with_dummy( &self.segment_aggregation.rhs, rhs_is_agg, rhs_is_dummy, &self.segment_aggregation.circuit, &mut agg_inputs, - rhs_proof, + real_rhs_proof, len_mem_cap, ); @@ -1974,19 +1976,75 @@ where proof, ); if is_dummy { - let lhs_pv = PublicValues::from_public_inputs(&proof.public_inputs, len_mem_cap); - let mut dummy_pv = lhs_pv.clone(); - dummy_pv.trie_roots_before = dummy_pv.trie_roots_after.clone(); - dummy_pv.registers_before = dummy_pv.registers_after.clone(); - dummy_pv.mem_before = dummy_pv.mem_after.clone(); - - let dummy_pv_targets = PublicValuesTarget::from_public_inputs( - &agg_child.dummy_proof.public_inputs, - len_mem_cap, + let mut dummy_pis = proof.public_inputs.clone(); + // We must change trie roots before, registers before and memory before. + // Trie roots before := Trie roots after + dummy_pis.copy_within(TrieRootsTarget::SIZE..TrieRootsTarget::SIZE * 2, 0); + // Registers before := Registers after + dummy_pis.copy_within( + TrieRootsTarget::SIZE * 2 + + BlockMetadataTarget::SIZE + + BlockHashesTarget::SIZE + + ExtraBlockDataTarget::SIZE + + RegistersDataTarget::SIZE + ..TrieRootsTarget::SIZE * 2 + + BlockMetadataTarget::SIZE + + BlockHashesTarget::SIZE + + ExtraBlockDataTarget::SIZE + + RegistersDataTarget::SIZE * 2, + TrieRootsTarget::SIZE * 2 + + BlockMetadataTarget::SIZE + + BlockHashesTarget::SIZE + + ExtraBlockDataTarget::SIZE, ); - - agg_inputs.set_proof_target(&agg_child.dummy_proof.proof, &proof.proof); - set_public_value_targets(agg_inputs, &dummy_pv_targets, &dummy_pv); + // Mem before := Mem after + dummy_pis.copy_within( + TrieRootsTarget::SIZE * 2 + + BlockMetadataTarget::SIZE + + BlockHashesTarget::SIZE + + ExtraBlockDataTarget::SIZE + + RegistersDataTarget::SIZE * 2 + + len_mem_cap * NUM_HASH_OUT_ELTS + ..TrieRootsTarget::SIZE * 2 + + BlockMetadataTarget::SIZE + + BlockHashesTarget::SIZE + + ExtraBlockDataTarget::SIZE + + RegistersDataTarget::SIZE * 2 + + 2 * len_mem_cap * NUM_HASH_OUT_ELTS, + TrieRootsTarget::SIZE * 2 + + BlockMetadataTarget::SIZE + + BlockHashesTarget::SIZE + + ExtraBlockDataTarget::SIZE + + RegistersDataTarget::SIZE * 2, + ); + // dummy_pis[0..TrieRootsTarget::SIZE] = + // dummy_pis[TrieRootsTarget::SIZE..TrieRootsTarget::SIZE * 2]; + + // let lhs_pv = PublicValues::from_public_inputs(&proof.public_inputs, + // len_mem_cap); let mut dummy_pv = lhs_pv.clone(); + // dummy_pv.trie_roots_before = dummy_pv.trie_roots_after.clone(); + // dummy_pv.registers_before = dummy_pv.registers_after.clone(); + // dummy_pv.mem_before = dummy_pv.mem_after.clone(); + + // let dummy_pv_targets = PublicValuesTarget::from_public_inputs( + // &agg_child.dummy_proof.public_inputs, + // len_mem_cap, + // ); + + let mut pw = PartialWitness::::new(); + for (i, &pi) in dummy_pis.iter().enumerate() { + pw.set_target(circuit.prover_only.public_inputs[i], pi); + } + let dummy_proof = circuit.prove(pw).expect("Cannot generate dummy proof."); + // let mut dummy_pis = vec![F::ZERO; circuit.common.num_public_inputs]; + + // let mut dummy_proof_with_pis = ProofWithPublicInputs { + // proof: dummy_proof, + // public_inputs: dummy_pis, + // } + agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, &dummy_proof); + // set_public_value_targets(agg_inputs, &dummy_pv_targets, + // &dummy_pv); } else { agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, proof); } diff --git a/evm_arithmetization/src/proof.rs b/evm_arithmetization/src/proof.rs index d707523ee..81b309056 100644 --- a/evm_arithmetization/src/proof.rs +++ b/evm_arithmetization/src/proof.rs @@ -1050,7 +1050,7 @@ pub struct ExtraBlockDataTarget { impl ExtraBlockDataTarget { /// Number of `Target`s required for the extra block data. - const SIZE: usize = 12; + pub const SIZE: usize = 12; /// Extracts the extra block data `Target`s from the public input `Target`s. /// The provided `pis` should start with the extra vblock data. @@ -1138,7 +1138,7 @@ pub struct RegistersDataTarget { impl RegistersDataTarget { /// Number of `Target`s required for the extra block data. - const SIZE: usize = 13; + pub const SIZE: usize = 13; /// Extracts the extra block data `Target`s from the public input `Target`s. /// The provided `pis` should start with the extra vblock data. From 5b22d346d55e25963ff3badbe8aedb555302e077 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Thu, 25 Apr 2024 18:00:59 -0400 Subject: [PATCH 05/31] Make dummy proof out of dummy circuit --- .../src/fixed_recursive_verifier.rs | 3 ++- evm_arithmetization/tests/log_opcode.rs | 26 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index dbe7c0e25..4ea949d18 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -26,7 +26,7 @@ use plonky2::plonk::circuit_data::{ use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; -use plonky2::recursion::dummy_circuit::cyclic_base_proof; +use plonky2::recursion::dummy_circuit::{self, cyclic_base_proof, dummy_circuit}; use plonky2::util::serialization::{ Buffer, GateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, }; @@ -2035,6 +2035,7 @@ where for (i, &pi) in dummy_pis.iter().enumerate() { pw.set_target(circuit.prover_only.public_inputs[i], pi); } + let dummy_circuit = dummy_circuit::(&circuit.common); let dummy_proof = circuit.prove(pw).expect("Cannot generate dummy proof."); // let mut dummy_pis = vec![F::ZERO; circuit.common.num_public_inputs]; diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 7fa186d6c..9bdbd4980 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -469,6 +469,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { let mut timing = TimingTree::new("prove root first", log::Level::Info); let max_cpu_len_log = 15; + println!("Prove first txn segment..."); let segment_proofs_data_first = &all_circuits.prove_all_segments( &all_stark, &config, @@ -481,6 +482,19 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { assert_eq!(segment_proofs_data_first.len(), 1); + println!("Prove first aggreg..."); + let (segment_agg_proof_first, updated_agg_public_values_first) = all_circuits + .prove_segment_aggregation( + false, + &segment_proofs_data_first[0].proof_with_pis, + segment_proofs_data_first[0].public_values.clone(), + false, + true, + &segment_proofs_data_first[0].proof_with_pis, + segment_proofs_data_first[0].public_values.clone(), + )?; + all_circuits.verify_segment_aggregation(&segment_agg_proof_first)?; + // The gas used and transaction number are fed to the next transaction, so the // two proofs can be correctly aggregated. let gas_used_second = segment_proofs_data_first[0] @@ -619,18 +633,6 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { all_circuits.verify_root(proof.clone())?; } - let (segment_agg_proof_first, updated_agg_public_values_first) = all_circuits - .prove_segment_aggregation( - false, - &segment_proofs_data_first[0].proof_with_pis, - segment_proofs_data_first[0].public_values.clone(), - false, - true, - &segment_proofs_data_first[0].proof_with_pis, - segment_proofs_data_first[0].public_values.clone(), - )?; - all_circuits.verify_segment_aggregation(&segment_agg_proof_first)?; - let (segment_agg_proof_second, updated_agg_public_values_second) = all_circuits .prove_segment_aggregation( false, From db9a8f204f20aa5f119ba1da316d5d8d34ab6887 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Fri, 26 Apr 2024 10:43:03 -0400 Subject: [PATCH 06/31] Try to generate dummy proof --- .../src/fixed_recursive_verifier.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 4ea949d18..4b718a46b 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -2031,12 +2031,17 @@ where // len_mem_cap, // ); - let mut pw = PartialWitness::::new(); - for (i, &pi) in dummy_pis.iter().enumerate() { - pw.set_target(circuit.prover_only.public_inputs[i], pi); - } + // let mut pw = PartialWitness::::new(); + // for (i, &pi) in dummy_pis.iter().enumerate() { + // pw.set_target(circuit.prover_only.public_inputs[i], pi); + // } + let dummy_circuit = dummy_circuit::(&circuit.common); - let dummy_proof = circuit.prove(pw).expect("Cannot generate dummy proof."); + println!("Generating dummy proof..."); + let dummy_proof = dummy_proof::(&dummy_circuit, HashMap::new())?; + + //let dummy_proof = circuit.prove(pw).expect("Cannot generate dummy proof."); + // let mut dummy_pis = vec![F::ZERO; circuit.common.num_public_inputs]; // let mut dummy_proof_with_pis = ProofWithPublicInputs { From 26d02b669a9535f8d054c7f3a38cec31e584fd6b Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Fri, 26 Apr 2024 10:46:40 -0400 Subject: [PATCH 07/31] Add import --- evm_arithmetization/src/fixed_recursive_verifier.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 4b718a46b..cf6d83aa4 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -26,7 +26,7 @@ use plonky2::plonk::circuit_data::{ use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; -use plonky2::recursion::dummy_circuit::{self, cyclic_base_proof, dummy_circuit}; +use plonky2::recursion::dummy_circuit::{self, cyclic_base_proof, dummy_circuit, dummy_proof}; use plonky2::util::serialization::{ Buffer, GateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, }; @@ -2038,7 +2038,8 @@ where let dummy_circuit = dummy_circuit::(&circuit.common); println!("Generating dummy proof..."); - let dummy_proof = dummy_proof::(&dummy_circuit, HashMap::new())?; + let dummy_proof = dummy_proof::(&dummy_circuit, HashMap::new()) + .expect("Cannot generate dummy proof."); //let dummy_proof = circuit.prove(pw).expect("Cannot generate dummy proof."); From 187e96eafd8facd019b1b0a3d1bc8c51d0f0eaf0 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Fri, 26 Apr 2024 11:09:21 -0400 Subject: [PATCH 08/31] Add pis to dummy proof --- evm_arithmetization/src/fixed_recursive_verifier.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index cf6d83aa4..326aaf171 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -2017,8 +2017,6 @@ where + ExtraBlockDataTarget::SIZE + RegistersDataTarget::SIZE * 2, ); - // dummy_pis[0..TrieRootsTarget::SIZE] = - // dummy_pis[TrieRootsTarget::SIZE..TrieRootsTarget::SIZE * 2]; // let lhs_pv = PublicValues::from_public_inputs(&proof.public_inputs, // len_mem_cap); let mut dummy_pv = lhs_pv.clone(); @@ -2036,10 +2034,16 @@ where // pw.set_target(circuit.prover_only.public_inputs[i], pi); // } + let mut dummy_pis_map = HashMap::new(); + for (idx, &pi) in dummy_pis.iter().enumerate() { + dummy_pis_map.insert(idx, pi); + } + let dummy_circuit = dummy_circuit::(&circuit.common); println!("Generating dummy proof..."); - let dummy_proof = dummy_proof::(&dummy_circuit, HashMap::new()) + let dummy_proof = dummy_proof::(&dummy_circuit, dummy_pis_map) .expect("Cannot generate dummy proof."); + println!("Dummy proof generated!"); //let dummy_proof = circuit.prove(pw).expect("Cannot generate dummy proof."); From f8806fde710add1cc77ad8079bf6f8ed2a4eb424 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Fri, 26 Apr 2024 11:51:24 -0400 Subject: [PATCH 09/31] Update method name --- evm_arithmetization/src/fixed_recursive_verifier.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 326aaf171..cc32621d4 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -1283,7 +1283,7 @@ where let is_dummy = builder.add_virtual_bool_target_safe(); let real_proof = builder.add_virtual_proof_with_pis(common); let (dummy_proof, dummy_vk) = builder - .dummy_proof_and_vk_no_generator::(common) + .dummy_proof_and_constant_vk_no_generator::(common) .expect("Failed to build dummy proof."); let segment_proof = builder.select_proof_with_pis(is_dummy, &dummy_proof, &real_proof); From 2a2d4a4694fc383ac9d05b0eac2d7c2338ff345d Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Mon, 29 Apr 2024 12:24:32 -0400 Subject: [PATCH 10/31] Fix PV connection --- evm_arithmetization/src/fixed_recursive_verifier.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index cc32621d4..3d0baa15a 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -876,18 +876,13 @@ where ); TrieRootsTarget::connect( &mut builder, - public_values.trie_roots_after, - rhs_pv.trie_roots_after, - ); - TrieRootsTarget::connect( - &mut builder, - public_values.trie_roots_before, + lhs_pv.trie_roots_after, rhs_pv.trie_roots_before, ); TrieRootsTarget::connect( &mut builder, public_values.trie_roots_after, - lhs_pv.trie_roots_after, + rhs_pv.trie_roots_after, ); BlockMetadataTarget::connect( &mut builder, From 4c00a54cc2bff928013eade4e60937c4be265a74 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Mon, 29 Apr 2024 18:03:20 +0100 Subject: [PATCH 11/31] Fix wire set twice --- evm_arithmetization/src/fixed_recursive_verifier.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 3d0baa15a..8e3e59cda 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -877,7 +877,7 @@ where TrieRootsTarget::connect( &mut builder, lhs_pv.trie_roots_after, - rhs_pv.trie_roots_before, + rhs_pv.trie_roots_after, ); TrieRootsTarget::connect( &mut builder, From 28912465e66a5597279c1c07a0ced4787fb33ffd Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Mon, 29 Apr 2024 13:25:28 -0400 Subject: [PATCH 12/31] Update ranges --- evm_arithmetization/tests/empty_txn_list.rs | 14 +++++++------- evm_arithmetization/tests/log_opcode.rs | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/evm_arithmetization/tests/empty_txn_list.rs b/evm_arithmetization/tests/empty_txn_list.rs index 976b45815..fcfa5a3c5 100644 --- a/evm_arithmetization/tests/empty_txn_list.rs +++ b/evm_arithmetization/tests/empty_txn_list.rs @@ -79,14 +79,14 @@ fn test_empty_txn_list() -> anyhow::Result<()> { // Minimal ranges to prove an empty list &[ 16..17, + 8..9, 8..10, - 7..11, - 4..15, - 8..11, - 4..13, - 11..18, - 8..18, - 10..18, + 5..8, + 8..9, + 4..6, + 16..17, + 16..17, + 16..17, ], &config, ); diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 9bdbd4980..9a81ed3ac 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -454,13 +454,13 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &all_stark, &[ 16..17, - 8..15, - 7..17, - 4..15, + 11..15, + 12..17, 8..11, - 4..13, - 16..20, - 8..18, + 8..9, + 6..12, + 17..20, + 16..17, 16..17, ], &config, From 0804c38e385e8a4d1622507e522c9908c02d892e Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Tue, 30 Apr 2024 08:48:13 -0400 Subject: [PATCH 13/31] Add getter and handle single segment --- evm_arithmetization/src/prover.rs | 11 +++++++++++ evm_arithmetization/tests/log_opcode.rs | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 779eee8a9..732acdc80 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -56,6 +56,11 @@ pub struct GenerationSegmentData { } impl GenerationSegmentData { + /// Indicates if this segment is a dummy one. + pub fn is_dummy(&self) -> bool { + self.is_dummy + } + /// Retrieves the index of this segment. pub fn segment_index(&self) -> usize { self.segment_index @@ -563,6 +568,12 @@ pub fn generate_all_data_segments( }; } + // Handle single-segment case + if all_seg_data.len() == 1 { + segment_data.is_dummy = true; + all_seg_data.push(segment_data); + } + Ok(all_seg_data) } diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index bfb689e76..10fb1d18f 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -476,7 +476,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { None, )?; - assert_eq!(segment_proofs_data_first.len(), 1); + assert_eq!(segment_proofs_data_first.len(), 2); // second one is a dummy segment println!("Prove first aggreg..."); let (segment_agg_proof_first, updated_agg_public_values_first) = all_circuits @@ -486,8 +486,8 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { segment_proofs_data_first[0].public_values.clone(), false, true, - &segment_proofs_data_first[0].proof_with_pis, - segment_proofs_data_first[0].public_values.clone(), + &segment_proofs_data_first[1].proof_with_pis, + segment_proofs_data_first[1].public_values.clone(), )?; all_circuits.verify_segment_aggregation(&segment_agg_proof_first)?; From ee16349fe58568a7c1a55b87935ee7664bd57a59 Mon Sep 17 00:00:00 2001 From: Hamy Ratoanina Date: Mon, 20 May 2024 22:48:43 -0400 Subject: [PATCH 14/31] Dummy segments, new version --- .../src/fixed_recursive_verifier.rs | 317 ++++++++++-------- evm_arithmetization/src/proof.rs | 74 ++++ evm_arithmetization/src/prover.rs | 8 +- evm_arithmetization/tests/log_opcode.rs | 8 +- 4 files changed, 255 insertions(+), 152 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 8e3e59cda..f3c28f39d 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -867,107 +867,118 @@ where let lhs_pv = lhs_segment.public_values(&mut builder, cap_before_len); let rhs_pv = rhs_segment.public_values(&mut builder, cap_before_len); - // All the block metadata is the same for both segments. It is also the case for - // extra_block_data. + let is_dummy = rhs_segment.is_dummy; + let one = builder.one(); + let is_not_dummy = builder.sub(one, is_dummy.target); + let is_not_dummy = BoolTarget::new_unsafe(is_not_dummy); + + // Always connect the lhs to the aggregation public values. TrieRootsTarget::connect( &mut builder, public_values.trie_roots_before, lhs_pv.trie_roots_before, ); - TrieRootsTarget::connect( + BlockMetadataTarget::connect( + &mut builder, + public_values.block_metadata, + lhs_pv.block_metadata, + ); + BlockHashesTarget::connect( + &mut builder, + public_values.block_hashes, + lhs_pv.block_hashes, + ); + ExtraBlockDataTarget::connect( + &mut builder, + public_values.extra_block_data, + lhs_pv.extra_block_data, + ); + RegistersDataTarget::connect( + &mut builder, + public_values.registers_before.clone(), + lhs_pv.registers_before.clone(), + ); + MemCapTarget::connect( + &mut builder, + public_values.mem_before.clone(), + lhs_pv.mem_before.clone(), + ); + + // If the rhs is a real proof: All the block metadata is the same for both + // segments. It is also the case for extra_block_data. + TrieRootsTarget::assert_equal_if( &mut builder, + is_not_dummy, lhs_pv.trie_roots_after, rhs_pv.trie_roots_after, ); - TrieRootsTarget::connect( + TrieRootsTarget::assert_equal_if( &mut builder, + is_not_dummy, public_values.trie_roots_after, rhs_pv.trie_roots_after, ); - BlockMetadataTarget::connect( + BlockMetadataTarget::assert_equal_if( &mut builder, + is_not_dummy, public_values.block_metadata, rhs_pv.block_metadata, ); - BlockMetadataTarget::connect( - &mut builder, - public_values.block_metadata, - lhs_pv.block_metadata, - ); - BlockHashesTarget::connect( + BlockHashesTarget::assert_equal_if( &mut builder, + is_not_dummy, public_values.block_hashes, rhs_pv.block_hashes, ); - BlockHashesTarget::connect( - &mut builder, - public_values.block_hashes, - lhs_pv.block_hashes, - ); - ExtraBlockDataTarget::connect( + ExtraBlockDataTarget::assert_equal_if( &mut builder, + is_not_dummy, public_values.extra_block_data, rhs_pv.extra_block_data, ); - ExtraBlockDataTarget::connect( - &mut builder, - public_values.extra_block_data, - lhs_pv.extra_block_data, - ); - // Connect registers and merkle caps between segments. - RegistersDataTarget::connect( + // If the rhs is a real proof: Connect registers and merkle caps between + // segments. + RegistersDataTarget::assert_equal_if( &mut builder, + is_not_dummy, public_values.registers_after.clone(), rhs_pv.registers_after.clone(), ); - RegistersDataTarget::connect( - &mut builder, - public_values.registers_before.clone(), - lhs_pv.registers_before.clone(), - ); - RegistersDataTarget::connect( + RegistersDataTarget::assert_equal_if( &mut builder, + is_not_dummy, lhs_pv.registers_after, rhs_pv.registers_before.clone(), ); - MemCapTarget::connect( - &mut builder, - public_values.mem_before.clone(), - lhs_pv.mem_before.clone(), - ); - MemCapTarget::connect( + MemCapTarget::assert_equal_if( &mut builder, + is_not_dummy, public_values.mem_after.clone(), rhs_pv.mem_after.clone(), ); - MemCapTarget::connect(&mut builder, lhs_pv.mem_after, rhs_pv.mem_before.clone()); + MemCapTarget::assert_equal_if( + &mut builder, + is_not_dummy, + lhs_pv.mem_after.clone(), + rhs_pv.mem_before.clone(), + ); // If the rhs is a dummy, then the lhs must be a segment. - builder.mul_sub( - rhs_segment.is_dummy.target, - lhs_segment.is_agg.target, - rhs_segment.is_dummy.target, - ); + builder.mul_sub(is_dummy.target, lhs_segment.is_agg.target, is_dummy.target); - // If the rhs is a dummy, then its PV after must be equal to its PV before. + // If the rhs is a dummy, then the aggregation PVs are equal to the lhs PVs. TrieRootsTarget::assert_equal_if( &mut builder, - rhs_segment.is_dummy, - rhs_pv.trie_roots_before, - rhs_pv.trie_roots_after, - ); - RegistersDataTarget::assert_equal_if( - &mut builder, - rhs_segment.is_dummy, - rhs_pv.registers_before, - rhs_pv.registers_after, + is_dummy, + public_values.trie_roots_after, + lhs_pv.trie_roots_after, ); MemCapTarget::assert_equal_if( &mut builder, - rhs_segment.is_dummy, - rhs_pv.mem_before, - rhs_pv.mem_after, + is_dummy, + public_values.mem_after.clone(), + lhs_pv.mem_after.clone(), ); // Pad to match the root circuit's degree. @@ -1278,7 +1289,7 @@ where let is_dummy = builder.add_virtual_bool_target_safe(); let real_proof = builder.add_virtual_proof_with_pis(common); let (dummy_proof, dummy_vk) = builder - .dummy_proof_and_constant_vk_no_generator::(common) + .dummy_proof_and_vk::(common) .expect("Failed to build dummy proof."); let segment_proof = builder.select_proof_with_pis(is_dummy, &dummy_proof, &real_proof); @@ -1751,24 +1762,31 @@ where ); // Aggregates both `PublicValues` from the provided proofs into a single one. + + let real_public_values = if rhs_is_dummy { + lhs_public_values.clone() + } else { + rhs_public_values.clone() + }; + let agg_public_values = PublicValues { trie_roots_before: lhs_public_values.trie_roots_before, - trie_roots_after: rhs_public_values.trie_roots_after, + trie_roots_after: real_public_values.trie_roots_after, extra_block_data: ExtraBlockData { checkpoint_state_trie_root: lhs_public_values .extra_block_data .checkpoint_state_trie_root, txn_number_before: lhs_public_values.extra_block_data.txn_number_before, - txn_number_after: rhs_public_values.extra_block_data.txn_number_after, + txn_number_after: real_public_values.extra_block_data.txn_number_after, gas_used_before: lhs_public_values.extra_block_data.gas_used_before, - gas_used_after: rhs_public_values.extra_block_data.gas_used_after, + gas_used_after: real_public_values.extra_block_data.gas_used_after, }, - block_metadata: rhs_public_values.block_metadata, - block_hashes: rhs_public_values.block_hashes, + block_metadata: real_public_values.block_metadata, + block_hashes: real_public_values.block_hashes, registers_before: lhs_public_values.registers_before, - registers_after: rhs_public_values.registers_after, + registers_after: real_public_values.registers_after, mem_before: lhs_public_values.mem_before, - mem_after: rhs_public_values.mem_after, + mem_after: real_public_values.mem_after, }; set_public_value_targets( @@ -1970,88 +1988,97 @@ where &agg_child.agg_proof, proof, ); - if is_dummy { - let mut dummy_pis = proof.public_inputs.clone(); - // We must change trie roots before, registers before and memory before. - // Trie roots before := Trie roots after - dummy_pis.copy_within(TrieRootsTarget::SIZE..TrieRootsTarget::SIZE * 2, 0); - // Registers before := Registers after - dummy_pis.copy_within( - TrieRootsTarget::SIZE * 2 - + BlockMetadataTarget::SIZE - + BlockHashesTarget::SIZE - + ExtraBlockDataTarget::SIZE - + RegistersDataTarget::SIZE - ..TrieRootsTarget::SIZE * 2 - + BlockMetadataTarget::SIZE - + BlockHashesTarget::SIZE - + ExtraBlockDataTarget::SIZE - + RegistersDataTarget::SIZE * 2, - TrieRootsTarget::SIZE * 2 - + BlockMetadataTarget::SIZE - + BlockHashesTarget::SIZE - + ExtraBlockDataTarget::SIZE, - ); - // Mem before := Mem after - dummy_pis.copy_within( - TrieRootsTarget::SIZE * 2 - + BlockMetadataTarget::SIZE - + BlockHashesTarget::SIZE - + ExtraBlockDataTarget::SIZE - + RegistersDataTarget::SIZE * 2 - + len_mem_cap * NUM_HASH_OUT_ELTS - ..TrieRootsTarget::SIZE * 2 - + BlockMetadataTarget::SIZE - + BlockHashesTarget::SIZE - + ExtraBlockDataTarget::SIZE - + RegistersDataTarget::SIZE * 2 - + 2 * len_mem_cap * NUM_HASH_OUT_ELTS, - TrieRootsTarget::SIZE * 2 - + BlockMetadataTarget::SIZE - + BlockHashesTarget::SIZE - + ExtraBlockDataTarget::SIZE - + RegistersDataTarget::SIZE * 2, - ); - - // let lhs_pv = PublicValues::from_public_inputs(&proof.public_inputs, - // len_mem_cap); let mut dummy_pv = lhs_pv.clone(); - // dummy_pv.trie_roots_before = dummy_pv.trie_roots_after.clone(); - // dummy_pv.registers_before = dummy_pv.registers_after.clone(); - // dummy_pv.mem_before = dummy_pv.mem_after.clone(); - - // let dummy_pv_targets = PublicValuesTarget::from_public_inputs( - // &agg_child.dummy_proof.public_inputs, - // len_mem_cap, - // ); - - // let mut pw = PartialWitness::::new(); - // for (i, &pi) in dummy_pis.iter().enumerate() { - // pw.set_target(circuit.prover_only.public_inputs[i], pi); - // } - - let mut dummy_pis_map = HashMap::new(); - for (idx, &pi) in dummy_pis.iter().enumerate() { - dummy_pis_map.insert(idx, pi); - } - - let dummy_circuit = dummy_circuit::(&circuit.common); - println!("Generating dummy proof..."); - let dummy_proof = dummy_proof::(&dummy_circuit, dummy_pis_map) - .expect("Cannot generate dummy proof."); - println!("Dummy proof generated!"); - - //let dummy_proof = circuit.prove(pw).expect("Cannot generate dummy proof."); - - // let mut dummy_pis = vec![F::ZERO; circuit.common.num_public_inputs]; - - // let mut dummy_proof_with_pis = ProofWithPublicInputs { - // proof: dummy_proof, - // public_inputs: dummy_pis, - // } - agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, &dummy_proof); - // set_public_value_targets(agg_inputs, &dummy_pv_targets, - // &dummy_pv); - } else { + // If we have a dummy, the PVs are just copied from the lhs. + // if is_dummy { + // let mut dummy_pis = proof.public_inputs.clone(); + // // We must change trie roots before, registers before and + // memory before. // Trie roots before := Trie + // roots after + // dummy_pis.copy_within(TrieRootsTarget::SIZE.. + // TrieRootsTarget::SIZE * 2, 0); // Registers + // before := Registers after + // dummy_pis.copy_within( + // TrieRootsTarget::SIZE * 2 + // + BlockMetadataTarget::SIZE + // + BlockHashesTarget::SIZE + // + ExtraBlockDataTarget::SIZE + // + RegistersDataTarget::SIZE + // ..TrieRootsTarget::SIZE * 2 + // + BlockMetadataTarget::SIZE + // + BlockHashesTarget::SIZE + // + ExtraBlockDataTarget::SIZE + // + RegistersDataTarget::SIZE * 2, + // TrieRootsTarget::SIZE * 2 + // + BlockMetadataTarget::SIZE + // + BlockHashesTarget::SIZE + // + ExtraBlockDataTarget::SIZE, + // ); + // // Mem before := Mem after + // dummy_pis.copy_within( + // TrieRootsTarget::SIZE * 2 + // + BlockMetadataTarget::SIZE + // + BlockHashesTarget::SIZE + // + ExtraBlockDataTarget::SIZE + // + RegistersDataTarget::SIZE * 2 + // + len_mem_cap * NUM_HASH_OUT_ELTS + // ..TrieRootsTarget::SIZE * 2 + // + BlockMetadataTarget::SIZE + // + BlockHashesTarget::SIZE + // + ExtraBlockDataTarget::SIZE + // + RegistersDataTarget::SIZE * 2 + // + 2 * len_mem_cap * NUM_HASH_OUT_ELTS, + // TrieRootsTarget::SIZE * 2 + // + BlockMetadataTarget::SIZE + // + BlockHashesTarget::SIZE + // + ExtraBlockDataTarget::SIZE + // + RegistersDataTarget::SIZE * 2, + // ); + + // // let lhs_pv = + // PublicValues::from_public_inputs(&proof.public_inputs, + // // len_mem_cap); let mut dummy_pv = lhs_pv.clone(); + // // dummy_pv.trie_roots_before = + // dummy_pv.trie_roots_after.clone(); // dummy_pv. + // registers_before = dummy_pv.registers_after.clone(); + // // dummy_pv.mem_before = dummy_pv.mem_after.clone(); + + // // let dummy_pv_targets = + // PublicValuesTarget::from_public_inputs( // + // &agg_child.dummy_proof.public_inputs, // len_mem_cap, + // // ); + + // // let mut pw = PartialWitness::::new(); + // // for (i, &pi) in dummy_pis.iter().enumerate() { + // // pw.set_target(circuit.prover_only.public_inputs[i], + // pi); // } + + // let mut dummy_pis_map = HashMap::new(); + // for (idx, &pi) in dummy_pis.iter().enumerate() { + // dummy_pis_map.insert(idx, pi); + // } + + // let dummy_circuit = dummy_circuit::(&circuit.common); println!("Generating + // dummy proof..."); let dummy_proof = + // dummy_proof::(&dummy_circuit, dummy_pis_map) + // .expect("Cannot generate dummy proof."); + // println!("Dummy proof generated!"); + + // //let dummy_proof = circuit.prove(pw).expect("Cannot generate + // dummy proof."); + + // // let mut dummy_pis = vec![F::ZERO; + // circuit.common.num_public_inputs]; + + // // let mut dummy_proof_with_pis = ProofWithPublicInputs { + // // proof: dummy_proof, + // // public_inputs: dummy_pis, + // // } + // agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, + // &dummy_proof); // set_public_value_targets(agg_inputs, + // &dummy_pv_targets, // &dummy_pv); + //} + if !is_dummy { agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, proof); } } diff --git a/evm_arithmetization/src/proof.rs b/evm_arithmetization/src/proof.rs index 81b309056..200a7c570 100644 --- a/evm_arithmetization/src/proof.rs +++ b/evm_arithmetization/src/proof.rs @@ -959,6 +959,41 @@ impl BlockMetadataTarget { builder.connect(bm0.block_bloom[i], bm1.block_bloom[i]) } } + + /// If `condition`, asserts that `bm0 == bm1`. + pub(crate) fn assert_equal_if, const D: usize>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + bm0: Self, + bm1: Self, + ) { + for i in 0..5 { + builder.assert_equal_if( + condition.target, + bm0.block_beneficiary[i], + bm1.block_beneficiary[i], + ); + } + builder.assert_equal_if(condition.target, bm0.block_timestamp, bm1.block_timestamp); + builder.assert_equal_if(condition.target, bm0.block_number, bm1.block_number); + builder.assert_equal_if(condition.target, bm0.block_difficulty, bm1.block_difficulty); + for i in 0..8 { + builder.assert_equal_if(condition.target, bm0.block_random[i], bm1.block_random[i]); + } + builder.assert_equal_if(condition.target, bm0.block_gaslimit, bm1.block_gaslimit); + builder.assert_equal_if(condition.target, bm0.block_chain_id, bm1.block_chain_id); + for i in 0..2 { + builder.assert_equal_if( + condition.target, + bm0.block_base_fee[i], + bm1.block_base_fee[i], + ) + } + builder.assert_equal_if(condition.target, bm0.block_gas_used, bm1.block_gas_used); + for i in 0..64 { + builder.assert_equal_if(condition.target, bm0.block_bloom[i], bm1.block_bloom[i]) + } + } } /// Circuit version of `BlockHashes`. @@ -1024,6 +1059,21 @@ impl BlockHashesTarget { builder.connect(bm0.cur_hash[i], bm1.cur_hash[i]); } } + + /// If `condition`, asserts that `bm0 == bm1`. + pub(crate) fn assert_equal_if, const D: usize>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + bm0: Self, + bm1: Self, + ) { + for i in 0..2048 { + builder.assert_equal_if(condition.target, bm0.prev_hashes[i], bm1.prev_hashes[i]); + } + for i in 0..8 { + builder.assert_equal_if(condition.target, bm0.cur_hash[i], bm1.cur_hash[i]); + } + } } /// Circuit version of `ExtraBlockData`. @@ -1115,6 +1165,30 @@ impl ExtraBlockDataTarget { builder.connect(ed0.gas_used_before, ed1.gas_used_before); builder.connect(ed0.gas_used_after, ed1.gas_used_after); } + + /// If `condition`, asserts that `ed0 == ed1`. + pub(crate) fn assert_equal_if, const D: usize>( + builder: &mut CircuitBuilder, + condition: BoolTarget, + ed0: Self, + ed1: Self, + ) { + for i in 0..8 { + builder.assert_equal_if( + condition.target, + ed0.checkpoint_state_trie_root[i], + ed1.checkpoint_state_trie_root[i], + ); + } + builder.assert_equal_if( + condition.target, + ed0.txn_number_before, + ed1.txn_number_before, + ); + builder.assert_equal_if(condition.target, ed0.txn_number_after, ed1.txn_number_after); + builder.assert_equal_if(condition.target, ed0.gas_used_before, ed1.gas_used_before); + builder.assert_equal_if(condition.target, ed0.gas_used_after, ed1.gas_used_after); + } } /// Circuit version of `RegistersData`. diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 732acdc80..222b68bf5 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -569,10 +569,10 @@ pub fn generate_all_data_segments( } // Handle single-segment case - if all_seg_data.len() == 1 { - segment_data.is_dummy = true; - all_seg_data.push(segment_data); - } + // if all_seg_data.len() == 1 { + // segment_data.is_dummy = true; + // all_seg_data.push(segment_data); + // } Ok(all_seg_data) } diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 10fb1d18f..0be386891 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -476,7 +476,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { None, )?; - assert_eq!(segment_proofs_data_first.len(), 2); // second one is a dummy segment + assert_eq!(segment_proofs_data_first.len(), 1); // second one is a dummy segment println!("Prove first aggreg..."); let (segment_agg_proof_first, updated_agg_public_values_first) = all_circuits @@ -486,8 +486,8 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { segment_proofs_data_first[0].public_values.clone(), false, true, - &segment_proofs_data_first[1].proof_with_pis, - segment_proofs_data_first[1].public_values.clone(), + &segment_proofs_data_first[0].proof_with_pis, + segment_proofs_data_first[0].public_values.clone(), )?; all_circuits.verify_segment_aggregation(&segment_agg_proof_first)?; @@ -611,6 +611,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { }; let mut timing = TimingTree::new("prove root second", log::Level::Info); + println!("Prove second txn segments..."); let segment_proofs_data_second = &all_circuits.prove_all_segments( &all_stark, &config, @@ -629,6 +630,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { all_circuits.verify_root(proof.clone())?; } + println!("Prove second aggreg..."); let (segment_agg_proof_second, updated_agg_public_values_second) = all_circuits .prove_segment_aggregation( false, From 73fdf940722f52af78e00a112ddb414429b794f4 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Tue, 21 May 2024 15:49:56 +0800 Subject: [PATCH 15/31] Fix AggChildWithDummy --- Cargo.toml | 6 +- .../src/cpu/kernel/tests/bignum/mod.rs | 3 +- evm_arithmetization/src/cpu/kernel/utils.rs | 3 +- .../src/fixed_recursive_verifier.rs | 107 +----------------- .../src/keccak_sponge/keccak_sponge_stark.rs | 3 +- evm_arithmetization/src/logic.rs | 3 +- 6 files changed, 11 insertions(+), 114 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1ecfd3f1e..83ac16a25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,10 +21,10 @@ serde-big-array = "0.5.1" thiserror = "1.0.49" # plonky2-related dependencies -plonky2 = { git = "https://github.com/0xPolygonZero/plonky2.git", branch = "zkevm_no_dummy_segment" } +plonky2 = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "a599a526de4364dce9c14fb8a887c8c1bdb04a3b" } plonky2_maybe_rayon = "0.2.0" -plonky2_util = { git = "https://github.com/0xPolygonZero/plonky2.git", branch = "zkevm_no_dummy_segment" } -starky = { git = "https://github.com/0xPolygonZero/plonky2.git", branch = "zkevm_no_dummy_segment" } +plonky2_util = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "a599a526de4364dce9c14fb8a887c8c1bdb04a3b" } +starky = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "a599a526de4364dce9c14fb8a887c8c1bdb04a3b" } [workspace.package] diff --git a/evm_arithmetization/src/cpu/kernel/tests/bignum/mod.rs b/evm_arithmetization/src/cpu/kernel/tests/bignum/mod.rs index 0db8b13da..efb37bcd3 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/bignum/mod.rs @@ -9,7 +9,6 @@ use itertools::Itertools; use num::{BigUint, One, Zero}; use num_bigint::RandBigInt; use plonky2::field::goldilocks_field::GoldilocksField as F; -use plonky2_util::ceil_div_usize; use rand::Rng; use crate::cpu::kernel::aggregator::KERNEL; @@ -90,7 +89,7 @@ fn max_bignum(bit_size: usize) -> BigUint { } fn bignum_len(a: &BigUint) -> usize { - ceil_div_usize(a.bits() as usize, BIGNUM_LIMB_BITS) + (a.bits() as usize).div_ceil(BIGNUM_LIMB_BITS) } fn run_test(fn_label: &str, memory: Vec, stack: Vec) -> Result<(Vec, Vec)> { diff --git a/evm_arithmetization/src/cpu/kernel/utils.rs b/evm_arithmetization/src/cpu/kernel/utils.rs index adda086e8..082086d17 100644 --- a/evm_arithmetization/src/cpu/kernel/utils.rs +++ b/evm_arithmetization/src/cpu/kernel/utils.rs @@ -1,7 +1,6 @@ use core::fmt::Debug; use ethereum_types::U256; -use plonky2_util::ceil_div_usize; /// Enumerate the length `W` windows of `vec`, and run `maybe_replace` on each /// one. @@ -28,7 +27,7 @@ where } pub(crate) fn u256_to_trimmed_be_bytes(u256: &U256) -> Vec { - let num_bytes = ceil_div_usize(u256.bits(), 8); + let num_bytes = u256.bits().div_ceil(8); // `byte` is little-endian, so we manually reverse it. (0..num_bytes).rev().map(|i| u256.byte(i)).collect() } diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index f3c28f39d..471624ecc 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -278,7 +278,6 @@ struct AggregationChildWithDummyTarget { is_dummy: BoolTarget, agg_proof: ProofWithPublicInputsTarget, real_proof: ProofWithPublicInputsTarget, - dummy_proof: ProofWithPublicInputsTarget, } impl AggregationChildWithDummyTarget { @@ -287,7 +286,6 @@ impl AggregationChildWithDummyTarget { buffer.write_target_bool(self.is_dummy)?; buffer.write_target_proof_with_public_inputs(&self.agg_proof)?; buffer.write_target_proof_with_public_inputs(&self.real_proof)?; - buffer.write_target_proof_with_public_inputs(&self.dummy_proof)?; Ok(()) } @@ -296,13 +294,11 @@ impl AggregationChildWithDummyTarget { let is_dummy = buffer.read_target_bool()?; let agg_proof = buffer.read_target_proof_with_public_inputs()?; let real_proof = buffer.read_target_proof_with_public_inputs()?; - let dummy_proof = buffer.read_target_proof_with_public_inputs()?; Ok(Self { is_agg, is_dummy, agg_proof, real_proof, - dummy_proof, }) } @@ -315,11 +311,9 @@ impl AggregationChildWithDummyTarget { ) -> PublicValuesTarget { let agg_pv = PublicValuesTarget::from_public_inputs(&self.agg_proof.public_inputs, len_mem_cap); - let real_pv = + let segment_pv = PublicValuesTarget::from_public_inputs(&self.real_proof.public_inputs, len_mem_cap); - let dummy_pv = - PublicValuesTarget::from_public_inputs(&self.dummy_proof.public_inputs, len_mem_cap); - let segment_pv = PublicValuesTarget::select(builder, self.is_dummy, dummy_pv, real_pv); + PublicValuesTarget::select(builder, self.is_agg, agg_pv, segment_pv) } } @@ -965,7 +959,8 @@ where ); // If the rhs is a dummy, then the lhs must be a segment. - builder.mul_sub(is_dummy.target, lhs_segment.is_agg.target, is_dummy.target); + let constr = builder.mul(is_dummy.target, lhs_segment.is_agg.target); + builder.assert_zero(constr); // If the rhs is a dummy, then the aggregation PVs are equal to the lhs PVs. TrieRootsTarget::assert_equal_if( @@ -1308,7 +1303,6 @@ where is_dummy, agg_proof, real_proof, - dummy_proof, } } @@ -1988,99 +1982,6 @@ where &agg_child.agg_proof, proof, ); - // If we have a dummy, the PVs are just copied from the lhs. - // if is_dummy { - // let mut dummy_pis = proof.public_inputs.clone(); - // // We must change trie roots before, registers before and - // memory before. // Trie roots before := Trie - // roots after - // dummy_pis.copy_within(TrieRootsTarget::SIZE.. - // TrieRootsTarget::SIZE * 2, 0); // Registers - // before := Registers after - // dummy_pis.copy_within( - // TrieRootsTarget::SIZE * 2 - // + BlockMetadataTarget::SIZE - // + BlockHashesTarget::SIZE - // + ExtraBlockDataTarget::SIZE - // + RegistersDataTarget::SIZE - // ..TrieRootsTarget::SIZE * 2 - // + BlockMetadataTarget::SIZE - // + BlockHashesTarget::SIZE - // + ExtraBlockDataTarget::SIZE - // + RegistersDataTarget::SIZE * 2, - // TrieRootsTarget::SIZE * 2 - // + BlockMetadataTarget::SIZE - // + BlockHashesTarget::SIZE - // + ExtraBlockDataTarget::SIZE, - // ); - // // Mem before := Mem after - // dummy_pis.copy_within( - // TrieRootsTarget::SIZE * 2 - // + BlockMetadataTarget::SIZE - // + BlockHashesTarget::SIZE - // + ExtraBlockDataTarget::SIZE - // + RegistersDataTarget::SIZE * 2 - // + len_mem_cap * NUM_HASH_OUT_ELTS - // ..TrieRootsTarget::SIZE * 2 - // + BlockMetadataTarget::SIZE - // + BlockHashesTarget::SIZE - // + ExtraBlockDataTarget::SIZE - // + RegistersDataTarget::SIZE * 2 - // + 2 * len_mem_cap * NUM_HASH_OUT_ELTS, - // TrieRootsTarget::SIZE * 2 - // + BlockMetadataTarget::SIZE - // + BlockHashesTarget::SIZE - // + ExtraBlockDataTarget::SIZE - // + RegistersDataTarget::SIZE * 2, - // ); - - // // let lhs_pv = - // PublicValues::from_public_inputs(&proof.public_inputs, - // // len_mem_cap); let mut dummy_pv = lhs_pv.clone(); - // // dummy_pv.trie_roots_before = - // dummy_pv.trie_roots_after.clone(); // dummy_pv. - // registers_before = dummy_pv.registers_after.clone(); - // // dummy_pv.mem_before = dummy_pv.mem_after.clone(); - - // // let dummy_pv_targets = - // PublicValuesTarget::from_public_inputs( // - // &agg_child.dummy_proof.public_inputs, // len_mem_cap, - // // ); - - // // let mut pw = PartialWitness::::new(); - // // for (i, &pi) in dummy_pis.iter().enumerate() { - // // pw.set_target(circuit.prover_only.public_inputs[i], - // pi); // } - - // let mut dummy_pis_map = HashMap::new(); - // for (idx, &pi) in dummy_pis.iter().enumerate() { - // dummy_pis_map.insert(idx, pi); - // } - - // let dummy_circuit = dummy_circuit::(&circuit.common); println!("Generating - // dummy proof..."); let dummy_proof = - // dummy_proof::(&dummy_circuit, dummy_pis_map) - // .expect("Cannot generate dummy proof."); - // println!("Dummy proof generated!"); - - // //let dummy_proof = circuit.prove(pw).expect("Cannot generate - // dummy proof."); - - // // let mut dummy_pis = vec![F::ZERO; - // circuit.common.num_public_inputs]; - - // // let mut dummy_proof_with_pis = ProofWithPublicInputs { - // // proof: dummy_proof, - // // public_inputs: dummy_pis, - // // } - // agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, - // &dummy_proof); // set_public_value_targets(agg_inputs, - // &dummy_pv_targets, // &dummy_pv); - //} - if !is_dummy { - agg_inputs.set_proof_with_pis_target(&agg_child.dummy_proof, proof); - } } agg_inputs.set_proof_with_pis_target(&agg_child.real_proof, proof); } diff --git a/evm_arithmetization/src/keccak_sponge/keccak_sponge_stark.rs b/evm_arithmetization/src/keccak_sponge/keccak_sponge_stark.rs index db1efae99..73418c40f 100644 --- a/evm_arithmetization/src/keccak_sponge/keccak_sponge_stark.rs +++ b/evm_arithmetization/src/keccak_sponge/keccak_sponge_stark.rs @@ -13,7 +13,6 @@ use plonky2::iop::ext_target::ExtensionTarget; use plonky2::timed; use plonky2::util::timing::TimingTree; use plonky2::util::transpose; -use plonky2_util::ceil_div_usize; use starky::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; use starky::evaluation_frame::StarkEvaluationFrame; use starky::lookup::{Column, Filter, Lookup}; @@ -137,7 +136,7 @@ pub(crate) fn ctl_looking_memory(i: usize) -> Vec> { /// Returns the number of `KeccakSponge` tables looking into the `LogicStark`. pub(crate) const fn num_logic_ctls() -> usize { const U8S_PER_CTL: usize = 32; - ceil_div_usize(KECCAK_RATE_BYTES, U8S_PER_CTL) + KECCAK_RATE_BYTES.div_ceil(U8S_PER_CTL) } /// Creates the vector of `Columns` required to perform the `i`th logic CTL. diff --git a/evm_arithmetization/src/logic.rs b/evm_arithmetization/src/logic.rs index c5f952465..be389450c 100644 --- a/evm_arithmetization/src/logic.rs +++ b/evm_arithmetization/src/logic.rs @@ -10,7 +10,6 @@ use plonky2::hash::hash_types::RichField; use plonky2::iop::ext_target::ExtensionTarget; use plonky2::timed; use plonky2::util::timing::TimingTree; -use plonky2_util::ceil_div_usize; use starky::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer}; use starky::evaluation_frame::StarkEvaluationFrame; use starky::lookup::{Column, Filter}; @@ -28,7 +27,7 @@ const VAL_BITS: usize = 256; pub(crate) const PACKED_LIMB_BITS: usize = 32; /// Number of field elements needed to store each input/output at the specified /// packing. -const PACKED_LEN: usize = ceil_div_usize(VAL_BITS, PACKED_LIMB_BITS); +const PACKED_LEN: usize = VAL_BITS.div_ceil(PACKED_LIMB_BITS); /// `LogicStark` columns. pub(crate) mod columns { From 2941d723a53dec6b7bb36e5bd946e075037b6b08 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Tue, 21 May 2024 16:11:11 +0800 Subject: [PATCH 16/31] Update to latest version of zkevm_no_dummy_segment --- Cargo.toml | 6 +- .../src/fixed_recursive_verifier.rs | 34 ++++----- evm_arithmetization/src/proof.rs | 74 ++++++++++--------- 3 files changed, 60 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 83ac16a25..3c76a43be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,10 +21,10 @@ serde-big-array = "0.5.1" thiserror = "1.0.49" # plonky2-related dependencies -plonky2 = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "a599a526de4364dce9c14fb8a887c8c1bdb04a3b" } +plonky2 = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "dc77c77f2b06500e16ad4d7f1c2b057903602eed" } plonky2_maybe_rayon = "0.2.0" -plonky2_util = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "a599a526de4364dce9c14fb8a887c8c1bdb04a3b" } -starky = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "a599a526de4364dce9c14fb8a887c8c1bdb04a3b" } +plonky2_util = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "dc77c77f2b06500e16ad4d7f1c2b057903602eed" } +starky = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "dc77c77f2b06500e16ad4d7f1c2b057903602eed" } [workspace.package] diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 471624ecc..0315d7cc0 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -26,7 +26,7 @@ use plonky2::plonk::circuit_data::{ use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; -use plonky2::recursion::dummy_circuit::{self, cyclic_base_proof, dummy_circuit, dummy_proof}; +use plonky2::recursion::dummy_circuit::cyclic_base_proof; use plonky2::util::serialization::{ Buffer, GateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, }; @@ -856,7 +856,8 @@ where let cyclic_vk = builder.add_verifier_data_public_inputs(); let lhs_segment = Self::add_segment_agg_child(&mut builder, root); - let rhs_segment = Self::add_segment_agg_child_with_dummy(&mut builder, root); + let rhs_segment = + Self::add_segment_agg_child_with_dummy(&mut builder, root, lhs_segment.proof.clone()); let lhs_pv = lhs_segment.public_values(&mut builder, cap_before_len); let rhs_pv = rhs_segment.public_values(&mut builder, cap_before_len); @@ -900,31 +901,31 @@ where // If the rhs is a real proof: All the block metadata is the same for both // segments. It is also the case for extra_block_data. - TrieRootsTarget::assert_equal_if( + TrieRootsTarget::conditional_assert_eq( &mut builder, is_not_dummy, lhs_pv.trie_roots_after, rhs_pv.trie_roots_after, ); - TrieRootsTarget::assert_equal_if( + TrieRootsTarget::conditional_assert_eq( &mut builder, is_not_dummy, public_values.trie_roots_after, rhs_pv.trie_roots_after, ); - BlockMetadataTarget::assert_equal_if( + BlockMetadataTarget::conditional_assert_eq( &mut builder, is_not_dummy, public_values.block_metadata, rhs_pv.block_metadata, ); - BlockHashesTarget::assert_equal_if( + BlockHashesTarget::conditional_assert_eq( &mut builder, is_not_dummy, public_values.block_hashes, rhs_pv.block_hashes, ); - ExtraBlockDataTarget::assert_equal_if( + ExtraBlockDataTarget::conditional_assert_eq( &mut builder, is_not_dummy, public_values.extra_block_data, @@ -933,25 +934,25 @@ where // If the rhs is a real proof: Connect registers and merkle caps between // segments. - RegistersDataTarget::assert_equal_if( + RegistersDataTarget::conditional_assert_eq( &mut builder, is_not_dummy, public_values.registers_after.clone(), rhs_pv.registers_after.clone(), ); - RegistersDataTarget::assert_equal_if( + RegistersDataTarget::conditional_assert_eq( &mut builder, is_not_dummy, lhs_pv.registers_after, rhs_pv.registers_before.clone(), ); - MemCapTarget::assert_equal_if( + MemCapTarget::conditional_assert_eq( &mut builder, is_not_dummy, public_values.mem_after.clone(), rhs_pv.mem_after.clone(), ); - MemCapTarget::assert_equal_if( + MemCapTarget::conditional_assert_eq( &mut builder, is_not_dummy, lhs_pv.mem_after.clone(), @@ -963,13 +964,13 @@ where builder.assert_zero(constr); // If the rhs is a dummy, then the aggregation PVs are equal to the lhs PVs. - TrieRootsTarget::assert_equal_if( + TrieRootsTarget::conditional_assert_eq( &mut builder, is_dummy, public_values.trie_roots_after, lhs_pv.trie_roots_after, ); - MemCapTarget::assert_equal_if( + MemCapTarget::conditional_assert_eq( &mut builder, is_dummy, public_values.mem_after.clone(), @@ -1276,6 +1277,7 @@ where fn add_segment_agg_child_with_dummy( builder: &mut CircuitBuilder, root: &RootCircuitData, + dummy_proof: ProofWithPublicInputsTarget, ) -> AggregationChildWithDummyTarget { let common = &root.circuit.common; let root_vk = builder.constant_verifier_data(&root.circuit.verifier_only); @@ -1283,18 +1285,14 @@ where let agg_proof = builder.add_virtual_proof_with_pis(common); let is_dummy = builder.add_virtual_bool_target_safe(); let real_proof = builder.add_virtual_proof_with_pis(common); - let (dummy_proof, dummy_vk) = builder - .dummy_proof_and_vk::(common) - .expect("Failed to build dummy proof."); let segment_proof = builder.select_proof_with_pis(is_dummy, &dummy_proof, &real_proof); - let segment_vk = builder.select_verifier_data(is_dummy, &dummy_vk, &root_vk); builder .conditionally_verify_cyclic_proof::( is_agg, &agg_proof, &segment_proof, - &segment_vk, + &root_vk, common, ) .expect("Failed to build cyclic recursion circuit"); diff --git a/evm_arithmetization/src/proof.rs b/evm_arithmetization/src/proof.rs index 200a7c570..c9c0fb01b 100644 --- a/evm_arithmetization/src/proof.rs +++ b/evm_arithmetization/src/proof.rs @@ -823,20 +823,24 @@ impl TrieRootsTarget { } /// If `condition`, asserts that `tr0 == tr1`. - pub(crate) fn assert_equal_if, const D: usize>( + pub(crate) fn conditional_assert_eq, const D: usize>( builder: &mut CircuitBuilder, condition: BoolTarget, tr0: Self, tr1: Self, ) { for i in 0..8 { - builder.assert_equal_if(condition.target, tr0.state_root[i], tr1.state_root[i]); - builder.assert_equal_if( + builder.conditional_assert_eq(condition.target, tr0.state_root[i], tr1.state_root[i]); + builder.conditional_assert_eq( condition.target, tr0.transactions_root[i], tr1.transactions_root[i], ); - builder.assert_equal_if(condition.target, tr0.receipts_root[i], tr1.receipts_root[i]); + builder.conditional_assert_eq( + condition.target, + tr0.receipts_root[i], + tr1.receipts_root[i], + ); } } } @@ -961,37 +965,41 @@ impl BlockMetadataTarget { } /// If `condition`, asserts that `bm0 == bm1`. - pub(crate) fn assert_equal_if, const D: usize>( + pub(crate) fn conditional_assert_eq, const D: usize>( builder: &mut CircuitBuilder, condition: BoolTarget, bm0: Self, bm1: Self, ) { for i in 0..5 { - builder.assert_equal_if( + builder.conditional_assert_eq( condition.target, bm0.block_beneficiary[i], bm1.block_beneficiary[i], ); } - builder.assert_equal_if(condition.target, bm0.block_timestamp, bm1.block_timestamp); - builder.assert_equal_if(condition.target, bm0.block_number, bm1.block_number); - builder.assert_equal_if(condition.target, bm0.block_difficulty, bm1.block_difficulty); + builder.conditional_assert_eq(condition.target, bm0.block_timestamp, bm1.block_timestamp); + builder.conditional_assert_eq(condition.target, bm0.block_number, bm1.block_number); + builder.conditional_assert_eq(condition.target, bm0.block_difficulty, bm1.block_difficulty); for i in 0..8 { - builder.assert_equal_if(condition.target, bm0.block_random[i], bm1.block_random[i]); + builder.conditional_assert_eq( + condition.target, + bm0.block_random[i], + bm1.block_random[i], + ); } - builder.assert_equal_if(condition.target, bm0.block_gaslimit, bm1.block_gaslimit); - builder.assert_equal_if(condition.target, bm0.block_chain_id, bm1.block_chain_id); + builder.conditional_assert_eq(condition.target, bm0.block_gaslimit, bm1.block_gaslimit); + builder.conditional_assert_eq(condition.target, bm0.block_chain_id, bm1.block_chain_id); for i in 0..2 { - builder.assert_equal_if( + builder.conditional_assert_eq( condition.target, bm0.block_base_fee[i], bm1.block_base_fee[i], ) } - builder.assert_equal_if(condition.target, bm0.block_gas_used, bm1.block_gas_used); + builder.conditional_assert_eq(condition.target, bm0.block_gas_used, bm1.block_gas_used); for i in 0..64 { - builder.assert_equal_if(condition.target, bm0.block_bloom[i], bm1.block_bloom[i]) + builder.conditional_assert_eq(condition.target, bm0.block_bloom[i], bm1.block_bloom[i]) } } } @@ -1061,17 +1069,17 @@ impl BlockHashesTarget { } /// If `condition`, asserts that `bm0 == bm1`. - pub(crate) fn assert_equal_if, const D: usize>( + pub(crate) fn conditional_assert_eq, const D: usize>( builder: &mut CircuitBuilder, condition: BoolTarget, bm0: Self, bm1: Self, ) { for i in 0..2048 { - builder.assert_equal_if(condition.target, bm0.prev_hashes[i], bm1.prev_hashes[i]); + builder.conditional_assert_eq(condition.target, bm0.prev_hashes[i], bm1.prev_hashes[i]); } for i in 0..8 { - builder.assert_equal_if(condition.target, bm0.cur_hash[i], bm1.cur_hash[i]); + builder.conditional_assert_eq(condition.target, bm0.cur_hash[i], bm1.cur_hash[i]); } } } @@ -1167,27 +1175,27 @@ impl ExtraBlockDataTarget { } /// If `condition`, asserts that `ed0 == ed1`. - pub(crate) fn assert_equal_if, const D: usize>( + pub(crate) fn conditional_assert_eq, const D: usize>( builder: &mut CircuitBuilder, condition: BoolTarget, ed0: Self, ed1: Self, ) { for i in 0..8 { - builder.assert_equal_if( + builder.conditional_assert_eq( condition.target, ed0.checkpoint_state_trie_root[i], ed1.checkpoint_state_trie_root[i], ); } - builder.assert_equal_if( + builder.conditional_assert_eq( condition.target, ed0.txn_number_before, ed1.txn_number_before, ); - builder.assert_equal_if(condition.target, ed0.txn_number_after, ed1.txn_number_after); - builder.assert_equal_if(condition.target, ed0.gas_used_before, ed1.gas_used_before); - builder.assert_equal_if(condition.target, ed0.gas_used_after, ed1.gas_used_after); + builder.conditional_assert_eq(condition.target, ed0.txn_number_after, ed1.txn_number_after); + builder.conditional_assert_eq(condition.target, ed0.gas_used_before, ed1.gas_used_before); + builder.conditional_assert_eq(condition.target, ed0.gas_used_after, ed1.gas_used_after); } } @@ -1272,20 +1280,20 @@ impl RegistersDataTarget { } /// If `condition`, asserts that `rd0 == rd1`. - pub(crate) fn assert_equal_if, const D: usize>( + pub(crate) fn conditional_assert_eq, const D: usize>( builder: &mut CircuitBuilder, condition: BoolTarget, rd0: Self, rd1: Self, ) { - builder.assert_equal_if(condition.target, rd0.program_counter, rd1.program_counter); - builder.assert_equal_if(condition.target, rd0.is_kernel, rd1.is_kernel); - builder.assert_equal_if(condition.target, rd0.stack_len, rd1.stack_len); + builder.conditional_assert_eq(condition.target, rd0.program_counter, rd1.program_counter); + builder.conditional_assert_eq(condition.target, rd0.is_kernel, rd1.is_kernel); + builder.conditional_assert_eq(condition.target, rd0.stack_len, rd1.stack_len); for i in 0..8 { - builder.assert_equal_if(condition.target, rd0.stack_top[i], rd1.stack_top[i]); + builder.conditional_assert_eq(condition.target, rd0.stack_top[i], rd1.stack_top[i]); } - builder.assert_equal_if(condition.target, rd0.context, rd1.context); - builder.assert_equal_if(condition.target, rd0.gas_used, rd1.gas_used); + builder.conditional_assert_eq(condition.target, rd0.context, rd1.context); + builder.conditional_assert_eq(condition.target, rd0.gas_used, rd1.gas_used); } } @@ -1356,7 +1364,7 @@ impl MemCapTarget { } /// If `condition`, asserts that `mc0 == mc1`. - pub(crate) fn assert_equal_if, const D: usize>( + pub(crate) fn conditional_assert_eq, const D: usize>( builder: &mut CircuitBuilder, condition: BoolTarget, mc0: Self, @@ -1364,7 +1372,7 @@ impl MemCapTarget { ) { for i in 0..mc0.mem_cap.0.len() { for j in 0..NUM_HASH_OUT_ELTS { - builder.assert_equal_if( + builder.conditional_assert_eq( condition.target, mc0.mem_cap.0[i].elements[j], mc1.mem_cap.0[i].elements[j], From 483de98a8153467480d7e4cd654aa156008e634e Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Tue, 21 May 2024 17:40:33 +0800 Subject: [PATCH 17/31] Add is_dummy to ProverOutputData, remove the special logic for dummy segments, re-export dummy_proof in proof_gen and cleanup --- .../src/cpu/kernel/interpreter.rs | 2 +- .../src/cpu/kernel/tests/init_exc_stop.rs | 42 ++++++++++++++++--- .../src/fixed_recursive_verifier.rs | 14 ++++++- evm_arithmetization/src/generation/mod.rs | 2 +- evm_arithmetization/src/generation/state.rs | 15 ++----- evm_arithmetization/tests/empty_txn_list.rs | 4 +- evm_arithmetization/tests/log_opcode.rs | 12 +++--- proof_gen/Cargo.toml | 1 + proof_gen/src/proof_gen.rs | 15 ++----- 9 files changed, 68 insertions(+), 39 deletions(-) diff --git a/evm_arithmetization/src/cpu/kernel/interpreter.rs b/evm_arithmetization/src/cpu/kernel/interpreter.rs index 7a2b8a9ca..2b80edc38 100644 --- a/evm_arithmetization/src/cpu/kernel/interpreter.rs +++ b/evm_arithmetization/src/cpu/kernel/interpreter.rs @@ -496,7 +496,7 @@ impl Interpreter { } pub(crate) fn run(&mut self) -> Result<(RegistersState, Option), anyhow::Error> { - let (final_registers, final_mem) = self.run_cpu(self.max_cpu_len_log, self.is_dummy)?; + let (final_registers, final_mem) = self.run_cpu(self.max_cpu_len_log)?; #[cfg(debug_assertions)] { diff --git a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs index d63920e19..b7547b67d 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs @@ -13,8 +13,10 @@ use crate::generation::state::State; use crate::generation::TrieInputs; use crate::generation::NUM_EXTRA_CYCLES_AFTER; use crate::generation::NUM_EXTRA_CYCLES_BEFORE; +use crate::memory::segments::Segment; use crate::proof::BlockMetadata; use crate::proof::TrieRoots; +use crate::witness::memory::MemoryAddress; use crate::witness::state::RegistersState; use crate::{proof::BlockHashes, GenerationInputs, Node}; @@ -89,19 +91,47 @@ fn test_init_exc_stop() { "Incorrect registers for dummy run." ); - let main_offset = KERNEL.global_labels["main"]; - let mut interpreter: Interpreter = - Interpreter::new_dummy_with_generation_inputs(initial_offset, vec![], &inputs); + let exc_stop_offset = KERNEL.global_labels["exc_stop"]; + + let pc_u256 = U256::from(interpreter.get_registers().program_counter); + let exit_info = pc_u256 + (U256::one() << 32); + interpreter.push(exit_info).unwrap(); + interpreter.get_mut_registers().program_counter = exc_stop_offset; interpreter.halt_offsets = vec![KERNEL.global_labels["halt_final"]]; interpreter.set_is_kernel(true); interpreter.clock = 0; + + // Set the program counter and `is_kernel` at the end of the execution. They + // have offsets 6 and 7 respectively in segment `RegistersStates`. + let regs_to_set = [ + ( + MemoryAddress { + context: 0, + segment: Segment::RegistersStates.unscale(), + virt: 6, + }, + pc_u256, + ), + ( + MemoryAddress { + context: 0, + segment: Segment::RegistersStates.unscale(), + virt: 7, + }, + U256::one(), + ), + ]; + interpreter.set_memory_multi_addresses(®s_to_set); + interpreter.run().expect("Running dummy exc_stop failed."); - // The "-1" comes from the fact that we stop 1 cycle before the max, to allow - // for one padding row, which is needed for CPU STARK. + // The "-2" comes from the fact that: + // - we stop 1 cycle before the max, to allow for one padding row, which is + // needed for CPU STARK. + // - we normally need one additional cycle to enter `exc_stop`. assert_eq!( interpreter.get_clock(), - NUM_EXTRA_CYCLES_BEFORE + NUM_EXTRA_CYCLES_AFTER - 1, + NUM_EXTRA_CYCLES_AFTER - 2, "NUM_EXTRA_CYCLES_AFTER is set incorrectly." ); } diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 0315d7cc0..717e1e7a0 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -64,12 +64,14 @@ use crate::witness::state::RegistersState; /// this size. const THRESHOLD_DEGREE_BITS: usize = 13; +#[derive(Clone)] pub struct ProverOutputData where F: RichField + Extendable, C: GenericConfig, C::Hasher: AlgebraicHasher, { + pub is_dummy: bool, pub proof_with_pis: ProofWithPublicInputs, pub public_values: PublicValues, } @@ -1546,6 +1548,7 @@ where let root_proof = self.root.circuit.prove(root_inputs)?; Ok(ProverOutputData { + is_dummy: false, proof_with_pis: root_proof, public_values: all_proof.public_values, }) @@ -1577,6 +1580,12 @@ where proofs.push(proof); } + if proofs.len() == 1 { + let mut first_proof = proofs[0].clone(); + first_proof.is_dummy = true; + proofs.push(first_proof); + } + Ok(proofs) } @@ -1959,7 +1968,10 @@ where agg_inputs.set_proof_with_pis_target(&agg_child.proof, proof); } - /// TODO: Better comment. This function also takes care of the dummy PIs. + /// If the proof is not an aggregation, we set the cyclic vk to a dummy + /// value, so that it corresponds to the aggregation cyclic vk. If the proof + /// is dummy, we set `is_dummy` to `true`. Note that only the rhs can be + /// dummy. fn set_dummy_if_necessary_with_dummy( agg_child: &AggregationChildWithDummyTarget, is_agg: bool, diff --git a/evm_arithmetization/src/generation/mod.rs b/evm_arithmetization/src/generation/mod.rs index d8a5c41d8..f7646ab17 100644 --- a/evm_arithmetization/src/generation/mod.rs +++ b/evm_arithmetization/src/generation/mod.rs @@ -477,7 +477,7 @@ fn simulate_cpu( max_cpu_len_log: Option, is_dummy: bool, ) -> anyhow::Result<(RegistersState, Option)> { - let (final_registers, mem_after) = state.run_cpu(max_cpu_len_log, is_dummy)?; + let (final_registers, mem_after) = state.run_cpu(max_cpu_len_log)?; let pc = state.registers.program_counter; // Setting the values of padding rows. diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index 62df8a208..95e16fb8a 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -76,13 +76,9 @@ pub(crate) trait State { fn get_context(&self) -> usize; /// Checks whether we have reached the maximal cpu length. - fn at_end_segment(&self, opt_max_cpu_len: Option, is_dummy: bool) -> bool { + fn at_end_segment(&self, opt_max_cpu_len: Option) -> bool { if let Some(max_cpu_len_log) = opt_max_cpu_len { - if is_dummy { - self.get_clock() == max_cpu_len_log - NUM_EXTRA_CYCLES_AFTER - } else { - self.get_clock() == (1 << max_cpu_len_log) - NUM_EXTRA_CYCLES_AFTER - } + self.get_clock() == (1 << max_cpu_len_log) - NUM_EXTRA_CYCLES_AFTER } else { false } @@ -91,10 +87,8 @@ pub(crate) trait State { /// Checks whether we have reached the `halt` label in kernel mode. fn at_halt(&self) -> bool { let halt = KERNEL.global_labels["halt"]; - let halt_final = KERNEL.global_labels["halt_final"]; let registers = self.get_registers(); - registers.is_kernel - && (registers.program_counter == halt || registers.program_counter == halt_final) + registers.is_kernel && (registers.program_counter == halt) } /// Returns the context in which the jumpdest analysis should end. @@ -172,7 +166,6 @@ pub(crate) trait State { fn run_cpu( &mut self, max_cpu_len_log: Option, - is_dummy: bool, ) -> anyhow::Result<(RegistersState, Option)> where Self: Transition, @@ -188,7 +181,7 @@ pub(crate) trait State { let pc = registers.program_counter; let halt_final = registers.is_kernel && halt_offsets.contains(&pc); - if running && (self.at_halt() || self.at_end_segment(max_cpu_len_log, is_dummy)) { + if running && (self.at_halt() || self.at_end_segment(max_cpu_len_log)) { running = false; final_registers = registers; diff --git a/evm_arithmetization/tests/empty_txn_list.rs b/evm_arithmetization/tests/empty_txn_list.rs index e3a9e8e9e..915759c54 100644 --- a/evm_arithmetization/tests/empty_txn_list.rs +++ b/evm_arithmetization/tests/empty_txn_list.rs @@ -182,7 +182,7 @@ fn test_empty_txn_list() -> anyhow::Result<()> { &segment_proofs_data[0].proof_with_pis, segment_proofs_data[0].public_values.clone(), false, - false, + segment_proofs_data[1].is_dummy, &segment_proofs_data[1].proof_with_pis, segment_proofs_data[1].public_values.clone(), )?; @@ -194,7 +194,7 @@ fn test_empty_txn_list() -> anyhow::Result<()> { &segmented_agg_proof, segmented_agg_public_values, false, - false, + segment_proofs_data[2].is_dummy, &segment_proofs_data[2].proof_with_pis, segment_proofs_data[2].public_values.clone(), )?; diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index 0be386891..b9e795a79 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -476,7 +476,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { None, )?; - assert_eq!(segment_proofs_data_first.len(), 1); // second one is a dummy segment + assert_eq!(segment_proofs_data_first.len(), 2); // second one is a dummy segment println!("Prove first aggreg..."); let (segment_agg_proof_first, updated_agg_public_values_first) = all_circuits @@ -485,9 +485,9 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &segment_proofs_data_first[0].proof_with_pis, segment_proofs_data_first[0].public_values.clone(), false, - true, - &segment_proofs_data_first[0].proof_with_pis, - segment_proofs_data_first[0].public_values.clone(), + segment_proofs_data_first[1].is_dummy, + &segment_proofs_data_first[1].proof_with_pis, + segment_proofs_data_first[1].public_values.clone(), )?; all_circuits.verify_segment_aggregation(&segment_agg_proof_first)?; @@ -637,7 +637,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &segment_proofs_data_second[0].proof_with_pis, segment_proofs_data_second[0].public_values.clone(), false, - false, + segment_proofs_data_second[1].is_dummy, &segment_proofs_data_second[1].proof_with_pis, segment_proofs_data_second[1].public_values.clone(), )?; @@ -726,7 +726,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { &segment_proofs_data[0].proof_with_pis, segment_proofs_data[0].public_values.clone(), false, - false, + segment_proofs_data[1].is_dummy, &segment_proofs_data[1].proof_with_pis, segment_proofs_data[1].public_values.clone(), )?; diff --git a/proof_gen/Cargo.toml b/proof_gen/Cargo.toml index b0f6b680e..d8fe50890 100644 --- a/proof_gen/Cargo.toml +++ b/proof_gen/Cargo.toml @@ -15,6 +15,7 @@ log = { workspace = true } paste = "1.0.14" plonky2 = { workspace = true } serde = { workspace = true } +hashbrown = { version = "0.14.0" } # Local dependencies evm_arithmetization = { version = "0.1.3", path = "../evm_arithmetization" } diff --git a/proof_gen/src/proof_gen.rs b/proof_gen/src/proof_gen.rs index fb3799ca6..177f32233 100644 --- a/proof_gen/src/proof_gen.rs +++ b/proof_gen/src/proof_gen.rs @@ -4,9 +4,9 @@ use std::sync::{atomic::AtomicBool, Arc}; use evm_arithmetization::{prover::GenerationSegmentData, AllStark, GenerationInputs, StarkConfig}; +use hashbrown::HashMap; use plonky2::{ gates::noop::NoopGate, - iop::witness::PartialWitness, plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig}, util::timing::TimingTree, }; @@ -17,7 +17,7 @@ use crate::{ SegmentAggregatableProof, TxnAggregatableProof, }, prover_state::ProverState, - types::{Config, Field, PlonkyProofIntern, EXTENSION_DEGREE}, + types::{Field, PlonkyProofIntern, EXTENSION_DEGREE}, }; /// A type alias for `Result`. @@ -166,13 +166,6 @@ pub fn dummy_proof() -> ProofGenResult { builder.add_gate(NoopGate, vec![]); let circuit_data = builder.build::<_>(); - let inputs = PartialWitness::new(); - - plonky2::plonk::prover::prove::( - &circuit_data.prover_only, - &circuit_data.common, - inputs, - &mut TimingTree::default(), - ) - .map_err(|e| ProofGenError(e.to_string())) + plonky2::recursion::dummy_circuit::dummy_proof(&circuit_data, HashMap::default()) + .map_err(|e| ProofGenError(e.to_string())) } From bc3933b10035075b2ca6f05ee547311c3446c4c5 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Thu, 23 May 2024 10:59:47 +0800 Subject: [PATCH 18/31] Update proof_gen --- evm_arithmetization/src/prover.rs | 6 ------ proof_gen/src/proof_types.rs | 10 +++++++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 222b68bf5..06cd3a9a7 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -568,12 +568,6 @@ pub fn generate_all_data_segments( }; } - // Handle single-segment case - // if all_seg_data.len() == 1 { - // segment_data.is_dummy = true; - // all_seg_data.push(segment_data); - // } - Ok(all_seg_data) } diff --git a/proof_gen/src/proof_types.rs b/proof_gen/src/proof_types.rs index 94f5ff3be..bdbc0eac5 100644 --- a/proof_gen/src/proof_types.rs +++ b/proof_gen/src/proof_types.rs @@ -68,6 +68,9 @@ pub enum SegmentAggregatableProof { /// away whether or not the proof was a txn or agg proof. #[derive(Clone, Debug, Deserialize, Serialize)] pub enum TxnAggregatableProof { + /// The underlying proof is a segment proof. It first needs to be aggregated + /// with a dummy proof. + Segment(GeneratedSegmentProof), /// The underlying proof is a transaction proof. Txn(GeneratedSegmentAggProof), /// The underlying proof is an aggregation proof. @@ -100,6 +103,7 @@ impl SegmentAggregatableProof { impl TxnAggregatableProof { pub(crate) fn public_values(&self) -> PublicValues { match self { + TxnAggregatableProof::Segment(info) => info.p_vals.clone(), TxnAggregatableProof::Txn(info) => info.p_vals.clone(), TxnAggregatableProof::Agg(info) => info.p_vals.clone(), } @@ -107,6 +111,7 @@ impl TxnAggregatableProof { pub(crate) fn is_agg(&self) -> bool { match self { + TxnAggregatableProof::Segment(_) => false, TxnAggregatableProof::Txn(_) => false, TxnAggregatableProof::Agg(_) => true, } @@ -114,6 +119,7 @@ impl TxnAggregatableProof { pub(crate) fn intern(&self) -> &PlonkyProofIntern { match self { + TxnAggregatableProof::Segment(info) => &info.intern, TxnAggregatableProof::Txn(info) => &info.intern, TxnAggregatableProof::Agg(info) => &info.intern, } @@ -148,9 +154,7 @@ impl From for TxnAggregatableProof { fn from(v: SegmentAggregatableProof) -> Self { match v { SegmentAggregatableProof::Agg(agg) => TxnAggregatableProof::Txn(agg), - SegmentAggregatableProof::Txn(_) => { - panic!("Should be an aggregation by now. Missing segment?") - } + SegmentAggregatableProof::Txn(seg) => TxnAggregatableProof::Segment(seg), } } } From 58d1e6ace597ee489a6793b39a07550482d8ecfb Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Fri, 24 May 2024 17:55:24 +0800 Subject: [PATCH 19/31] Cleanup and add missing connections in create_segment_aggregation_circuit --- .../src/fixed_recursive_verifier.rs | 27 ++++++++++++------- evm_arithmetization/tests/log_opcode.rs | 4 --- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 789687632..27b619f81 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -857,6 +857,7 @@ where let public_values = add_virtual_public_values(&mut builder, cap_before_len); let cyclic_vk = builder.add_verifier_data_public_inputs(); + // The right hand side child might be dummy. let lhs_segment = Self::add_segment_agg_child(&mut builder, root); let rhs_segment = Self::add_segment_agg_child_with_dummy(&mut builder, root, lhs_segment.proof.clone()); @@ -875,6 +876,11 @@ where public_values.trie_roots_before, lhs_pv.trie_roots_before, ); + TrieRootsTarget::connect( + &mut builder, + public_values.trie_roots_after, + lhs_pv.trie_roots_after, + ); BlockMetadataTarget::connect( &mut builder, public_values.block_metadata, @@ -906,8 +912,8 @@ where TrieRootsTarget::conditional_assert_eq( &mut builder, is_not_dummy, - lhs_pv.trie_roots_after, - rhs_pv.trie_roots_after, + public_values.trie_roots_before, + rhs_pv.trie_roots_before, ); TrieRootsTarget::conditional_assert_eq( &mut builder, @@ -945,7 +951,7 @@ where RegistersDataTarget::conditional_assert_eq( &mut builder, is_not_dummy, - lhs_pv.registers_after, + lhs_pv.registers_after.clone(), rhs_pv.registers_before.clone(), ); MemCapTarget::conditional_assert_eq( @@ -966,17 +972,17 @@ where builder.assert_zero(constr); // If the rhs is a dummy, then the aggregation PVs are equal to the lhs PVs. - TrieRootsTarget::conditional_assert_eq( + MemCapTarget::conditional_assert_eq( &mut builder, is_dummy, - public_values.trie_roots_after, - lhs_pv.trie_roots_after, + public_values.mem_after.clone(), + lhs_pv.mem_after, ); - MemCapTarget::conditional_assert_eq( + RegistersDataTarget::conditional_assert_eq( &mut builder, is_dummy, - public_values.mem_after.clone(), - lhs_pv.mem_after.clone(), + public_values.registers_after.clone(), + lhs_pv.registers_after, ); // Pad to match the root circuit's degree. @@ -1580,6 +1586,8 @@ where proofs.push(proof); } + // Since aggregations require at least two segment proofs, add a dummy proof if + // there is only one proof. if proofs.len() == 1 { let mut first_proof = proofs[0].clone(); first_proof.is_dummy = true; @@ -1745,6 +1753,7 @@ where .0 .len(); + // If rhs is dummy, the rhs proof is also set to be the lhs. let real_rhs_proof = if rhs_is_dummy { lhs_proof } else { rhs_proof }; Self::set_dummy_if_necessary_with_dummy( diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index b9e795a79..8ff7c73e1 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -465,7 +465,6 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { let mut timing = TimingTree::new("prove root first", log::Level::Info); let max_cpu_len_log = 15; - println!("Prove first txn segment..."); let segment_proofs_data_first = &all_circuits.prove_all_segments( &all_stark, &config, @@ -478,7 +477,6 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { assert_eq!(segment_proofs_data_first.len(), 2); // second one is a dummy segment - println!("Prove first aggreg..."); let (segment_agg_proof_first, updated_agg_public_values_first) = all_circuits .prove_segment_aggregation( false, @@ -611,7 +609,6 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { }; let mut timing = TimingTree::new("prove root second", log::Level::Info); - println!("Prove second txn segments..."); let segment_proofs_data_second = &all_circuits.prove_all_segments( &all_stark, &config, @@ -630,7 +627,6 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { all_circuits.verify_root(proof.clone())?; } - println!("Prove second aggreg..."); let (segment_agg_proof_second, updated_agg_public_values_second) = all_circuits .prove_segment_aggregation( false, From 08dd0ab7af0151c778c99ea6544edf05bac36664 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Wed, 29 May 2024 15:54:29 +0800 Subject: [PATCH 20/31] Create generate_next_segment and make_dummy_segment --- evm_arithmetization/src/prover.rs | 69 ++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index e3003ee38..fd7d70c9a 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -25,7 +25,7 @@ use starky::stark::Stark; use crate::all_stark::{AllStark, Table, NUM_TABLES}; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::{set_registers_and_run, ExtraSegmentData, Interpreter}; -use crate::generation::state::GenerationState; +use crate::generation::state::{GenerationState, State}; use crate::generation::{generate_traces, GenerationInputs}; use crate::get_challenges::observe_public_values; use crate::memory::segments::Segment; @@ -53,6 +53,18 @@ pub struct GenerationSegmentData { pub(crate) max_cpu_len_log: Option, } +/// Dummy data used for padding. +pub fn make_dummy_segment_data(template: GenerationSegmentData) -> GenerationSegmentData { + assert!( + template.registers_after.program_counter == KERNEL.global_labels["halt"], + "Dummy segment isn't terminal." + ); + GenerationSegmentData { + registers_before: template.registers_after, + ..template + } +} + impl GenerationSegmentData { /// Indicates if this segment is a dummy one. pub fn is_dummy(&self) -> bool { @@ -523,6 +535,61 @@ fn build_segment_data( } } +/// Returns the data for the current segment, as well as the data -- except +/// registers_after -- for the next segment. +pub fn generate_next_segment( + max_cpu_len_log: Option, + inputs: &GenerationInputs, + partial_segment_data: Option, +) -> Option<(GenerationSegmentData, Option)> { + let mut interpreter = Interpreter::::new_with_generation_inputs( + KERNEL.global_labels["init"], + vec![], + inputs, + max_cpu_len_log, + ); + + // Get the (partial) current segment data, if it is provided. Otherwise, + // initialize it. + let mut segment_data = if let Some(partial) = partial_segment_data { + if partial.registers_after.program_counter == KERNEL.global_labels["halt"] { + return None; + } + interpreter + .get_mut_generation_state() + .set_segment_data(&partial); + interpreter.generation_state.memory = partial.memory.clone(); + partial + } else { + build_segment_data(0, None, None, None, &interpreter) + }; + + let segment_index = segment_data.segment_index; + + // Run the interpreter to get `registers_after` and the partial data for the + // next segment. + let run_result = set_registers_and_run(segment_data.registers_after, &mut interpreter); + + if let Ok((updated_registers, mem_after)) = run_result { + // Set `registers_after` correctly and push the data. + let before_registers = segment_data.registers_after; + + let partial_segment_data = Some(build_segment_data( + segment_index + 1, + Some(updated_registers), + Some(updated_registers), + mem_after, + &interpreter, + )); + + segment_data.registers_after = updated_registers; + + Some((segment_data, partial_segment_data)) + } else { + None + } +} + /// Returns a vector containing the data required to generate all the segments /// of a transaction. pub fn generate_all_data_segments( From 5578e8bc7ca75dc43d921b35bd9a73976f06ba04 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Wed, 29 May 2024 20:51:02 +0800 Subject: [PATCH 21/31] Add debug log --- evm_arithmetization/src/prover.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index fd7d70c9a..bc756e162 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -565,6 +565,10 @@ pub fn generate_next_segment( }; let segment_index = segment_data.segment_index; + log::info!( + "Starting generate_next_segment for index {}. Interpreter already created.", + segment_index + ); // Run the interpreter to get `registers_after` and the partial data for the // next segment. @@ -583,9 +587,10 @@ pub fn generate_next_segment( )); segment_data.registers_after = updated_registers; - + log::info!("Done with segment {:?}", segment_index); Some((segment_data, partial_segment_data)) } else { + log::info!("Done with segment {:?}", segment_index); None } } From 717d29c7f4452d388e412f12b4b510560574e7db Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Thu, 30 May 2024 18:25:45 +0800 Subject: [PATCH 22/31] Have teh SegmentDataIterator in zk_evm and change prove_all_segments to use it --- .../src/fixed_recursive_verifier.rs | 22 ++++++--- evm_arithmetization/src/prover.rs | 45 +++++++++++++++++-- evm_arithmetization/tests/log_opcode.rs | 2 +- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index e0e39b2c9..fa8039ea9 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -49,7 +49,10 @@ use crate::proof::{ FinalPublicValues, MemCapTarget, PublicValues, PublicValuesTarget, RegistersDataTarget, TrieRoots, TrieRootsTarget, TARGET_HASH_SIZE, }; -use crate::prover::{check_abort_signal, generate_all_data_segments, prove, GenerationSegmentData}; +use crate::prover::{ + check_abort_signal, generate_all_data_segments, prove, GenerationSegmentData, + SegmentDataIterator, +}; use crate::recursive_verifier::{ add_common_recursion_gates, add_virtual_public_values, get_memory_extra_looking_sum_circuit, recursive_stark_circuit, set_public_value_targets, PlonkWrapperCircuit, PublicInputs, @@ -1560,15 +1563,22 @@ where timing: &mut TimingTree, abort_signal: Option>, ) -> anyhow::Result>> { - let mut all_data_segments = - generate_all_data_segments::(Some(max_cpu_len_log), &generation_inputs)?; - let mut proofs = Vec::with_capacity(all_data_segments.len()); - for mut data in all_data_segments { + // log::info!("hello"); + let mut it_segment_data = SegmentDataIterator { + inputs: generation_inputs.clone(), + partial_next_data: None, + max_cpu_len_log: Some(max_cpu_len_log), + nb_segments: 0, + }; + + let mut proofs = vec![]; + + while let Some(mut next_data) = it_segment_data.next() { let proof = self.prove_segment( all_stark, config, generation_inputs.clone(), - &mut data, + &mut next_data.1, timing, abort_signal.clone(), )?; diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index bc756e162..62be6fc2e 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -5,6 +5,7 @@ use anyhow::{anyhow, Result}; use itertools::Itertools; use once_cell::sync::Lazy; use plonky2::field::extension::Extendable; +use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::polynomial::PolynomialValues; use plonky2::field::types::Field; use plonky2::fri::oracle::PolynomialBatch; @@ -54,7 +55,7 @@ pub struct GenerationSegmentData { } /// Dummy data used for padding. -pub fn make_dummy_segment_data(template: GenerationSegmentData) -> GenerationSegmentData { +pub(crate) fn make_dummy_segment_data(template: GenerationSegmentData) -> GenerationSegmentData { assert!( template.registers_after.program_counter == KERNEL.global_labels["halt"], "Dummy segment isn't terminal." @@ -535,9 +536,47 @@ fn build_segment_data( } } +pub struct SegmentDataIterator { + pub partial_next_data: Option, + pub inputs: GenerationInputs, + pub max_cpu_len_log: Option, + pub nb_segments: usize, +} + +type F = GoldilocksField; +impl Iterator for SegmentDataIterator { + type Item = (GenerationInputs, GenerationSegmentData); + + fn next(&mut self) -> Option { + let cur_and_next_data = generate_next_segment::( + self.max_cpu_len_log, + &self.inputs, + self.partial_next_data.clone(), + ); + + if cur_and_next_data.is_some() { + let (data, next_data) = cur_and_next_data.expect( + "Data cannot be +`None`", + ); + self.nb_segments += 1; + self.partial_next_data = next_data; + Some((self.inputs.clone(), data)) + } else { + if self.nb_segments == 1 { + let data = self.partial_next_data.clone().expect("eyo"); + self.nb_segments += 1; + Some((self.inputs.clone(), make_dummy_segment_data(data))) + } else { + None + } + } + } +} + /// Returns the data for the current segment, as well as the data -- except /// registers_after -- for the next segment. -pub fn generate_next_segment( +pub(crate) fn generate_next_segment( max_cpu_len_log: Option, inputs: &GenerationInputs, partial_segment_data: Option, @@ -587,10 +626,8 @@ pub fn generate_next_segment( )); segment_data.registers_after = updated_registers; - log::info!("Done with segment {:?}", segment_index); Some((segment_data, partial_segment_data)) } else { - log::info!("Done with segment {:?}", segment_index); None } } diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index d428966c9..ad220ae31 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -463,7 +463,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { ); let mut timing = TimingTree::new("prove root first", log::Level::Info); - let max_cpu_len_log = 15; + let max_cpu_len_log = 20; let segment_proofs_data_first = &all_circuits.prove_all_segments( &all_stark, From 3261e6285af9225f9cd699051f0a6a311760985f Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Fri, 31 May 2024 10:44:41 +0800 Subject: [PATCH 23/31] Remove dummy segment in SegmentDataIterator --- evm_arithmetization/src/prover.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 62be6fc2e..d34200bc9 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -54,18 +54,6 @@ pub struct GenerationSegmentData { pub(crate) max_cpu_len_log: Option, } -/// Dummy data used for padding. -pub(crate) fn make_dummy_segment_data(template: GenerationSegmentData) -> GenerationSegmentData { - assert!( - template.registers_after.program_counter == KERNEL.global_labels["halt"], - "Dummy segment isn't terminal." - ); - GenerationSegmentData { - registers_before: template.registers_after, - ..template - } -} - impl GenerationSegmentData { /// Indicates if this segment is a dummy one. pub fn is_dummy(&self) -> bool { @@ -563,13 +551,7 @@ impl Iterator for SegmentDataIterator { self.partial_next_data = next_data; Some((self.inputs.clone(), data)) } else { - if self.nb_segments == 1 { - let data = self.partial_next_data.clone().expect("eyo"); - self.nb_segments += 1; - Some((self.inputs.clone(), make_dummy_segment_data(data))) - } else { - None - } + None } } } From a289b7a379ad592e18db16aff061720c13c78f16 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Fri, 31 May 2024 10:55:37 +0800 Subject: [PATCH 24/31] Clippy and cleanup --- evm_arithmetization/src/fixed_recursive_verifier.rs | 3 +-- evm_arithmetization/src/prover.rs | 4 ---- evm_arithmetization/tests/log_opcode.rs | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index fa8039ea9..54bdc7865 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -1563,7 +1563,6 @@ where timing: &mut TimingTree, abort_signal: Option>, ) -> anyhow::Result>> { - // log::info!("hello"); let mut it_segment_data = SegmentDataIterator { inputs: generation_inputs.clone(), partial_next_data: None, @@ -1573,7 +1572,7 @@ where let mut proofs = vec![]; - while let Some(mut next_data) = it_segment_data.next() { + for mut next_data in it_segment_data { let proof = self.prove_segment( all_stark, config, diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index d34200bc9..1c1711dd0 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -586,10 +586,6 @@ pub(crate) fn generate_next_segment( }; let segment_index = segment_data.segment_index; - log::info!( - "Starting generate_next_segment for index {}. Interpreter already created.", - segment_index - ); // Run the interpreter to get `registers_after` and the partial data for the // next segment. diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index ad220ae31..d428966c9 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -463,7 +463,7 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { ); let mut timing = TimingTree::new("prove root first", log::Level::Info); - let max_cpu_len_log = 20; + let max_cpu_len_log = 15; let segment_proofs_data_first = &all_circuits.prove_all_segments( &all_stark, From 60f67a843cf5605297771b8142c8605eed8d00c0 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Thu, 6 Jun 2024 14:24:00 +0800 Subject: [PATCH 25/31] Apply comments --- Cargo.toml | 1 + evm_arithmetization/Cargo.toml | 2 +- .../src/cpu/kernel/tests/init_exc_stop.rs | 14 ++-- .../src/fixed_recursive_verifier.rs | 50 +++++++------- evm_arithmetization/src/generation/state.rs | 11 ++-- evm_arithmetization/src/proof.rs | 12 ++++ evm_arithmetization/tests/empty_txn_list.rs | 59 +++++++++-------- evm_arithmetization/tests/log_opcode.rs | 65 ++++++++----------- proof_gen/Cargo.toml | 2 +- proof_gen/src/proof_gen.rs | 28 ++++++-- 10 files changed, 135 insertions(+), 109 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3c76a43be..767178329 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ serde = "1.0.166" serde_json = "1.0.96" serde-big-array = "0.5.1" thiserror = "1.0.49" +hashbrown = "0.14.0" # plonky2-related dependencies plonky2 = { git = "https://github.com/0xPolygonZero/plonky2.git", rev = "dc77c77f2b06500e16ad4d7f1c2b057903602eed" } diff --git a/evm_arithmetization/Cargo.toml b/evm_arithmetization/Cargo.toml index 7835399a4..0a3894be1 100644 --- a/evm_arithmetization/Cargo.toml +++ b/evm_arithmetization/Cargo.toml @@ -36,7 +36,7 @@ rlp = { workspace = true } rlp-derive = { workspace = true } serde = { workspace = true, features = ["derive"] } static_assertions = "1.1.0" -hashbrown = { version = "0.14.0" } +hashbrown = { workspace = true } tiny-keccak = "2.0.2" serde_json = { workspace = true } serde-big-array = { workspace = true } diff --git a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs index c33455d09..e37407034 100644 --- a/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs +++ b/evm_arithmetization/src/cpu/kernel/tests/init_exc_stop.rs @@ -15,6 +15,8 @@ use crate::generation::NUM_EXTRA_CYCLES_AFTER; use crate::generation::NUM_EXTRA_CYCLES_BEFORE; use crate::memory::segments::Segment; use crate::proof::BlockMetadata; +use crate::proof::RegistersData; +use crate::proof::RegistersIdx; use crate::proof::TrieRoots; use crate::witness::memory::MemoryAddress; use crate::witness::state::RegistersState; @@ -101,14 +103,16 @@ fn test_init_exc_stop() { interpreter.set_is_kernel(true); interpreter.clock = 0; - // Set the program counter and `is_kernel` at the end of the execution. They - // have offsets 6 and 7 respectively in segment `RegistersStates`. + // Set the program counter and `is_kernel` at the end of the execution. The + // `registers_before` and `registers_after` are stored contiguously in the + // `RegistersState` segment. We need to update `registers_after` here, hence the + // offset by `RegistersData::SIZE`. let regs_to_set = [ ( MemoryAddress { context: 0, segment: Segment::RegistersStates.unscale(), - virt: 6, + virt: RegistersData::SIZE + RegistersIdx::ProgramCounter as usize, }, pc_u256, ), @@ -116,7 +120,7 @@ fn test_init_exc_stop() { MemoryAddress { context: 0, segment: Segment::RegistersStates.unscale(), - virt: 7, + virt: RegistersData::SIZE + RegistersIdx::IsKernel as usize, }, U256::one(), ), @@ -128,7 +132,7 @@ fn test_init_exc_stop() { // The "-2" comes from the fact that: // - we stop 1 cycle before the max, to allow for one padding row, which is // needed for CPU STARK. - // - we normally need one additional cycle to enter `exc_stop`. + // - we need one additional cycle to enter `exc_stop`. assert_eq!( interpreter.get_clock(), NUM_EXTRA_CYCLES_AFTER - 2, diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index e0e39b2c9..cc4f7bfb3 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -900,8 +900,8 @@ where lhs_pv.mem_before.clone(), ); - // If the rhs is a real proof: All the block metadata is the same for both - // segments. It is also the case for extra_block_data. + // If the rhs is a real proof, all the block metadata must be the same for both + // segments. It is also the case for the extra block data. TrieRootsTarget::conditional_assert_eq( &mut builder, is_not_dummy, @@ -1695,35 +1695,29 @@ where /// /// - `lhs_is_agg`: a boolean indicating whether the left child proof is an /// aggregation proof or a regular segment proof. - /// - `lhs_proof`: the left child proof. - /// - `lhs_public_values`: the public values associated to the right child - /// proof. + /// - `lhs_proof`: the left child prover output data. /// - `rhs_is_agg`: a boolean indicating whether the right child proof is an /// aggregation proof or a regular transaction proof. - /// - `rhs_proof`: the right child proof. - /// - `rhs_public_values`: the public values associated to the right child - /// proof. + /// - `rhs_proof`: the right child prover output data. /// /// # Outputs /// - /// This method outputs a tuple of [`ProofWithPublicInputs`] and - /// its [`PublicValues`]. Only the proof with public inputs is necessary - /// for a verifier to assert correctness of the computation, - /// but the public values are output for the prover convenience, as these - /// are necessary during proof aggregation. + /// This method outputs a [`ProverOutputData`]. Only the proof with + /// public inputs is necessary for a verifier to assert correctness of + /// the computation, but the public values and `is_dummy` are output for the + /// prover convenience, as these are necessary during proof aggregation. pub fn prove_segment_aggregation( &self, lhs_is_agg: bool, - lhs_proof: &ProofWithPublicInputs, - lhs_public_values: PublicValues, - + lhs_prover_output: &ProverOutputData, rhs_is_agg: bool, - rhs_is_dummy: bool, - rhs_proof: &ProofWithPublicInputs, - rhs_public_values: PublicValues, - ) -> anyhow::Result<(ProofWithPublicInputs, PublicValues)> { + rhs_prover_output: &ProverOutputData, + ) -> anyhow::Result> { let mut agg_inputs = PartialWitness::new(); + let lhs_proof = &lhs_prover_output.proof_with_pis; + let rhs_proof = &rhs_prover_output.proof_with_pis; + let rhs_is_dummy = rhs_prover_output.is_dummy; Self::set_dummy_if_necessary( &self.segment_aggregation.lhs, lhs_is_agg, @@ -1760,6 +1754,9 @@ where // Aggregates both `PublicValues` from the provided proofs into a single one. + let lhs_public_values = &lhs_prover_output.public_values; + let rhs_public_values = &rhs_prover_output.public_values; + let real_public_values = if rhs_is_dummy { lhs_public_values.clone() } else { @@ -1767,7 +1764,7 @@ where }; let agg_public_values = PublicValues { - trie_roots_before: lhs_public_values.trie_roots_before, + trie_roots_before: lhs_public_values.trie_roots_before.clone(), trie_roots_after: real_public_values.trie_roots_after, extra_block_data: ExtraBlockData { checkpoint_state_trie_root: lhs_public_values @@ -1780,9 +1777,9 @@ where }, block_metadata: real_public_values.block_metadata, block_hashes: real_public_values.block_hashes, - registers_before: lhs_public_values.registers_before, + registers_before: lhs_public_values.registers_before.clone(), registers_after: real_public_values.registers_after, - mem_before: lhs_public_values.mem_before, + mem_before: lhs_public_values.mem_before.clone(), mem_after: real_public_values.mem_after, }; @@ -1796,7 +1793,12 @@ where })?; let aggregation_proof = self.segment_aggregation.circuit.prove(agg_inputs)?; - Ok((aggregation_proof, agg_public_values)) + let agg_output = ProverOutputData { + is_dummy: false, + proof_with_pis: aggregation_proof, + public_values: agg_public_values, + }; + Ok(agg_output) } pub fn verify_segment_aggregation( diff --git a/evm_arithmetization/src/generation/state.rs b/evm_arithmetization/src/generation/state.rs index b4f5c8768..b804b4a49 100644 --- a/evm_arithmetization/src/generation/state.rs +++ b/evm_arithmetization/src/generation/state.rs @@ -77,9 +77,9 @@ pub(crate) trait State { fn get_context(&self) -> usize; /// Checks whether we have reached the maximal cpu length. - fn at_end_segment(&self, opt_max_cpu_len: Option) -> bool { - if let Some(max_cpu_len_log) = opt_max_cpu_len { - self.get_clock() == (1 << max_cpu_len_log) - NUM_EXTRA_CYCLES_AFTER + fn at_end_segment(&self, opt_cycle_limit: Option) -> bool { + if let Some(cycle_limit) = opt_cycle_limit { + self.get_clock() == cycle_limit } else { false } @@ -173,6 +173,9 @@ pub(crate) trait State { { let halt_offsets = self.get_halt_offsets(); + let cycle_limit = + max_cpu_len_log.map(|max_len_log| (1 << max_len_log) - NUM_EXTRA_CYCLES_AFTER); + let mut final_registers = RegistersState::default(); let final_mem = self.get_generation_state().memory.clone(); let mut running = true; @@ -182,7 +185,7 @@ pub(crate) trait State { let pc = registers.program_counter; let halt_final = registers.is_kernel && halt_offsets.contains(&pc); - if running && (self.at_halt() || self.at_end_segment(max_cpu_len_log)) { + if running && (self.at_halt() || self.at_end_segment(cycle_limit)) { running = false; final_registers = registers; diff --git a/evm_arithmetization/src/proof.rs b/evm_arithmetization/src/proof.rs index 25706b3df..f946b63cf 100644 --- a/evm_arithmetization/src/proof.rs +++ b/evm_arithmetization/src/proof.rs @@ -378,7 +378,19 @@ pub struct RegistersData { /// Gas used so far. pub gas_used: U256, } + +pub(crate) enum RegistersIdx { + ProgramCounter = 0, + IsKernel = 1, + StackLen = 2, + StackTop = 3, + Context = 4, + GasUsed = 5, +} + impl RegistersData { + pub(crate) const SIZE: usize = 6; + pub fn from_public_inputs(pis: &[F]) -> Self { assert!(pis.len() == RegistersDataTarget::SIZE); diff --git a/evm_arithmetization/tests/empty_txn_list.rs b/evm_arithmetization/tests/empty_txn_list.rs index 5f4cccfa4..b4a46c2e4 100644 --- a/evm_arithmetization/tests/empty_txn_list.rs +++ b/evm_arithmetization/tests/empty_txn_list.rs @@ -178,44 +178,43 @@ fn test_empty_txn_list() -> anyhow::Result<()> { ); // We can duplicate the proofs here because the state hasn't mutated. - let (segmented_agg_proof, segmented_agg_public_values) = all_circuits - .prove_segment_aggregation( - false, - &segment_proofs_data[0].proof_with_pis, - segment_proofs_data[0].public_values.clone(), - false, - segment_proofs_data[1].is_dummy, - &segment_proofs_data[1].proof_with_pis, - segment_proofs_data[1].public_values.clone(), - )?; - all_circuits.verify_segment_aggregation(&segmented_agg_proof)?; - - let (segmented_agg_proof, segmented_agg_public_values) = all_circuits - .prove_segment_aggregation( - true, - &segmented_agg_proof, - segmented_agg_public_values, - false, - segment_proofs_data[2].is_dummy, - &segment_proofs_data[2].proof_with_pis, - segment_proofs_data[2].public_values.clone(), - )?; - all_circuits.verify_segment_aggregation(&segmented_agg_proof)?; + let aggregation_output_data = all_circuits.prove_segment_aggregation( + false, + &segment_proofs_data[0], + false, + &segment_proofs_data[1], + )?; + all_circuits.verify_segment_aggregation(&aggregation_output_data.proof_with_pis)?; + + let aggregation_output_data = all_circuits.prove_segment_aggregation( + true, + &aggregation_output_data, + false, + &segment_proofs_data[2], + )?; + all_circuits.verify_segment_aggregation(&aggregation_output_data.proof_with_pis)?; // Test retrieved public values from the proof public inputs. let retrieved_public_values = PublicValues::from_public_inputs( - &segmented_agg_proof.public_inputs, - segmented_agg_public_values.mem_before.mem_cap.len(), + &aggregation_output_data.proof_with_pis.public_inputs, + aggregation_output_data + .public_values + .mem_before + .mem_cap + .len(), + ); + assert_eq!( + retrieved_public_values, + aggregation_output_data.public_values ); - assert_eq!(retrieved_public_values, segmented_agg_public_values); let (txn_proof, txn_public_values) = all_circuits.prove_transaction_aggregation( false, - &segmented_agg_proof, - segmented_agg_public_values.clone(), + &aggregation_output_data.proof_with_pis, + aggregation_output_data.public_values.clone(), false, - &segmented_agg_proof, - segmented_agg_public_values, + &aggregation_output_data.proof_with_pis, + aggregation_output_data.public_values, )?; all_circuits.verify_txn_aggregation(&txn_proof)?; diff --git a/evm_arithmetization/tests/log_opcode.rs b/evm_arithmetization/tests/log_opcode.rs index d428966c9..0008f462e 100644 --- a/evm_arithmetization/tests/log_opcode.rs +++ b/evm_arithmetization/tests/log_opcode.rs @@ -477,17 +477,14 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { assert_eq!(segment_proofs_data_first.len(), 2); // second one is a dummy segment - let (segment_agg_proof_first, updated_agg_public_values_first) = all_circuits - .prove_segment_aggregation( - false, - &segment_proofs_data_first[0].proof_with_pis, - segment_proofs_data_first[0].public_values.clone(), - false, - segment_proofs_data_first[1].is_dummy, - &segment_proofs_data_first[1].proof_with_pis, - segment_proofs_data_first[1].public_values.clone(), - )?; - all_circuits.verify_segment_aggregation(&segment_agg_proof_first)?; + let segment_agg_prover_output_data_first = all_circuits.prove_segment_aggregation( + false, + &segment_proofs_data_first[0], + false, + &segment_proofs_data_first[1], + )?; + all_circuits + .verify_segment_aggregation(&segment_agg_prover_output_data_first.proof_with_pis)?; // The gas used and transaction number are fed to the next transaction, so the // two proofs can be correctly aggregated. @@ -627,25 +624,22 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { all_circuits.verify_root(proof.clone())?; } - let (segment_agg_proof_second, updated_agg_public_values_second) = all_circuits - .prove_segment_aggregation( - false, - &segment_proofs_data_second[0].proof_with_pis, - segment_proofs_data_second[0].public_values.clone(), - false, - segment_proofs_data_second[1].is_dummy, - &segment_proofs_data_second[1].proof_with_pis, - segment_proofs_data_second[1].public_values.clone(), - )?; - all_circuits.verify_segment_aggregation(&segment_agg_proof_second)?; + let segment_agg_prover_output_data_second = all_circuits.prove_segment_aggregation( + false, + &segment_proofs_data_second[0], + false, + &segment_proofs_data_second[1], + )?; + all_circuits + .verify_segment_aggregation(&segment_agg_prover_output_data_second.proof_with_pis)?; let (txn_proof, txn_pv) = all_circuits.prove_transaction_aggregation( false, - &segment_agg_proof_first, - updated_agg_public_values_first, + &segment_agg_prover_output_data_first.proof_with_pis, + segment_agg_prover_output_data_first.public_values, false, - &segment_agg_proof_second, - updated_agg_public_values_second, + &segment_agg_prover_output_data_second.proof_with_pis, + segment_agg_prover_output_data_second.public_values, )?; let (first_block_proof, _block_public_values) = @@ -717,24 +711,21 @@ fn test_log_with_aggreg() -> anyhow::Result<()> { all_circuits.verify_root(proof.clone())?; } - let (segment_agg_proof, updated_agg_public_values) = all_circuits.prove_segment_aggregation( + let segment_agg_prover_output_data = all_circuits.prove_segment_aggregation( false, - &segment_proofs_data[0].proof_with_pis, - segment_proofs_data[0].public_values.clone(), + &segment_proofs_data[0], false, - segment_proofs_data[1].is_dummy, - &segment_proofs_data[1].proof_with_pis, - segment_proofs_data[1].public_values.clone(), + &segment_proofs_data[1], )?; - all_circuits.verify_segment_aggregation(&segment_agg_proof)?; + all_circuits.verify_segment_aggregation(&segment_agg_prover_output_data.proof_with_pis)?; let (second_txn_proof, second_txn_pvs) = all_circuits.prove_transaction_aggregation( false, - &segment_agg_proof, - updated_agg_public_values.clone(), + &segment_agg_prover_output_data.proof_with_pis, + segment_agg_prover_output_data.public_values.clone(), false, - &segment_agg_proof, - updated_agg_public_values, + &segment_agg_prover_output_data.proof_with_pis, + segment_agg_prover_output_data.public_values, )?; let (second_block_proof, _block_public_values) = all_circuits.prove_block( None, // We don't specify a previous proof, considering block 1 as the new checkpoint. diff --git a/proof_gen/Cargo.toml b/proof_gen/Cargo.toml index d8fe50890..044dd3e72 100644 --- a/proof_gen/Cargo.toml +++ b/proof_gen/Cargo.toml @@ -15,7 +15,7 @@ log = { workspace = true } paste = "1.0.14" plonky2 = { workspace = true } serde = { workspace = true } -hashbrown = { version = "0.14.0" } +hashbrown = { workspace = true } # Local dependencies evm_arithmetization = { version = "0.1.3", path = "../evm_arithmetization" } diff --git a/proof_gen/src/proof_gen.rs b/proof_gen/src/proof_gen.rs index 177f32233..e6ed784b0 100644 --- a/proof_gen/src/proof_gen.rs +++ b/proof_gen/src/proof_gen.rs @@ -3,7 +3,10 @@ use std::sync::{atomic::AtomicBool, Arc}; -use evm_arithmetization::{prover::GenerationSegmentData, AllStark, GenerationInputs, StarkConfig}; +use evm_arithmetization::{ + fixed_recursive_verifier::ProverOutputData, prover::GenerationSegmentData, AllStark, + GenerationInputs, StarkConfig, +}; use hashbrown::HashMap; use plonky2::{ gates::noop::NoopGate, @@ -86,19 +89,30 @@ pub fn generate_segment_agg_proof( "Cannot have a dummy segment with an aggregation." ); } - let (intern, p_vals) = p_state + + let lhs_prover_output_data = ProverOutputData { + is_dummy: false, + proof_with_pis: lhs_child.intern().clone(), + public_values: lhs_child.public_values(), + }; + let rhs_prover_output_data = ProverOutputData { + is_dummy: false, + proof_with_pis: rhs_child.intern().clone(), + public_values: rhs_child.public_values(), + }; + let agg_output_data = p_state .state .prove_segment_aggregation( lhs_child.is_agg(), - lhs_child.intern(), - lhs_child.public_values(), + &lhs_prover_output_data, rhs_child.is_agg(), - has_dummy, - rhs_child.intern(), - rhs_child.public_values(), + &rhs_prover_output_data, ) .map_err(|err| err.to_string())?; + let p_vals = agg_output_data.public_values; + let intern = agg_output_data.proof_with_pis; + Ok(GeneratedSegmentAggProof { p_vals, intern }) } From 0153a62b71cf484db86afb81b2c1991349473913 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Thu, 6 Jun 2024 17:35:03 +0800 Subject: [PATCH 26/31] Remove segments from AggregatableTxnProofs --- proof_gen/src/proof_types.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/proof_gen/src/proof_types.rs b/proof_gen/src/proof_types.rs index bdbc0eac5..94f5ff3be 100644 --- a/proof_gen/src/proof_types.rs +++ b/proof_gen/src/proof_types.rs @@ -68,9 +68,6 @@ pub enum SegmentAggregatableProof { /// away whether or not the proof was a txn or agg proof. #[derive(Clone, Debug, Deserialize, Serialize)] pub enum TxnAggregatableProof { - /// The underlying proof is a segment proof. It first needs to be aggregated - /// with a dummy proof. - Segment(GeneratedSegmentProof), /// The underlying proof is a transaction proof. Txn(GeneratedSegmentAggProof), /// The underlying proof is an aggregation proof. @@ -103,7 +100,6 @@ impl SegmentAggregatableProof { impl TxnAggregatableProof { pub(crate) fn public_values(&self) -> PublicValues { match self { - TxnAggregatableProof::Segment(info) => info.p_vals.clone(), TxnAggregatableProof::Txn(info) => info.p_vals.clone(), TxnAggregatableProof::Agg(info) => info.p_vals.clone(), } @@ -111,7 +107,6 @@ impl TxnAggregatableProof { pub(crate) fn is_agg(&self) -> bool { match self { - TxnAggregatableProof::Segment(_) => false, TxnAggregatableProof::Txn(_) => false, TxnAggregatableProof::Agg(_) => true, } @@ -119,7 +114,6 @@ impl TxnAggregatableProof { pub(crate) fn intern(&self) -> &PlonkyProofIntern { match self { - TxnAggregatableProof::Segment(info) => &info.intern, TxnAggregatableProof::Txn(info) => &info.intern, TxnAggregatableProof::Agg(info) => &info.intern, } @@ -154,7 +148,9 @@ impl From for TxnAggregatableProof { fn from(v: SegmentAggregatableProof) -> Self { match v { SegmentAggregatableProof::Agg(agg) => TxnAggregatableProof::Txn(agg), - SegmentAggregatableProof::Txn(seg) => TxnAggregatableProof::Segment(seg), + SegmentAggregatableProof::Txn(_) => { + panic!("Should be an aggregation by now. Missing segment?") + } } } } From 0f5c1852a6a2d6d9dc4d726240ecd10caabc668c Mon Sep 17 00:00:00 2001 From: hratoanina Date: Thu, 6 Jun 2024 14:48:23 -0400 Subject: [PATCH 27/31] Rename SegmentAggregatableProof variant --- proof_gen/src/proof_types.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/proof_gen/src/proof_types.rs b/proof_gen/src/proof_types.rs index 94f5ff3be..6183e5a82 100644 --- a/proof_gen/src/proof_types.rs +++ b/proof_gen/src/proof_types.rs @@ -58,7 +58,7 @@ pub struct GeneratedBlockProof { #[derive(Clone, Debug, Deserialize, Serialize)] pub enum SegmentAggregatableProof { /// The underlying proof is a segment proof. - Txn(GeneratedSegmentProof), + Seg(GeneratedSegmentProof), /// The underlying proof is an aggregation proof. Agg(GeneratedSegmentAggProof), } @@ -77,21 +77,21 @@ pub enum TxnAggregatableProof { impl SegmentAggregatableProof { pub(crate) fn public_values(&self) -> PublicValues { match self { - SegmentAggregatableProof::Txn(info) => info.p_vals.clone(), + SegmentAggregatableProof::Seg(info) => info.p_vals.clone(), SegmentAggregatableProof::Agg(info) => info.p_vals.clone(), } } pub(crate) const fn is_agg(&self) -> bool { match self { - SegmentAggregatableProof::Txn(_) => false, + SegmentAggregatableProof::Seg(_) => false, SegmentAggregatableProof::Agg(_) => true, } } pub(crate) const fn intern(&self) -> &PlonkyProofIntern { match self { - SegmentAggregatableProof::Txn(info) => &info.intern, + SegmentAggregatableProof::Seg(info) => &info.intern, SegmentAggregatableProof::Agg(info) => &info.intern, } } @@ -122,7 +122,7 @@ impl TxnAggregatableProof { impl From for SegmentAggregatableProof { fn from(v: GeneratedSegmentProof) -> Self { - Self::Txn(v) + Self::Seg(v) } } @@ -148,7 +148,7 @@ impl From for TxnAggregatableProof { fn from(v: SegmentAggregatableProof) -> Self { match v { SegmentAggregatableProof::Agg(agg) => TxnAggregatableProof::Txn(agg), - SegmentAggregatableProof::Txn(_) => { + SegmentAggregatableProof::Seg(_) => { panic!("Should be an aggregation by now. Missing segment?") } } From cfd1fcf75884aded7fc524a7d2d521fac535759f Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Fri, 7 Jun 2024 09:56:50 +0800 Subject: [PATCH 28/31] Fix generate_segment_agg_proof --- proof_gen/src/proof_gen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proof_gen/src/proof_gen.rs b/proof_gen/src/proof_gen.rs index e6ed784b0..cd6d48a52 100644 --- a/proof_gen/src/proof_gen.rs +++ b/proof_gen/src/proof_gen.rs @@ -96,7 +96,7 @@ pub fn generate_segment_agg_proof( public_values: lhs_child.public_values(), }; let rhs_prover_output_data = ProverOutputData { - is_dummy: false, + is_dummy: has_dummy, proof_with_pis: rhs_child.intern().clone(), public_values: rhs_child.public_values(), }; From 87fa930a8b77f3692d235a35832c3e89295f5177 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Tue, 11 Jun 2024 15:06:30 +0800 Subject: [PATCH 29/31] Apply comments --- evm_arithmetization/src/fixed_recursive_verifier.rs | 1 - evm_arithmetization/src/prover.rs | 13 ++++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 28ae99c19..0bca46677 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -1567,7 +1567,6 @@ where inputs: generation_inputs.clone(), partial_next_data: None, max_cpu_len_log: Some(max_cpu_len_log), - nb_segments: 0, }; let mut proofs = vec![]; diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 4c0dd030d..3cf248cb6 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -527,7 +527,6 @@ pub struct SegmentDataIterator { pub partial_next_data: Option, pub inputs: GenerationInputs, pub max_cpu_len_log: Option, - pub nb_segments: usize, } type F = GoldilocksField; @@ -542,11 +541,7 @@ impl Iterator for SegmentDataIterator { ); if cur_and_next_data.is_some() { - let (data, next_data) = cur_and_next_data.expect( - "Data cannot be -`None`", - ); - self.nb_segments += 1; + let (data, next_data) = cur_and_next_data.expect("Data cannot be `None`"); self.partial_next_data = next_data; Some((self.inputs.clone(), data)) } else { @@ -588,9 +583,9 @@ pub(crate) fn generate_next_segment( // Run the interpreter to get `registers_after` and the partial data for the // next segment. - let run_result = set_registers_and_run(segment_data.registers_after, &mut interpreter); - - if let Ok((updated_registers, mem_after)) = run_result { + if let Ok((updated_registers, mem_after)) = + set_registers_and_run(segment_data.registers_after, &mut interpreter) + { // Set `registers_after` correctly and push the data. let before_registers = segment_data.registers_after; From 1380841267bdd0085531eb4bbd1d82b2dc291c37 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Thu, 13 Jun 2024 14:31:07 +0800 Subject: [PATCH 30/31] Use reference for GenerationInputs in SegmentDataIterator --- evm_arithmetization/src/fixed_recursive_verifier.rs | 2 +- evm_arithmetization/src/prover.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/evm_arithmetization/src/fixed_recursive_verifier.rs b/evm_arithmetization/src/fixed_recursive_verifier.rs index 0bca46677..59035b909 100644 --- a/evm_arithmetization/src/fixed_recursive_verifier.rs +++ b/evm_arithmetization/src/fixed_recursive_verifier.rs @@ -1564,7 +1564,7 @@ where abort_signal: Option>, ) -> anyhow::Result>> { let mut it_segment_data = SegmentDataIterator { - inputs: generation_inputs.clone(), + inputs: &generation_inputs, partial_next_data: None, max_cpu_len_log: Some(max_cpu_len_log), }; diff --git a/evm_arithmetization/src/prover.rs b/evm_arithmetization/src/prover.rs index 3cf248cb6..a660d88bf 100644 --- a/evm_arithmetization/src/prover.rs +++ b/evm_arithmetization/src/prover.rs @@ -523,20 +523,20 @@ fn build_segment_data( } } -pub struct SegmentDataIterator { +pub struct SegmentDataIterator<'a> { pub partial_next_data: Option, - pub inputs: GenerationInputs, + pub inputs: &'a GenerationInputs, pub max_cpu_len_log: Option, } type F = GoldilocksField; -impl Iterator for SegmentDataIterator { +impl<'a> Iterator for SegmentDataIterator<'a> { type Item = (GenerationInputs, GenerationSegmentData); fn next(&mut self) -> Option { let cur_and_next_data = generate_next_segment::( self.max_cpu_len_log, - &self.inputs, + self.inputs, self.partial_next_data.clone(), ); From b9c1ce723b647873c6a009e88821118b3447a6d5 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Fri, 14 Jun 2024 14:25:36 +0800 Subject: [PATCH 31/31] Reintroduce changes to TxnAggregatableProof for zero-bin compatibility --- proof_gen/src/proof_types.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/proof_gen/src/proof_types.rs b/proof_gen/src/proof_types.rs index 6183e5a82..fea8f845f 100644 --- a/proof_gen/src/proof_types.rs +++ b/proof_gen/src/proof_types.rs @@ -68,6 +68,9 @@ pub enum SegmentAggregatableProof { /// away whether or not the proof was a txn or agg proof. #[derive(Clone, Debug, Deserialize, Serialize)] pub enum TxnAggregatableProof { + /// The underlying proof is a segment proof. It first needs to be aggregated + /// with another segment proof, or a dummy one. + Segment(GeneratedSegmentProof), /// The underlying proof is a transaction proof. Txn(GeneratedSegmentAggProof), /// The underlying proof is an aggregation proof. @@ -100,6 +103,7 @@ impl SegmentAggregatableProof { impl TxnAggregatableProof { pub(crate) fn public_values(&self) -> PublicValues { match self { + TxnAggregatableProof::Segment(info) => info.p_vals.clone(), TxnAggregatableProof::Txn(info) => info.p_vals.clone(), TxnAggregatableProof::Agg(info) => info.p_vals.clone(), } @@ -107,6 +111,7 @@ impl TxnAggregatableProof { pub(crate) fn is_agg(&self) -> bool { match self { + TxnAggregatableProof::Segment(_) => false, TxnAggregatableProof::Txn(_) => false, TxnAggregatableProof::Agg(_) => true, } @@ -114,6 +119,7 @@ impl TxnAggregatableProof { pub(crate) fn intern(&self) -> &PlonkyProofIntern { match self { + TxnAggregatableProof::Segment(info) => &info.intern, TxnAggregatableProof::Txn(info) => &info.intern, TxnAggregatableProof::Agg(info) => &info.intern, } @@ -148,9 +154,7 @@ impl From for TxnAggregatableProof { fn from(v: SegmentAggregatableProof) -> Self { match v { SegmentAggregatableProof::Agg(agg) => TxnAggregatableProof::Txn(agg), - SegmentAggregatableProof::Seg(_) => { - panic!("Should be an aggregation by now. Missing segment?") - } + SegmentAggregatableProof::Seg(seg) => TxnAggregatableProof::Segment(seg), } } }