From 624642c915a208e8d50e71d0fb0468cc7005ea21 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Wed, 27 Nov 2024 21:02:54 +0000 Subject: [PATCH 1/8] modify honk recursion constraint to handle ipa claim --- .../dsl/acir_format/acir_format.cpp | 15 +++- .../acir_format/acir_to_constraint_buf.cpp | 5 +- .../acir_format/honk_recursion_constraint.cpp | 69 +++++++++++++--- .../acir_format/honk_recursion_constraint.hpp | 15 ++-- .../honk_recursion_constraint.test.cpp | 82 ++++++++++--------- .../dsl/acir_format/recursion_constraint.hpp | 2 +- 6 files changed, 128 insertions(+), 60 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 dd48e644a22..d47bc3823cb 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -351,8 +351,19 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( // Add recursion constraints size_t idx = 0; for (auto& constraint : constraint_system.honk_recursion_constraints) { - current_aggregation_object = create_honk_recursion_constraints( - builder, constraint, current_aggregation_object, has_valid_witness_assignments); + if (constraint.proof_type == HONK) { + auto [next_aggregation_object, ipa_claim_indices] = + 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) { + auto [next_aggregation_object, ipa_claim_indices] = + create_honk_recursion_constraints>( + builder, constraint, current_aggregation_object, has_valid_witness_assignments); + current_aggregation_object = next_aggregation_object; + } else { + throw_or_abort("Invalid Honk proof type"); + } gate_counter.track_diff(constraint_system.gates_per_opcode, constraint_system.original_opcode_indices.honk_recursion_constraints.at(idx++)); 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 cae59733e3b..251ca8236e7 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 @@ -634,7 +634,8 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1074): Eventually arg.proof_type will // 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 (honk_recursion && proof_type_in != HONK && proof_type_in != AVM) { + if (honk_recursion && proof_type_in != HONK && proof_type_in != AVM && proof_type_in != ROLLUP_HONK && + proof_type_in != ROLLUP_ROOT_HONK) { proof_type_in = HONK; } @@ -653,6 +654,8 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, af.original_opcode_indices.recursion_constraints.push_back(opcode_index); break; case HONK: + case ROLLUP_HONK: + case ROLLUP_ROOT_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 45da4234f6f..7158694b8e1 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 @@ -31,17 +31,16 @@ namespace { * @param key_fields * @param proof_fields */ +template void create_dummy_vkey_and_proof(Builder& builder, size_t proof_size, size_t public_inputs_size, const std::vector& key_fields, const std::vector& proof_fields) { - using Flavor = UltraFlavor; - // Set vkey->circuit_size correctly based on the proof size - size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); - size_t num_frs_fr = bb::field_conversion::calc_num_bn254_frs(); + size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); + size_t num_frs_fr = bb::field_conversion::calc_num_bn254_frs(); assert((proof_size - bb::HONK_PROOF_PUBLIC_INPUT_OFFSET - Flavor::NUM_WITNESS_ENTITIES * num_frs_comm - Flavor::NUM_ALL_ENTITIES * num_frs_fr - num_frs_comm) % (num_frs_comm + num_frs_fr * (Flavor::BATCHED_RELATION_PARTIAL_LENGTH + 1)) == @@ -61,13 +60,26 @@ void create_dummy_vkey_and_proof(Builder& builder, builder.assert_equal(builder.add_variable(1), key_fields[3].witness_index); uint32_t offset = 4; size_t num_inner_public_inputs = public_inputs_size - bb::PAIRING_POINT_ACCUMULATOR_SIZE; + if constexpr (HasIPAAccumulator) { + num_inner_public_inputs -= bb::IPA_CLAIM_SIZE; + } - // We are making the assumption that the aggregation object are behind all the inner public inputs + // We are making the assumption that the pairing point object is behind all the inner public inputs for (size_t i = 0; i < bb::PAIRING_POINT_ACCUMULATOR_SIZE; i++) { builder.assert_equal(builder.add_variable(num_inner_public_inputs + i), key_fields[offset].witness_index); offset++; } + if constexpr (HasIPAAccumulator) { + // Key field is the whether the proof contains an aggregation object. + builder.assert_equal(builder.add_variable(1), key_fields[offset++].witness_index); + // We are making the assumption that the IPA claim is behind the inner public inputs and pairing point object + for (size_t i = 0; i < bb::IPA_CLAIM_SIZE; i++) { + builder.assert_equal(builder.add_variable(num_inner_public_inputs + i), key_fields[offset].witness_index); + offset++; + } + } + for (size_t i = 0; i < Flavor::NUM_PRECOMPUTED_ENTITIES; ++i) { auto comm = curve::BN254::AffineElement::one() * fr::random_element(); auto frs = field_conversion::convert_to_bn254_frs(comm); @@ -96,6 +108,14 @@ void create_dummy_vkey_and_proof(Builder& builder, offset++; } + if constexpr (HasIPAAccumulator) { + IPAClaimIndices ipa_claim; // WORKTODO: initialize this to something? + for (auto idx : ipa_claim) { + builder.assert_equal(idx, proof_fields[offset].witness_index); + offset++; + } + } + // first 8 witness commitments for (size_t i = 0; i < Flavor::NUM_WITNESS_ENTITIES; i++) { auto comm = curve::BN254::AffineElement::one() * fr::random_element(); @@ -107,7 +127,8 @@ void create_dummy_vkey_and_proof(Builder& builder, offset += 4; } - // now the univariates, which can just be 0s (8*CONST_PROOF_SIZE_LOG_N Frs, where 8 is the maximum relation degree) + // now the univariates, which can just be 0s (8*CONST_PROOF_SIZE_LOG_N Frs, where 8 is the maximum relation + // degree) for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N * Flavor::BATCHED_RELATION_PARTIAL_LENGTH; i++) { builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); offset++; @@ -162,17 +183,18 @@ void create_dummy_vkey_and_proof(Builder& builder, * We would either need a separate ACIR opcode where inner_proof_contains_pairing_point_accumulator = true, * or we need non-witness data to be provided as metadata in the ACIR opcode */ -PairingPointAccumulatorIndices create_honk_recursion_constraints( + +template +HonkRecursionConstraintOutput create_honk_recursion_constraints( Builder& builder, const RecursionConstraint& input, PairingPointAccumulatorIndices input_aggregation_object_indices, bool has_valid_witness_assignments) { - using Flavor = UltraRecursiveFlavor_; using RecursiveVerificationKey = Flavor::VerificationKey; using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; - ASSERT(input.proof_type == HONK); + ASSERT(input.proof_type == HONK || input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. @@ -200,8 +222,14 @@ PairingPointAccumulatorIndices create_honk_recursion_constraints( // In the constraint, the agg object public inputs are still contained in the proof. To get the 'raw' size of // the proof and public_inputs we subtract and add the corresponding amount from the respective sizes. size_t size_of_proof_with_no_pub_inputs = input.proof.size() - bb::PAIRING_POINT_ACCUMULATOR_SIZE; + if constexpr (HasIPAAccumulator) { + size_of_proof_with_no_pub_inputs -= bb::IPA_CLAIM_SIZE; + } size_t total_num_public_inputs = input.public_inputs.size() + bb::PAIRING_POINT_ACCUMULATOR_SIZE; - create_dummy_vkey_and_proof( + if constexpr (HasIPAAccumulator) { + total_num_public_inputs += bb::IPA_CLAIM_SIZE; + } + create_dummy_vkey_and_proof( builder, size_of_proof_with_no_pub_inputs, total_num_public_inputs, key_fields, proof_fields); } @@ -210,11 +238,28 @@ PairingPointAccumulatorIndices create_honk_recursion_constraints( RecursiveVerifier verifier(&builder, vkey); aggregation_state_ct input_agg_obj = bb::stdlib::recursion::convert_witness_indices_to_agg_obj( builder, input_aggregation_object_indices); - UltraRecursiveVerifierOutput output = verifier.verify_proof(proof_fields, input_agg_obj); + UltraRecursiveVerifierOutput verifier_output = verifier.verify_proof(proof_fields, input_agg_obj); // TODO(https://github.com/AztecProtocol/barretenberg/issues/996): investigate whether assert_equal on public inputs // is important, like what the plonk recursion constraint does. - return output.agg_obj.get_witness_indices(); + HonkRecursionConstraintOutput output; + output.agg_obj_indices = verifier_output.agg_obj.get_witness_indices(); + if constexpr (HasIPAAccumulator) { + output.ipa_claim_indices = verifier_output.ipa_opening_claim.get_witness_indices(); + } + return output; } +template HonkRecursionConstraintOutput create_honk_recursion_constraints>( + Builder& builder, + const RecursionConstraint& input, + PairingPointAccumulatorIndices input_aggregation_object_indices, + bool has_valid_witness_assignments); + +template HonkRecursionConstraintOutput create_honk_recursion_constraints>( + Builder& builder, + const RecursionConstraint& input, + PairingPointAccumulatorIndices input_aggregation_object_indices, + bool has_valid_witness_assignments); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp index 71a4a26e9cb..ec936a91baf 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp @@ -8,10 +8,15 @@ using Builder = bb::UltraCircuitBuilder; using namespace bb; -PairingPointAccumulatorIndices create_honk_recursion_constraints( - Builder& builder, - const RecursionConstraint& input, - PairingPointAccumulatorIndices input_aggregation_object, - bool has_valid_witness_assignments = false); +struct HonkRecursionConstraintOutput { + PairingPointAccumulatorIndices agg_obj_indices; + IPAClaimIndices ipa_claim_indices; +}; + +template +HonkRecursionConstraintOutput create_honk_recursion_constraints(Builder& builder, + const RecursionConstraint& input, + PairingPointAccumulatorIndices input_aggregation_object, + bool has_valid_witness_assignments = false); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index 50b92017818..a8feaa93b24 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -12,13 +12,13 @@ using namespace acir_format; using namespace bb; -class AcirHonkRecursionConstraint : public ::testing::Test { +template class AcirHonkRecursionConstraint : public ::testing::Test { public: - using DeciderProvingKey = DeciderProvingKey_; - using Prover = bb::UltraProver; - using VerificationKey = UltraFlavor::VerificationKey; - using Verifier = bb::UltraVerifier; + using DeciderProvingKey = DeciderProvingKey_; + using Prover = bb::UltraProver_; + using VerificationKey = typename Flavor::VerificationKey; + using Verifier = bb::UltraVerifier_; Builder create_inner_circuit() { @@ -186,45 +186,49 @@ class AcirHonkRecursionConstraint : public ::testing::Test { static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } }; -TEST_F(AcirHonkRecursionConstraint, TestBasicSingleHonkRecursionConstraint) +using Flavors = testing::Types; + +TYPED_TEST_SUITE(AcirHonkRecursionConstraint, Flavors); + +TYPED_TEST(AcirHonkRecursionConstraint, TestBasicSingleHonkRecursionConstraint) { std::vector layer_1_circuits; - layer_1_circuits.push_back(create_inner_circuit()); + layer_1_circuits.push_back(TestFixture::create_inner_circuit()); - auto layer_2_circuit = create_outer_circuit(layer_1_circuits); + auto layer_2_circuit = TestFixture::create_outer_circuit(layer_1_circuits); info("circuit gates = ", layer_2_circuit.get_estimated_num_finalized_gates()); - auto proving_key = std::make_shared(layer_2_circuit); - Prover prover(proving_key); + auto proving_key = std::make_shared(layer_2_circuit); + typename TestFixture::Prover prover(proving_key); info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); - auto verification_key = std::make_shared(proving_key->proving_key); - Verifier verifier(verification_key); + auto verification_key = std::make_shared(proving_key->proving_key); + typename TestFixture::Verifier verifier(verification_key); EXPECT_EQ(verifier.verify_proof(proof), true); } -TEST_F(AcirHonkRecursionConstraint, TestBasicDoubleHonkRecursionConstraints) +TYPED_TEST(AcirHonkRecursionConstraint, TestBasicDoubleHonkRecursionConstraints) { std::vector layer_1_circuits; - layer_1_circuits.push_back(create_inner_circuit()); + layer_1_circuits.push_back(TestFixture::create_inner_circuit()); - layer_1_circuits.push_back(create_inner_circuit()); + layer_1_circuits.push_back(TestFixture::create_inner_circuit()); - auto layer_2_circuit = create_outer_circuit(layer_1_circuits); + auto layer_2_circuit = TestFixture::create_outer_circuit(layer_1_circuits); info("circuit gates = ", layer_2_circuit.get_estimated_num_finalized_gates()); - auto proving_key = std::make_shared(layer_2_circuit); - Prover prover(proving_key); + auto proving_key = std::make_shared(layer_2_circuit); + typename TestFixture::Prover prover(proving_key); info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); - auto verification_key = std::make_shared(proving_key->proving_key); - Verifier verifier(verification_key); + auto verification_key = std::make_shared(proving_key->proving_key); + typename TestFixture::Verifier verifier(verification_key); EXPECT_EQ(verifier.verify_proof(proof), true); } -TEST_F(AcirHonkRecursionConstraint, TestOneOuterRecursiveCircuit) +TYPED_TEST(AcirHonkRecursionConstraint, TestOneOuterRecursiveCircuit) { /** * We want to test the following: @@ -259,55 +263,55 @@ TEST_F(AcirHonkRecursionConstraint, TestOneOuterRecursiveCircuit) * Final aggregation object contains aggregated proofs for 2 instances of A and 1 instance of B */ std::vector layer_1_circuits; - layer_1_circuits.push_back(create_inner_circuit()); + layer_1_circuits.push_back(TestFixture::create_inner_circuit()); info("created first inner circuit"); std::vector layer_2_circuits; - layer_2_circuits.push_back(create_inner_circuit()); + layer_2_circuits.push_back(TestFixture::create_inner_circuit()); info("created second inner circuit"); - layer_2_circuits.push_back(create_outer_circuit(layer_1_circuits)); + layer_2_circuits.push_back(TestFixture::create_outer_circuit(layer_1_circuits)); info("created first outer circuit"); - auto layer_3_circuit = create_outer_circuit(layer_2_circuits); + auto layer_3_circuit = TestFixture::create_outer_circuit(layer_2_circuits); info("created second outer circuit"); info("number of gates in layer 3 = ", layer_3_circuit.get_estimated_num_finalized_gates()); - auto proving_key = std::make_shared(layer_3_circuit); - Prover prover(proving_key); + auto proving_key = std::make_shared(layer_3_circuit); + typename TestFixture::Prover prover(proving_key); info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); - auto verification_key = std::make_shared(proving_key->proving_key); - Verifier verifier(verification_key); + auto verification_key = std::make_shared(proving_key->proving_key); + typename TestFixture::Verifier verifier(verification_key); EXPECT_EQ(verifier.verify_proof(proof), true); } -TEST_F(AcirHonkRecursionConstraint, TestFullRecursiveComposition) +TYPED_TEST(AcirHonkRecursionConstraint, TestFullRecursiveComposition) { std::vector layer_b_1_circuits; - layer_b_1_circuits.push_back(create_inner_circuit()); + layer_b_1_circuits.push_back(TestFixture::create_inner_circuit()); info("created first inner circuit"); std::vector layer_b_2_circuits; - layer_b_2_circuits.push_back(create_inner_circuit()); + layer_b_2_circuits.push_back(TestFixture::create_inner_circuit()); info("created second inner circuit"); std::vector layer_2_circuits; - layer_2_circuits.push_back(create_outer_circuit(layer_b_1_circuits)); + layer_2_circuits.push_back(TestFixture::create_outer_circuit(layer_b_1_circuits)); info("created first outer circuit"); - layer_2_circuits.push_back(create_outer_circuit(layer_b_2_circuits)); + layer_2_circuits.push_back(TestFixture::create_outer_circuit(layer_b_2_circuits)); info("created second outer circuit"); - auto layer_3_circuit = create_outer_circuit(layer_2_circuits); + auto layer_3_circuit = TestFixture::create_outer_circuit(layer_2_circuits); info("created third outer circuit"); info("number of gates in layer 3 circuit = ", layer_3_circuit.get_estimated_num_finalized_gates()); - auto proving_key = std::make_shared(layer_3_circuit); - Prover prover(proving_key); + auto proving_key = std::make_shared(layer_3_circuit); + typename TestFixture::Prover prover(proving_key); info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); - auto verification_key = std::make_shared(proving_key->proving_key); - Verifier verifier(verification_key); + auto verification_key = std::make_shared(proving_key->proving_key); + typename TestFixture::Verifier verifier(verification_key); EXPECT_EQ(verifier.verify_proof(proof), true); } 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 6fa308df92c..c7ae3ab1d07 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 }; +enum PROOF_TYPE { PLONK, HONK, OINK, PG, AVM, ROLLUP_HONK, ROLLUP_ROOT_HONK }; using namespace bb::plonk; using Builder = bb::UltraCircuitBuilder; From cd95fb4f0ec193e365e1cc6b41afac02330dd895 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Fri, 6 Dec 2024 19:31:51 +0000 Subject: [PATCH 2/8] change to claim and not indices --- .../src/barretenberg/dsl/acir_format/acir_format.cpp | 10 ++++++---- .../dsl/acir_format/honk_recursion_constraint.cpp | 2 +- .../dsl/acir_format/honk_recursion_constraint.hpp | 2 +- 3 files changed, 8 insertions(+), 6 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 d47bc3823cb..1d3d0646caf 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -350,17 +350,19 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( { // Add recursion constraints size_t idx = 0; + std::vector>> nested_ipa_claims; for (auto& constraint : constraint_system.honk_recursion_constraints) { if (constraint.proof_type == HONK) { - auto [next_aggregation_object, ipa_claim_indices] = - create_honk_recursion_constraints>( - builder, constraint, current_aggregation_object, has_valid_witness_assignments); + auto [next_aggregation_object, _] = 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) { - auto [next_aggregation_object, ipa_claim_indices] = + auto [next_aggregation_object, ipa_claim] = create_honk_recursion_constraints>( builder, constraint, current_aggregation_object, has_valid_witness_assignments); current_aggregation_object = next_aggregation_object; + + nested_ipa_claims.push_back(ipa_claim); } else { throw_or_abort("Invalid Honk proof type"); } 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 7158694b8e1..dc8b524a7f8 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 @@ -245,7 +245,7 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( HonkRecursionConstraintOutput output; output.agg_obj_indices = verifier_output.agg_obj.get_witness_indices(); if constexpr (HasIPAAccumulator) { - output.ipa_claim_indices = verifier_output.ipa_opening_claim.get_witness_indices(); + output.ipa_claim = verifier_output.ipa_opening_claim; } return output; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp index ec936a91baf..e50f384f759 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp @@ -10,7 +10,7 @@ using namespace bb; struct HonkRecursionConstraintOutput { PairingPointAccumulatorIndices agg_obj_indices; - IPAClaimIndices ipa_claim_indices; + OpeningClaim> ipa_claim; }; template From e163856b07c67afbca497fc2890f531735caa2dc Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Fri, 6 Dec 2024 19:43:34 +0000 Subject: [PATCH 3/8] fix build --- .../barretenberg/dsl/acir_format/honk_recursion_constraint.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp index e50f384f759..2ded9781fe5 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp @@ -1,6 +1,8 @@ #pragma once +#include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/dsl/acir_format/recursion_constraint.hpp" #include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" +#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" #include namespace acir_format { From 19e6ebdad67584d3b6cf39ddce0f49b3bb88f311 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Fri, 6 Dec 2024 20:44:07 +0000 Subject: [PATCH 4/8] wip --- .../dsl/acir_format/acir_format.cpp | 10 +++++-- .../acir_format/honk_recursion_constraint.cpp | 29 +++++++++++++------ .../acir_format/honk_recursion_constraint.hpp | 1 + 3 files changed, 29 insertions(+), 11 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 1d3d0646caf..0c8bc24f81c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -351,18 +351,20 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( // Add recursion constraints size_t idx = 0; std::vector>> nested_ipa_claims; + std::vector>> nested_ipa_proofs; for (auto& constraint : constraint_system.honk_recursion_constraints) { if (constraint.proof_type == HONK) { - auto [next_aggregation_object, _] = create_honk_recursion_constraints>( + auto [next_aggregation_object, _, _] = 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) { - auto [next_aggregation_object, ipa_claim] = + 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; nested_ipa_claims.push_back(ipa_claim); + nested_ipa_proofs.push_back(ipa_proof); } else { throw_or_abort("Invalid Honk proof type"); } @@ -370,6 +372,10 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( gate_counter.track_diff(constraint_system.gates_per_opcode, constraint_system.original_opcode_indices.honk_recursion_constraints.at(idx++)); } + // Accumulate the claims + if (nested_ipa_claims.size() == 2) { + // IPA>::accumulate() + } return current_aggregation_object; } 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 dc8b524a7f8..95a5745f854 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 @@ -36,7 +36,8 @@ void create_dummy_vkey_and_proof(Builder& builder, size_t proof_size, size_t public_inputs_size, const std::vector& key_fields, - const std::vector& proof_fields) + const std::vector& proof_fields, + bool is_rollup_honk_recursion_constraint) { // Set vkey->circuit_size correctly based on the proof size size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); @@ -60,7 +61,7 @@ void create_dummy_vkey_and_proof(Builder& builder, builder.assert_equal(builder.add_variable(1), key_fields[3].witness_index); uint32_t offset = 4; size_t num_inner_public_inputs = public_inputs_size - bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if constexpr (HasIPAAccumulator) { + if (is_rollup_honk_recursion_constraint) { num_inner_public_inputs -= bb::IPA_CLAIM_SIZE; } @@ -70,7 +71,7 @@ void create_dummy_vkey_and_proof(Builder& builder, offset++; } - if constexpr (HasIPAAccumulator) { + if (is_rollup_honk_recursion_constraint) { // Key field is the whether the proof contains an aggregation object. builder.assert_equal(builder.add_variable(1), key_fields[offset++].witness_index); // We are making the assumption that the IPA claim is behind the inner public inputs and pairing point object @@ -108,7 +109,7 @@ void create_dummy_vkey_and_proof(Builder& builder, offset++; } - if constexpr (HasIPAAccumulator) { + if (is_rollup_honk_recursion_constraint) { IPAClaimIndices ipa_claim; // WORKTODO: initialize this to something? for (auto idx : ipa_claim) { builder.assert_equal(idx, proof_fields[offset].witness_index); @@ -194,7 +195,8 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( using RecursiveVerificationKey = Flavor::VerificationKey; using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; - ASSERT(input.proof_type == HONK || input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK); + bool rollup_honk_recursion_constraint = (input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK); + ASSERT(input.proof_type == HONK || rollup_honk_recursion_constraint); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. @@ -222,11 +224,11 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( // In the constraint, the agg object public inputs are still contained in the proof. To get the 'raw' size of // the proof and public_inputs we subtract and add the corresponding amount from the respective sizes. size_t size_of_proof_with_no_pub_inputs = input.proof.size() - bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if constexpr (HasIPAAccumulator) { + if (rollup_honk_recursion_constraint) { size_of_proof_with_no_pub_inputs -= bb::IPA_CLAIM_SIZE; } size_t total_num_public_inputs = input.public_inputs.size() + bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if constexpr (HasIPAAccumulator) { + if (rollup_honk_recursion_constraint) { total_num_public_inputs += bb::IPA_CLAIM_SIZE; } create_dummy_vkey_and_proof( @@ -238,14 +240,23 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( RecursiveVerifier verifier(&builder, vkey); aggregation_state_ct input_agg_obj = bb::stdlib::recursion::convert_witness_indices_to_agg_obj( builder, input_aggregation_object_indices); + std::vector honk_proof = proof_fields; + HonkRecursionConstraintOutput output; + if (rollup_honk_recursion_constraint) { + ASSERT(input.proof.size() == 602); // WORKTODO: figure out how to not involve random constants + // split out the ipa proof + output.ipa_proof = StdlibProof(honk_proof.begin() + 473, honk_proof.end()); + honk_proof = StdlibProof(honk_proof.begin(), honk_proof.end() + 473); + } UltraRecursiveVerifierOutput verifier_output = verifier.verify_proof(proof_fields, input_agg_obj); // TODO(https://github.com/AztecProtocol/barretenberg/issues/996): investigate whether assert_equal on public inputs // is important, like what the plonk recursion constraint does. - HonkRecursionConstraintOutput output; output.agg_obj_indices = verifier_output.agg_obj.get_witness_indices(); - if constexpr (HasIPAAccumulator) { + if (rollup_honk_recursion_constraint) { + static_assert(HasIPAAccumulator); output.ipa_claim = verifier_output.ipa_opening_claim; + output.ipa_proof = } return output; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp index 2ded9781fe5..34fde4140f9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp @@ -13,6 +13,7 @@ using namespace bb; struct HonkRecursionConstraintOutput { PairingPointAccumulatorIndices agg_obj_indices; OpeningClaim> ipa_claim; + StdlibProof ipa_proof; }; template From 12117e58a57a1a01fadbbb9129a7508b40d28ad1 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Sun, 8 Dec 2024 02:57:05 +0000 Subject: [PATCH 5/8] major updates to honk recursion constarint, acir format, and test to handle IPA proofs --- .../dsl/acir_format/acir_format.cpp | 20 ++++++-- .../acir_format/honk_recursion_constraint.cpp | 38 ++++++++------ .../acir_format/honk_recursion_constraint.hpp | 1 + .../honk_recursion_constraint.test.cpp | 49 ++++++++++++++++--- .../ultra_circuit_builder.hpp | 4 +- .../ultra_rollup_flavor.hpp | 32 ++++++++++++ .../barretenberg/ultra_honk/ultra_prover.cpp | 8 ++- 7 files changed, 126 insertions(+), 26 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 0c8bc24f81c..b71993548b4 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -3,6 +3,7 @@ #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/dsl/acir_format/ivc_recursion_constraint.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" @@ -351,11 +352,12 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( // Add recursion constraints size_t idx = 0; std::vector>> nested_ipa_claims; - std::vector>> nested_ipa_proofs; + std::vector> nested_ipa_proofs; for (auto& constraint : constraint_system.honk_recursion_constraints) { if (constraint.proof_type == HONK) { - auto [next_aggregation_object, _, _] = create_honk_recursion_constraints>( - builder, constraint, current_aggregation_object, has_valid_witness_assignments); + 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) { auto [next_aggregation_object, ipa_claim, ipa_proof] = @@ -374,7 +376,17 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( } // Accumulate the claims if (nested_ipa_claims.size() == 2) { - // IPA>::accumulate() + auto commitment_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + using StdlibTranscript = bb::stdlib::recursion::honk::UltraStdlibTranscript; + + auto ipa_transcript_1 = std::make_shared(nested_ipa_proofs[0]); + auto ipa_transcript_2 = std::make_shared(nested_ipa_proofs[1]); + IPA>::accumulate( + commitment_key, ipa_transcript_1, nested_ipa_claims[0], ipa_transcript_2, nested_ipa_claims[1]); + } else if (nested_ipa_claims.size() == 1) { + builder.add_ipa_claim(nested_ipa_claims[0].get_witness_indices()); + builder.ipa_proof = convert_stdlib_proof_to_native( + nested_ipa_proofs[0]); // WORKTODO: is this bad? or is it fine to just pass the proofs along } return current_aggregation_object; } 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 95a5745f854..5fb7728e74d 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 @@ -195,8 +195,9 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( using RecursiveVerificationKey = Flavor::VerificationKey; using RecursiveVerifier = bb::stdlib::recursion::honk::UltraRecursiveVerifier_; - bool rollup_honk_recursion_constraint = (input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK); - ASSERT(input.proof_type == HONK || rollup_honk_recursion_constraint); + bool is_rollup_honk_recursion_constraint = + (input.proof_type == ROLLUP_HONK || input.proof_type == ROLLUP_ROOT_HONK); + ASSERT(input.proof_type == HONK || is_rollup_honk_recursion_constraint); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. @@ -224,15 +225,19 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( // In the constraint, the agg object public inputs are still contained in the proof. To get the 'raw' size of // the proof and public_inputs we subtract and add the corresponding amount from the respective sizes. size_t size_of_proof_with_no_pub_inputs = input.proof.size() - bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if (rollup_honk_recursion_constraint) { + if (is_rollup_honk_recursion_constraint) { size_of_proof_with_no_pub_inputs -= bb::IPA_CLAIM_SIZE; } size_t total_num_public_inputs = input.public_inputs.size() + bb::PAIRING_POINT_ACCUMULATOR_SIZE; - if (rollup_honk_recursion_constraint) { + if (is_rollup_honk_recursion_constraint) { total_num_public_inputs += bb::IPA_CLAIM_SIZE; } - create_dummy_vkey_and_proof( - builder, size_of_proof_with_no_pub_inputs, total_num_public_inputs, key_fields, proof_fields); + create_dummy_vkey_and_proof(builder, + size_of_proof_with_no_pub_inputs, + total_num_public_inputs, + key_fields, + proof_fields, + is_rollup_honk_recursion_constraint); } // Recursively verify the proof @@ -242,21 +247,26 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( builder, input_aggregation_object_indices); std::vector honk_proof = proof_fields; HonkRecursionConstraintOutput output; - if (rollup_honk_recursion_constraint) { - ASSERT(input.proof.size() == 602); // WORKTODO: figure out how to not involve random constants + if (is_rollup_honk_recursion_constraint) { + const size_t HONK_PROOF_LENGTH = 473; + ASSERT(input.proof.size() == + HONK_PROOF_LENGTH + 65); // WORKTODO: figure out how to not involve random constants + ASSERT(proof_fields.size() == HONK_PROOF_LENGTH + 65 + input.public_inputs.size()); // split out the ipa proof - output.ipa_proof = StdlibProof(honk_proof.begin() + 473, honk_proof.end()); - honk_proof = StdlibProof(honk_proof.begin(), honk_proof.end() + 473); + const std::ptrdiff_t honk_proof_with_pub_inputs_length = + static_cast(HONK_PROOF_LENGTH + input.public_inputs.size()); + output.ipa_proof = + StdlibProof(honk_proof.begin() + honk_proof_with_pub_inputs_length, honk_proof.end()); + honk_proof = StdlibProof(honk_proof.begin(), honk_proof.end() + honk_proof_with_pub_inputs_length); } - UltraRecursiveVerifierOutput verifier_output = verifier.verify_proof(proof_fields, input_agg_obj); + UltraRecursiveVerifierOutput verifier_output = verifier.verify_proof(honk_proof, input_agg_obj); // TODO(https://github.com/AztecProtocol/barretenberg/issues/996): investigate whether assert_equal on public inputs // is important, like what the plonk recursion constraint does. output.agg_obj_indices = verifier_output.agg_obj.get_witness_indices(); - if (rollup_honk_recursion_constraint) { - static_assert(HasIPAAccumulator); + if (is_rollup_honk_recursion_constraint) { + ASSERT(HasIPAAccumulator); output.ipa_claim = verifier_output.ipa_opening_claim; - output.ipa_proof = } return output; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp index 34fde4140f9..a850c8b4f0c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.hpp @@ -1,6 +1,7 @@ #pragma once #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/dsl/acir_format/recursion_constraint.hpp" +#include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" #include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" #include diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index a8feaa93b24..fdb12836ff7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -127,7 +127,29 @@ template class AcirHonkRecursionConstraint : public ::testing: }; auto builder = create_circuit(constraint_system, /*recursive*/ true, /*size_hint*/ 0, witness, /*honk recursion*/ true); - + if constexpr (HasIPAAccumulator) { + using NativeCurve = curve::Grumpkin; + using Curve = stdlib::grumpkin; + auto ipa_transcript = std::make_shared(); + auto ipa_commitment_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + size_t n = 4; + auto poly = Polynomial(n); + for (size_t i = 0; i < n; i++) { + poly.at(i) = fq::random_element(); + } + fq x = fq::random_element(); + fq eval = poly.evaluate(x); + auto commitment = ipa_commitment_key->commit(poly); + const OpeningPair opening_pair = { x, eval }; + IPA::compute_opening_proof(ipa_commitment_key, { poly, opening_pair }, ipa_transcript); + + auto stdlib_comm = Curve::Group::from_witness(&builder, commitment); + auto stdlib_x = Curve::ScalarField::from_witness(&builder, x); + auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval); + OpeningClaim stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm }; + builder.add_ipa_claim(stdlib_opening_claim.get_witness_indices()); + builder.ipa_proof = ipa_transcript->export_proof(); + } return builder; } @@ -153,8 +175,13 @@ template class AcirHonkRecursionConstraint : public ::testing: std::vector key_witnesses = verification_key->to_field_elements(); std::vector proof_witnesses = inner_proof; - const size_t num_public_inputs_to_extract = + size_t num_public_inputs_to_extract = inner_circuit.get_public_inputs().size() - bb::PAIRING_POINT_ACCUMULATOR_SIZE; + acir_format::PROOF_TYPE proof_type = acir_format::HONK; + if constexpr (HasIPAAccumulator) { + num_public_inputs_to_extract -= IPA_CLAIM_SIZE; + proof_type = ROLLUP_HONK; + } auto [key_indices, proof_indices, inner_public_inputs] = ProofSurgeon::populate_recursion_witness_data( witness, proof_witnesses, key_witnesses, num_public_inputs_to_extract); @@ -164,7 +191,7 @@ template class AcirHonkRecursionConstraint : public ::testing: .proof = proof_indices, .public_inputs = inner_public_inputs, .key_hash = 0, // not used - .proof_type = HONK, + .proof_type = proof_type, }; honk_recursion_constraints.push_back(honk_recursion_constraint); } @@ -183,7 +210,11 @@ template class AcirHonkRecursionConstraint : public ::testing: } protected: - static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } + static void SetUpTestSuite() + { + bb::srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } }; using Flavors = testing::Types; @@ -204,8 +235,14 @@ TYPED_TEST(AcirHonkRecursionConstraint, TestBasicSingleHonkRecursionConstraint) info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); auto verification_key = std::make_shared(proving_key->proving_key); - typename TestFixture::Verifier verifier(verification_key); - EXPECT_EQ(verifier.verify_proof(proof), true); + if constexpr (HasIPAAccumulator) { + auto ipa_verification_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + typename TestFixture::Verifier verifier(verification_key, ipa_verification_key); + EXPECT_EQ(verifier.verify_proof(proof, proving_key->proving_key.ipa_proof), true); + } else { + typename TestFixture::Verifier verifier(verification_key); + EXPECT_EQ(verifier.verify_proof(proof), true); + } } TYPED_TEST(AcirHonkRecursionConstraint, TestBasicDoubleHonkRecursionConstraints) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp index 499dc9df159..c70c8d062e0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp @@ -392,7 +392,8 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase + */ + std::vector to_field_elements() const + { + using namespace bb::field_conversion; + + auto serialize_to_field_buffer = [](const auto& input, std::vector& buffer) { + std::vector input_fields = convert_to_bn254_frs(input); + buffer.insert(buffer.end(), input_fields.begin(), input_fields.end()); + }; + + std::vector elements; + + serialize_to_field_buffer(this->circuit_size, elements); + serialize_to_field_buffer(this->num_public_inputs, elements); + serialize_to_field_buffer(this->pub_inputs_offset, elements); + serialize_to_field_buffer(this->contains_pairing_point_accumulator, elements); + serialize_to_field_buffer(this->pairing_point_accumulator_public_input_indices, elements); + serialize_to_field_buffer(contains_ipa_claim, elements); + serialize_to_field_buffer(ipa_claim_public_input_indices, elements); + + for (const Commitment& commitment : this->get_all()) { + serialize_to_field_buffer(commitment, elements); + } + + return elements; + } + VerificationKey(ProvingKey& proving_key) : contains_ipa_claim(proving_key.contains_ipa_claim) , ipa_claim_public_input_indices(proving_key.ipa_claim_public_input_indices) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp index 152605af4b6..48c1b30a963 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp @@ -36,6 +36,11 @@ UltraProver_::UltraProver_(Builder& circuit) template HonkProof UltraProver_::export_proof() { proof = transcript->proof_data; + // Add the IPA proof + if constexpr (HasIPAAccumulator) { + ASSERT(proving_key->proving_key.ipa_proof.size() == 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2); + proof.insert(proof.end(), proving_key->proving_key.ipa_proof.begin(), proving_key->proving_key.ipa_proof.end()); + } return proof; } template void UltraProver_::generate_gate_challenges() @@ -58,7 +63,8 @@ template HonkProof UltraProver_::construct_proof( DeciderProver_ decider_prover(proving_key, transcript); vinfo("created decider prover"); - return decider_prover.construct_proof(); + decider_prover.construct_proof(); + return export_proof(); } template class UltraProver_; From 74a67be196284def5e19e899da316fe8cc0368e5 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Sun, 8 Dec 2024 04:02:07 +0000 Subject: [PATCH 6/8] update the other tests to actually verify the ipa proof --- .../honk_recursion_constraint.test.cpp | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index fdb12836ff7..194eaf0e9d5 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -261,8 +261,14 @@ TYPED_TEST(AcirHonkRecursionConstraint, TestBasicDoubleHonkRecursionConstraints) info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); auto verification_key = std::make_shared(proving_key->proving_key); - typename TestFixture::Verifier verifier(verification_key); - EXPECT_EQ(verifier.verify_proof(proof), true); + if constexpr (HasIPAAccumulator) { + auto ipa_verification_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + typename TestFixture::Verifier verifier(verification_key, ipa_verification_key); + EXPECT_EQ(verifier.verify_proof(proof, proving_key->proving_key.ipa_proof), true); + } else { + typename TestFixture::Verifier verifier(verification_key); + EXPECT_EQ(verifier.verify_proof(proof), true); + } } TYPED_TEST(AcirHonkRecursionConstraint, TestOneOuterRecursiveCircuit) @@ -319,8 +325,14 @@ TYPED_TEST(AcirHonkRecursionConstraint, TestOneOuterRecursiveCircuit) info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); auto verification_key = std::make_shared(proving_key->proving_key); - typename TestFixture::Verifier verifier(verification_key); - EXPECT_EQ(verifier.verify_proof(proof), true); + if constexpr (HasIPAAccumulator) { + auto ipa_verification_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + typename TestFixture::Verifier verifier(verification_key, ipa_verification_key); + EXPECT_EQ(verifier.verify_proof(proof, proving_key->proving_key.ipa_proof), true); + } else { + typename TestFixture::Verifier verifier(verification_key); + EXPECT_EQ(verifier.verify_proof(proof), true); + } } TYPED_TEST(AcirHonkRecursionConstraint, TestFullRecursiveComposition) @@ -349,6 +361,12 @@ TYPED_TEST(AcirHonkRecursionConstraint, TestFullRecursiveComposition) info("prover gates = ", proving_key->proving_key.circuit_size); auto proof = prover.construct_proof(); auto verification_key = std::make_shared(proving_key->proving_key); - typename TestFixture::Verifier verifier(verification_key); - EXPECT_EQ(verifier.verify_proof(proof), true); + if constexpr (HasIPAAccumulator) { + auto ipa_verification_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); + typename TestFixture::Verifier verifier(verification_key, ipa_verification_key); + EXPECT_EQ(verifier.verify_proof(proof, proving_key->proving_key.ipa_proof), true); + } else { + typename TestFixture::Verifier verifier(verification_key); + EXPECT_EQ(verifier.verify_proof(proof), true); + } } From fa045f20820a0d2c6030cc483a141ea3be919d88 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Sun, 8 Dec 2024 15:57:11 +0000 Subject: [PATCH 7/8] change print statement --- .../dsl/acir_format/honk_recursion_constraint.test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp index 194eaf0e9d5..7f1dbd8f6cb 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.test.cpp @@ -228,7 +228,7 @@ TYPED_TEST(AcirHonkRecursionConstraint, TestBasicSingleHonkRecursionConstraint) auto layer_2_circuit = TestFixture::create_outer_circuit(layer_1_circuits); - info("circuit gates = ", layer_2_circuit.get_estimated_num_finalized_gates()); + info("estimate finalized circuit gates = ", layer_2_circuit.get_estimated_num_finalized_gates()); auto proving_key = std::make_shared(layer_2_circuit); typename TestFixture::Prover prover(proving_key); From 616fe1d218ed787927e733b477f695ae87916b42 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Mon, 9 Dec 2024 21:06:57 +0000 Subject: [PATCH 8/8] add TODOs and cleanup --- .../cpp/src/barretenberg/dsl/acir_format/acir_format.cpp | 5 +++-- .../dsl/acir_format/honk_recursion_constraint.cpp | 6 ++++-- .../cpp/src/barretenberg/ultra_honk/ultra_prover.cpp | 1 + 3 files changed, 8 insertions(+), 4 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 b71993548b4..a4a864625ca 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -385,8 +385,9 @@ PairingPointAccumulatorIndices process_honk_recursion_constraints( commitment_key, ipa_transcript_1, nested_ipa_claims[0], ipa_transcript_2, nested_ipa_claims[1]); } else if (nested_ipa_claims.size() == 1) { builder.add_ipa_claim(nested_ipa_claims[0].get_witness_indices()); - builder.ipa_proof = convert_stdlib_proof_to_native( - nested_ipa_proofs[0]); // WORKTODO: is this bad? or is it fine to just pass the proofs along + // This conversion looks suspicious but there's no need to make this an output of the circuit since its a proof + // that will be checked anyway. + builder.ipa_proof = convert_stdlib_proof_to_native(nested_ipa_proofs[0]); } return current_aggregation_object; } 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 5fb7728e74d..c79535ad7d4 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 @@ -42,6 +42,7 @@ void create_dummy_vkey_and_proof(Builder& builder, // Set vkey->circuit_size correctly based on the proof size size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); size_t num_frs_fr = bb::field_conversion::calc_num_bn254_frs(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor assert((proof_size - bb::HONK_PROOF_PUBLIC_INPUT_OFFSET - Flavor::NUM_WITNESS_ENTITIES * num_frs_comm - Flavor::NUM_ALL_ENTITIES * num_frs_fr - num_frs_comm) % (num_frs_comm + num_frs_fr * (Flavor::BATCHED_RELATION_PARTIAL_LENGTH + 1)) == @@ -248,9 +249,10 @@ HonkRecursionConstraintOutput create_honk_recursion_constraints( std::vector honk_proof = proof_fields; HonkRecursionConstraintOutput output; if (is_rollup_honk_recursion_constraint) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor const size_t HONK_PROOF_LENGTH = 473; - ASSERT(input.proof.size() == - HONK_PROOF_LENGTH + 65); // WORKTODO: figure out how to not involve random constants + // The extra calculation is for the IPA proof length. + ASSERT(input.proof.size() == HONK_PROOF_LENGTH + 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2); ASSERT(proof_fields.size() == HONK_PROOF_LENGTH + 65 + input.public_inputs.size()); // split out the ipa proof const std::ptrdiff_t honk_proof_with_pub_inputs_length = diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp index 48c1b30a963..c07c75b34a3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp @@ -38,6 +38,7 @@ template HonkProof UltraProver_::export_proof() proof = transcript->proof_data; // Add the IPA proof if constexpr (HasIPAAccumulator) { + // The extra calculation is for the IPA proof length. ASSERT(proving_key->proving_key.ipa_proof.size() == 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2); proof.insert(proof.end(), proving_key->proving_key.ipa_proof.begin(), proving_key->proving_key.ipa_proof.end()); }