From ea4c95aff2903750815eb0d48f04bef18a08d122 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 24 Dec 2024 16:55:50 +0000 Subject: [PATCH 1/3] change root rollup to use ROOT_ROLLUP proof type --- .../rollup-lib/src/abis/previous_rollup_block_data.nr | 9 ++++----- .../src/block_merge/block_merge_rollup_inputs.nr | 9 ++++++--- .../crates/rollup-lib/src/root/root_rollup_inputs.nr | 9 ++++++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr index 3a81f8e3923..0f63dffab72 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_block_data.nr @@ -1,10 +1,9 @@ use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs; use dep::types::{ - constants::{PROOF_TYPE_ROLLUP_HONK, VK_TREE_HEIGHT}, + constants::VK_TREE_HEIGHT, merkle_tree::{membership::assert_check_membership, MembershipWitness}, proof::{ rollup_recursive_proof::NestedRecursiveProof, - traits::Verifiable, verification_key::{RollupHonkVerificationKey, VerificationKey}, }, traits::Empty, @@ -18,8 +17,8 @@ pub struct PreviousRollupBlockData { pub vk_witness: MembershipWitness, } -impl Verifiable for PreviousRollupBlockData { - fn verify(self) { +impl PreviousRollupBlockData { + fn verify(self, proof_type_id: u32) { let inputs = BlockRootOrBlockMergePublicInputs::serialize( self.block_root_or_block_merge_public_inputs, ); @@ -28,7 +27,7 @@ impl Verifiable for PreviousRollupBlockData { self.proof.fields, inputs, self.vk.hash, - PROOF_TYPE_ROLLUP_HONK, + proof_type_id, ); } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr index d753043a639..cac5ba693bd 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_merge/block_merge_rollup_inputs.nr @@ -1,7 +1,10 @@ use crate::abis::block_root_or_block_merge_public_inputs::BlockRootOrBlockMergePublicInputs; use crate::abis::previous_rollup_block_data::PreviousRollupBlockData; use crate::components; -use dep::types::{constants::{BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_INDEX}, traits::Empty}; +use dep::types::{ + constants::{BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_INDEX, PROOF_TYPE_ROLLUP_HONK}, + traits::Empty, +}; // TODO(#7346): Currently unused! Will be used when batch rollup circuits are integrated. global ALLOWED_PREVIOUS_CIRCUITS: [u32; 2] = [BLOCK_ROOT_ROLLUP_INDEX, BLOCK_MERGE_ROLLUP_INDEX]; @@ -21,10 +24,10 @@ impl BlockMergeRollupInputs { // we don't have a set of permitted kernel vks yet. // Verify the previous rollup proofs if !dep::std::runtime::is_unconstrained() { - self.previous_rollup_data[0].verify(); + self.previous_rollup_data[0].verify(PROOF_TYPE_ROLLUP_HONK); self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); - self.previous_rollup_data[1].verify(); + self.previous_rollup_data[1].verify(PROOF_TYPE_ROLLUP_HONK); self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index c94ece862f3..4ae66da587a 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -3,7 +3,10 @@ use crate::{ root::root_rollup_public_inputs::RootRollupPublicInputs, }; use types::{ - constants::{BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX, BLOCK_ROOT_ROLLUP_INDEX}, + constants::{ + BLOCK_MERGE_ROLLUP_INDEX, BLOCK_ROOT_ROLLUP_EMPTY_INDEX, BLOCK_ROOT_ROLLUP_INDEX, + PROOF_TYPE_ROLLUP_HONK, PROOF_TYPE_ROOT_ROLLUP_HONK, + }, traits::Empty, }; // TODO(#7346): Currently unused! Will be used when batch rollup circuits are integrated. @@ -28,10 +31,10 @@ impl RootRollupInputs { pub fn root_rollup_circuit(self) -> RootRollupPublicInputs { // Verify the previous rollup proofs if !dep::std::runtime::is_unconstrained() { - self.previous_rollup_data[0].verify(); + self.previous_rollup_data[0].verify(PROOF_TYPE_ROLLUP_HONK); self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); - self.previous_rollup_data[1].verify(); + self.previous_rollup_data[1].verify(PROOF_TYPE_ROOT_ROLLUP_HONK); self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); } From 9720b9243d64ba80d96be7890d5eed0d774c2de7 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 24 Dec 2024 17:19:03 +0000 Subject: [PATCH 2/3] use full recursive verifier in root rollup --- .../dsl/acir_format/acir_format.cpp | 31 +++++++++++++++---- .../acir_format/acir_to_constraint_buf.cpp | 4 +-- .../acir_format/honk_recursion_constraint.cpp | 2 +- .../dsl/acir_format/recursion_constraint.hpp | 2 +- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index fbbd3f0a58a..66a17d0b68e 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -3,14 +3,17 @@ #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp" #include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/stdlib/eccvm_verifier/verifier_commitment_key.hpp" #include "barretenberg/stdlib/plonk_recursion/aggregation_state/aggregation_state.hpp" #include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" #include "barretenberg/stdlib/primitives/field/field_conversion.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include "barretenberg/transcript/transcript.hpp" #include "proof_surgeon.hpp" #include #include +#include namespace acir_format { @@ -270,9 +273,8 @@ void build_constraints(Builder& builder, AcirProgram& program, const ProgramMeta // final recursion output. builder.add_pairing_point_accumulator(current_aggregation_object); } - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1183): This assertion should be true, except for - // the root rollup as of now since the root rollup will not output a ipa proof. - // ASSERT((metadata.honk_recursion == 2) == (output.ipa_proof.size() > 0)); + // If we are proving with UltraRollupFlavor, the IPA proof should have nonzero size. + ASSERT((metadata.honk_recursion == 2) == (output.ipa_proof.size() > 0)); if (metadata.honk_recursion == 2) { builder.add_ipa_claim(output.ipa_claim.get_witness_indices()); builder.ipa_proof = output.ipa_proof; @@ -379,13 +381,17 @@ HonkRecursionConstraintsOutput process_honk_recursion_constraints( size_t idx = 0; std::vector>> nested_ipa_claims; std::vector> nested_ipa_proofs; + bool is_root_rollup = false; for (auto& constraint : constraint_system.honk_recursion_constraints) { if (constraint.proof_type == HONK) { auto [next_aggregation_object, _ipa_claim, _ipa_proof] = create_honk_recursion_constraints>( builder, constraint, current_aggregation_object, has_valid_witness_assignments); current_aggregation_object = next_aggregation_object; - } else if (constraint.proof_type == ROLLUP_HONK || constraint.proof_type == ROLLUP_ROOT_HONK) { + } else if (constraint.proof_type == ROLLUP_HONK || constraint.proof_type == ROOT_ROLLUP_HONK) { + if (constraint.proof_type == ROOT_ROLLUP_HONK) { + is_root_rollup = true; + } auto [next_aggregation_object, ipa_claim, ipa_proof] = create_honk_recursion_constraints>( builder, constraint, current_aggregation_object, has_valid_witness_assignments); @@ -400,6 +406,7 @@ HonkRecursionConstraintsOutput process_honk_recursion_constraints( gate_counter.track_diff(constraint_system.gates_per_opcode, constraint_system.original_opcode_indices.honk_recursion_constraints.at(idx++)); } + ASSERT(!(is_root_rollup && nested_ipa_claims.size() != 2) && "Root rollup must accumulate two IPA proofs."); // Accumulate the claims if (nested_ipa_claims.size() == 2) { auto commitment_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); @@ -409,8 +416,20 @@ HonkRecursionConstraintsOutput process_honk_recursion_constraints( auto ipa_transcript_2 = std::make_shared(nested_ipa_proofs[1]); auto [ipa_claim, ipa_proof] = IPA>::accumulate( commitment_key, ipa_transcript_1, nested_ipa_claims[0], ipa_transcript_2, nested_ipa_claims[1]); - output.ipa_claim = ipa_claim; - output.ipa_proof = ipa_proof; + if (is_root_rollup) { + auto verifier_commitment_key = std::make_shared>>( + &builder, + 1 << CONST_ECCVM_LOG_N, + std::make_shared>(1 << CONST_ECCVM_LOG_N)); + // do full IPA verification + auto accumulated_ipa_transcript = + std::make_shared(convert_native_proof_to_stdlib(&builder, ipa_proof)); + IPA>::full_verify_recursive( + verifier_commitment_key, ipa_claim, accumulated_ipa_transcript); + } else { + output.ipa_claim = ipa_claim; + output.ipa_proof = ipa_proof; + } } else if (nested_ipa_claims.size() == 1) { output.ipa_claim = nested_ipa_claims[0]; // This conversion looks suspicious but there's no need to make this an output of the circuit since its a proof diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index f22bf954b85..3307a21184c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -635,7 +635,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, // be the only means for setting the proof type. use of honk_recursion flag in this context can go // away once all noir programs (e.g. protocol circuits) are updated to use the new pattern. if (proof_type_in != HONK && proof_type_in != AVM && proof_type_in != ROLLUP_HONK && - proof_type_in != ROLLUP_ROOT_HONK) { + proof_type_in != ROOT_ROLLUP_HONK) { if (honk_recursion == 1) { proof_type_in = HONK; } else if (honk_recursion == 2) { @@ -659,7 +659,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, break; case HONK: case ROLLUP_HONK: - case ROLLUP_ROOT_HONK: + case ROOT_ROLLUP_HONK: af.honk_recursion_constraints.push_back(c); af.original_opcode_indices.honk_recursion_constraints.push_back(opcode_index); break; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp index 38849d2554b..e44428be1a4 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp @@ -229,7 +229,7 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; ASSERT(input.proof_type == HONK || HasIPAAccumulator); - ASSERT((input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK) == HasIPAAccumulator); + ASSERT((input.proof_type == ROLLUP_HONK || input.proof_type == ROOT_ROLLUP_HONK) == HasIPAAccumulator); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index c7ae3ab1d07..01fdeccd75c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -10,7 +10,7 @@ namespace acir_format { // ACIR // Keep this enum values in sync with their noir counterpart constants defined in // noir-protocol-circuits/crates/types/src/constants.nr -enum PROOF_TYPE { PLONK, HONK, OINK, PG, AVM, ROLLUP_HONK, ROLLUP_ROOT_HONK }; +enum PROOF_TYPE { PLONK, HONK, OINK, PG, AVM, ROLLUP_HONK, ROOT_ROLLUP_HONK }; using namespace bb::plonk; using Builder = bb::UltraCircuitBuilder; From c710fc1c924c5d937bcf9f9e652e90f059afcddc Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 24 Dec 2024 19:03:25 +0000 Subject: [PATCH 3/3] added comments --- .../cpp/src/barretenberg/dsl/acir_format/acir_format.cpp | 1 + .../crates/rollup-lib/src/root/root_rollup_inputs.nr | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 66a17d0b68e..077ffd9de8c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -416,6 +416,7 @@ HonkRecursionConstraintsOutput process_honk_recursion_constraints( auto ipa_transcript_2 = std::make_shared(nested_ipa_proofs[1]); auto [ipa_claim, ipa_proof] = IPA>::accumulate( commitment_key, ipa_transcript_1, nested_ipa_claims[0], ipa_transcript_2, nested_ipa_claims[1]); + // If this is the root rollup, do full IPA verification if (is_root_rollup) { auto verifier_commitment_key = std::make_shared>>( &builder, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 4ae66da587a..7ede3a240b5 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -31,10 +31,10 @@ impl RootRollupInputs { pub fn root_rollup_circuit(self) -> RootRollupPublicInputs { // Verify the previous rollup proofs if !dep::std::runtime::is_unconstrained() { - self.previous_rollup_data[0].verify(PROOF_TYPE_ROLLUP_HONK); + self.previous_rollup_data[0].verify(PROOF_TYPE_ROOT_ROLLUP_HONK); // root rollup honk proof type so we do full IPA recursive verifier self.previous_rollup_data[0].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); - self.previous_rollup_data[1].verify(PROOF_TYPE_ROOT_ROLLUP_HONK); + self.previous_rollup_data[1].verify(PROOF_TYPE_ROOT_ROLLUP_HONK); // root rollup honk proof type so we do full IPA recursive verifier self.previous_rollup_data[1].validate_in_vk_tree(ALLOWED_PREVIOUS_CIRCUITS); }