From 4418ef2a5768e0f627160b86e8dc8735d4bf00e7 Mon Sep 17 00:00:00 2001 From: Lucas Xia Date: Mon, 25 Nov 2024 11:28:43 -0500 Subject: [PATCH] feat: UltraRollupRecursiveFlavor (#10088) Creates new recursive flavor. The recursive verifier with this flavor will extract the IPA claim from the public inputs and return it as part of its output. Modifies the ClientTubeBase test to use this new flavor. --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 2 +- .../acir_format/honk_recursion_constraint.cpp | 6 +- .../acir_format/ivc_recursion_constraint.cpp | 1 + .../cpp/src/barretenberg/flavor/flavor.hpp | 33 ++-- .../client_ivc_recursive_verifier.hpp | 1 - .../client_ivc_recursive_verifier.test.cpp | 24 ++- .../decider_recursive_verifier.hpp | 1 + .../honk_verifier/oink_recursive_verifier.cpp | 2 + .../ultra_recursive_verifier.cpp | 43 +++++- .../ultra_recursive_verifier.hpp | 13 +- .../ultra_recursive_verifier.test.cpp | 4 +- .../stdlib/primitives/group/cycle_group.cpp | 2 +- .../stdlib/transcript/transcript.test.cpp | 1 + .../circuit_simulator.hpp | 17 +++ .../mega_circuit_builder.hpp | 8 +- .../ultra_circuit_builder.hpp | 38 +++-- .../ultra_rollup_recursive_flavor.hpp | 144 ++++++++++++++++++ .../ultra_honk/decider_proving_key.hpp | 2 +- .../ultra_honk/ultra_verifier.cpp | 2 +- 19 files changed, 283 insertions(+), 61 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 12884597ab3..df9fdcb9193 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -1148,7 +1148,7 @@ template bool verify_honk(const std::string& proof_path, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1154): Remove this and pass in the IPA proof to the // verifier. std::shared_ptr> ipa_verification_key = nullptr; - if constexpr (HasIPAAccumulatorFlavor) { + if constexpr (HasIPAAccumulator) { init_grumpkin_crs(1 << 16); vk->contains_ipa_claim = false; ipa_verification_key = std::make_shared>(1 << CONST_ECCVM_LOG_N); 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 fb46b29e8f0..45da4234f6f 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 @@ -6,12 +6,14 @@ #include "barretenberg/stdlib/primitives/bigfield/constants.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp" #include "proof_surgeon.hpp" #include "recursion_constraint.hpp" namespace acir_format { using namespace bb; +using namespace bb::stdlib::recursion::honk; using field_ct = stdlib::field_t; using bn254 = stdlib::bn254; using aggregation_state_ct = bb::stdlib::recursion::aggregation_state; @@ -208,11 +210,11 @@ 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); - aggregation_state_ct output_agg_object = verifier.verify_proof(proof_fields, input_agg_obj); + UltraRecursiveVerifierOutput 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_object.get_witness_indices(); + return output.agg_obj.get_witness_indices(); } } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp index ee700237966..7543b933f9e 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp @@ -6,6 +6,7 @@ #include "barretenberg/stdlib/primitives/bigfield/constants.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp" #include "proof_surgeon.hpp" #include "recursion_constraint.hpp" diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index b170033f7b2..b9230e4675a 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -331,6 +331,7 @@ class MegaZKFlavor; class TranslatorFlavor; class AvmFlavor; template class UltraRecursiveFlavor_; +template class UltraRollupRecursiveFlavor_; template class MegaRecursiveFlavor_; template class MegaZKRecursiveFlavor_; template class TranslatorRecursiveFlavor_; @@ -367,30 +368,31 @@ template concept IsMegaFlavor = IsAnyOf, MegaRecursiveFlavor_, -MegaRecursiveFlavor_, -MegaZKRecursiveFlavor_, -MegaZKRecursiveFlavor_>; + MegaRecursiveFlavor_, + MegaZKRecursiveFlavor_, + MegaZKRecursiveFlavor_>; template concept HasDataBus = IsMegaFlavor; template -concept HasIPAAccumulatorFlavor = IsAnyOf; +concept HasIPAAccumulator = IsAnyOf>; template concept IsRecursiveFlavor = IsAnyOf, UltraRecursiveFlavor_, UltraRecursiveFlavor_, + UltraRollupRecursiveFlavor_, MegaRecursiveFlavor_, MegaRecursiveFlavor_, -MegaRecursiveFlavor_, -MegaZKRecursiveFlavor_, -MegaZKRecursiveFlavor_, -TranslatorRecursiveFlavor_, -TranslatorRecursiveFlavor_, -TranslatorRecursiveFlavor_, -ECCVMRecursiveFlavor_, -AvmRecursiveFlavor_>; + MegaRecursiveFlavor_, + MegaZKRecursiveFlavor_, + MegaZKRecursiveFlavor_, + TranslatorRecursiveFlavor_, + TranslatorRecursiveFlavor_, + TranslatorRecursiveFlavor_, + ECCVMRecursiveFlavor_, + AvmRecursiveFlavor_>; template concept IsECCVMRecursiveFlavor = IsAnyOf>; @@ -406,11 +408,12 @@ template concept IsFoldingFlavor = IsAnyOf, UltraRecursiveFlavor_, UltraRecursiveFlavor_, + UltraRollupRecursiveFlavor_, MegaRecursiveFlavor_, MegaRecursiveFlavor_, -MegaRecursiveFlavor_, -MegaZKRecursiveFlavor_, -MegaZKRecursiveFlavor_>; + MegaRecursiveFlavor_, + MegaZKRecursiveFlavor_, + MegaZKRecursiveFlavor_>; template concept FlavorHasZK = T::HasZK; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp index 4381b1f5faf..db36f16230a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.hpp @@ -10,7 +10,6 @@ class ClientIVCRecursiveVerifier { using RecursiveDeciderVerificationKeys = RecursiveDeciderVerificationKeys_; using RecursiveDeciderVerificationKey = RecursiveDeciderVerificationKeys::DeciderVK; using RecursiveVerificationKey = RecursiveDeciderVerificationKeys::VerificationKey; - using DeciderVerifier = DeciderRecursiveVerifier_; using FoldingVerifier = ProtogalaxyRecursiveVerifier_; using MegaVerifier = UltraRecursiveVerifier_; using GoblinVerifier = GoblinRecursiveVerifier; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp index 3c4cc8a4a2c..3ce5a457400 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.test.cpp @@ -15,8 +15,8 @@ class ClientIVCRecursionTests : public testing::Test { using ECCVMVK = GoblinVerifier::ECCVMVerificationKey; using TranslatorVK = GoblinVerifier::TranslatorVerificationKey; using Proof = ClientIVC::Proof; - using Flavor = UltraRecursiveFlavor_; - using NativeFlavor = UltraRollupFlavor; + using Flavor = UltraRollupRecursiveFlavor_; + using NativeFlavor = Flavor::NativeFlavor; using UltraRecursiveVerifier = UltraRecursiveVerifier_; static void SetUpTestSuite() @@ -125,7 +125,7 @@ TEST_F(ClientIVCRecursionTests, ClientTubeBase) // EXPECT_TRUE(CircuitChecker::check(*tube_builder)); // Construct and verify a proof for the ClientIVC Recursive Verifier circuit - auto proving_key = std::make_shared>(*tube_builder); + auto proving_key = std::make_shared>(*tube_builder); UltraProver_ tube_prover{ proving_key }; auto native_tube_proof = tube_prover.construct_proof(); @@ -135,18 +135,26 @@ TEST_F(ClientIVCRecursionTests, ClientTubeBase) UltraVerifier_ native_verifier(native_vk_with_ipa, ipa_verification_key); EXPECT_TRUE(native_verifier.verify_proof(native_tube_proof, tube_prover.proving_key->proving_key.ipa_proof)); - // Construct a base rollup circuit that recursively verifies the tube proof. + // Construct a base rollup circuit that recursively verifies the tube proof and forwards the IPA proof. Builder base_builder; - auto native_vk = std::make_shared(proving_key->proving_key); + auto native_vk = std::make_shared(proving_key->proving_key); auto vk = std::make_shared(&base_builder, native_vk); auto tube_proof = bb::convert_native_proof_to_stdlib(&base_builder, native_tube_proof); UltraRecursiveVerifier base_verifier{ &base_builder, vk }; - base_verifier.verify_proof(tube_proof, - stdlib::recursion::init_default_aggregation_state(base_builder)); + UltraRecursiveVerifierOutput output = base_verifier.verify_proof( + tube_proof, stdlib::recursion::init_default_aggregation_state(base_builder)); info("UH Recursive Verifier: num prefinalized gates = ", base_builder.num_gates); - + base_builder.add_pairing_point_accumulator(output.agg_obj.get_witness_indices()); + base_builder.add_ipa_claim(output.ipa_opening_claim.get_witness_indices()); + base_builder.ipa_proof = tube_prover.proving_key->proving_key.ipa_proof; EXPECT_EQ(base_builder.failed(), false) << base_builder.err(); EXPECT_TRUE(CircuitChecker::check(base_builder)); + + // Natively verify the IPA proof for the base rollup circuit + auto base_proving_key = std::make_shared>(base_builder); + auto ipa_transcript = std::make_shared(base_proving_key->proving_key.ipa_proof); + IPA::reduce_verify( + ipa_verification_key, output.ipa_opening_claim.get_native_opening_claim(), ipa_transcript); } } // namespace bb::stdlib::recursion::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp index 409159fd764..2b2c8d053f0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.hpp @@ -4,6 +4,7 @@ #include "barretenberg/stdlib/transcript/transcript.hpp" #include "barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" namespace bb::stdlib::recursion::honk { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp index 6e09db90b52..d9974b8f056 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp @@ -5,6 +5,7 @@ #include "barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/mega_zk_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp" #include namespace bb::stdlib::recursion::honk { @@ -136,4 +137,5 @@ template class OinkRecursiveVerifier_>; template class OinkRecursiveVerifier_>; template class OinkRecursiveVerifier_>; +template class OinkRecursiveVerifier_>; } // namespace bb::stdlib::recursion::honk diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 2bd074dfd97..2cd6e8050d6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -24,8 +24,8 @@ UltraRecursiveVerifier_::UltraRecursiveVerifier_(Builder* builder, const * @return Output aggregation object */ template -UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_::verify_proof( - const HonkProof& proof, AggregationObject agg_obj) +UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_proof(const HonkProof& proof, + AggregationObject agg_obj) { StdlibProof stdlib_proof = bb::convert_native_proof_to_stdlib(builder, proof); return verify_proof(stdlib_proof, agg_obj); @@ -36,8 +36,8 @@ UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_ -UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_::verify_proof( - const StdlibProof& proof, AggregationObject agg_obj) +UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_proof(const StdlibProof& proof, + AggregationObject agg_obj) { using Sumcheck = ::bb::SumcheckVerifier; using PCS = typename Flavor::PCS; @@ -127,7 +127,39 @@ UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_ipa_claim_public_input_indices and runs the native IPA verifier. + if constexpr (HasIPAAccumulator) { + const auto recover_fq_from_public_inputs = [](std::array& limbs) { + for (size_t k = 0; k < Curve::BaseField::NUM_LIMBS; k++) { + limbs[k].create_range_constraint(Curve::BaseField::NUM_LIMB_BITS, "limb_" + std::to_string(k)); + } + return Curve::BaseField::unsafe_construct_from_limbs(limbs[0], limbs[1], limbs[2], limbs[3], false); + }; + + if (verification_key->verification_key->contains_ipa_claim) { + OpeningClaim> ipa_claim; + std::array bigfield_limbs; + for (size_t k = 0; k < 4; k++) { + bigfield_limbs[k] = + verification_key + ->public_inputs[verification_key->verification_key->ipa_claim_public_input_indices[k]]; + } + ipa_claim.opening_pair.challenge = recover_fq_from_public_inputs(bigfield_limbs); + ipa_claim.opening_pair.evaluation = 0; + ipa_claim.commitment = { + verification_key->public_inputs[verification_key->verification_key->ipa_claim_public_input_indices[4]], + verification_key->public_inputs[verification_key->verification_key->ipa_claim_public_input_indices[5]], + false // WORKTODO: make this a witness? + }; + output.ipa_opening_claim = std::move(ipa_claim); + } + } + + return output; } template class UltraRecursiveVerifier_>; @@ -138,4 +170,5 @@ template class UltraRecursiveVerifier_>; template class UltraRecursiveVerifier_>; template class UltraRecursiveVerifier_>; +template class UltraRecursiveVerifier_>; } // namespace bb::stdlib::recursion::honk diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp index a72692241f8..7a8006e6431 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp @@ -6,9 +6,17 @@ #include "barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/mega_zk_recursive_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" namespace bb::stdlib::recursion::honk { + +template struct UltraRecursiveVerifierOutput { + using AggregationObject = aggregation_state; + using Builder = typename Flavor::CircuitBuilder; + AggregationObject agg_obj; + OpeningClaim> ipa_opening_claim; +}; template class UltraRecursiveVerifier_ { public: using FF = typename Flavor::FF; @@ -23,13 +31,14 @@ template class UltraRecursiveVerifier_ { using AggregationObject = aggregation_state; using Transcript = bb::BaseTranscript>; using OinkVerifier = OinkRecursiveVerifier_; + using Output = UltraRecursiveVerifierOutput; explicit UltraRecursiveVerifier_(Builder* builder, const std::shared_ptr& native_verifier_key); explicit UltraRecursiveVerifier_(Builder* builder, const std::shared_ptr& vkey); - AggregationObject verify_proof(const HonkProof& proof, AggregationObject agg_obj); - AggregationObject verify_proof(const StdlibProof& proof, AggregationObject agg_obj); + Output verify_proof(const HonkProof& proof, AggregationObject agg_obj); + Output verify_proof(const StdlibProof& proof, AggregationObject agg_obj); std::shared_ptr key; std::shared_ptr pcs_verification_key; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp index 5e9eb7727ff..86ab9028de1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp @@ -211,7 +211,9 @@ template class RecursiveVerifierTest : public testing aggregation_state agg_obj = init_default_aggregation_state(outer_circuit); - auto pairing_points = verifier.verify_proof(inner_proof, agg_obj); + bb::stdlib::recursion::honk::UltraRecursiveVerifierOutput output = + verifier.verify_proof(inner_proof, agg_obj); + aggregation_state pairing_points = output.agg_obj; info("Recursive Verifier: num gates = ", outer_circuit.get_estimated_num_finalized_gates()); // Check for a failure flag in the recursive verifier circuit diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp index f7f632e298b..ab196d6d1c2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.cpp @@ -1606,6 +1606,6 @@ template cycle_group cycle_group::operator/ template class cycle_group; template class cycle_group; template class cycle_group; -template struct cycle_group::cycle_scalar; +template class cycle_group; } // namespace bb::stdlib diff --git a/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp index debefb03a5d..d133798224a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/transcript/transcript.test.cpp @@ -6,6 +6,7 @@ #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp" #include "barretenberg/transcript/transcript.hpp" #include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp index 14c55eac6b2..5d8221ee15b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_simulator.hpp @@ -189,6 +189,23 @@ class CircuitSimulatorBN254 { [[nodiscard]] bool check_circuit() const { return !_failed; } + size_t create_ROM_array([[maybe_unused]] const size_t array_size) { return {}; } + + void set_ROM_element_pair([[maybe_unused]] const size_t rom_id, + [[maybe_unused]] const size_t index_value, + [[maybe_unused]] const std::array& value_witnesses) + {} + uint32_t read_ROM_array([[maybe_unused]] const size_t rom_id, [[maybe_unused]] const uint32_t index_witness) + { + return {}; + } + std::array read_ROM_array_pair([[maybe_unused]] const size_t rom_id, + [[maybe_unused]] const uint32_t index_witness) + { + return {}; + } + void create_ecc_dbl_gate([[maybe_unused]] const ecc_dbl_gate_& in){}; + // Public input indices which contain recursive proof information PairingPointAccumulatorPubInputIndices pairing_point_accumulator_public_input_indices; }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp index 7daa6ded4d7..af513c5509b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp @@ -1,4 +1,6 @@ #pragma once +#include + #include "barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp" #include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" #include "barretenberg/trace_to_polynomials/trace_to_polynomials.hpp" @@ -45,7 +47,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_ op_queue_in = std::make_shared()) : UltraCircuitBuilder_(size_hint) - , op_queue(op_queue_in) + , op_queue(std::move(op_queue_in)) { PROFILE_THIS(); @@ -75,7 +77,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_& public_inputs, size_t varnum) : UltraCircuitBuilder_(/*size_hint=*/0, witness_values, public_inputs, varnum) - , op_queue(op_queue_in) + , op_queue(std::move(op_queue_in)) { // Set indices to constants corresponding to Goblin ECC op codes set_goblin_ecc_op_code_constant_variables(); @@ -153,7 +155,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_is_recursive_circuit = recursive; }; UltraCircuitBuilder_(const UltraCircuitBuilder_& other) = default; - UltraCircuitBuilder_(UltraCircuitBuilder_&& other) + UltraCircuitBuilder_(UltraCircuitBuilder_&& other) noexcept : CircuitBuilderBase(std::move(other)) - { - blocks = other.blocks; - constant_variable_indices = other.constant_variable_indices; - - lookup_tables = other.lookup_tables; - range_lists = other.range_lists; - ram_arrays = other.ram_arrays; - rom_arrays = other.rom_arrays; - memory_read_records = other.memory_read_records; - memory_write_records = other.memory_write_records; - cached_partial_non_native_field_multiplications = other.cached_partial_non_native_field_multiplications; - circuit_finalized = other.circuit_finalized; - }; + , blocks(other.blocks) + , constant_variable_indices(other.constant_variable_indices) + , lookup_tables(other.lookup_tables) + , range_lists(other.range_lists) + , ram_arrays(other.ram_arrays) + , rom_arrays(other.rom_arrays) + , memory_read_records(other.memory_read_records) + , memory_write_records(other.memory_write_records) + , cached_partial_non_native_field_multiplications(other.cached_partial_non_native_field_multiplications) + , circuit_finalized(other.circuit_finalized){}; UltraCircuitBuilder_& operator=(const UltraCircuitBuilder_& other) = default; - UltraCircuitBuilder_& operator=(UltraCircuitBuilder_&& other) + UltraCircuitBuilder_& operator=(UltraCircuitBuilder_&& other) noexcept { CircuitBuilderBase::operator=(std::move(other)); blocks = other.blocks; @@ -504,7 +501,6 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase evaluate_non_native_field_multiplication(const non_native_field_witnesses& input); std::array queue_partial_non_native_field_multiplication(const non_native_field_witnesses& input); - typedef std::pair scaled_witness; - typedef std::tuple add_simple; + using scaled_witness = std::pair; + using add_simple = std::tuple; std::array evaluate_non_native_field_subtraction(add_simple limb0, add_simple limb1, add_simple limb2, diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp new file mode 100644 index 00000000000..96276a00773 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_rollup_recursive_flavor.hpp @@ -0,0 +1,144 @@ +#pragma once +#include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/flavor/flavor_macros.hpp" +#include "barretenberg/polynomials/barycentric.hpp" +#include "barretenberg/polynomials/evaluation_domain.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/transcript/transcript.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_rollup_flavor.hpp" + +namespace bb { + +/** + * @brief The recursive counterpart to the "native" UltraRollupFlavor. + * @details This flavor can be used to instantiate a recursive Mega Honk verifier for a proof created using the + * MegaZKFlavor. It is similar in structure to its native counterpart with two main differences: 1) the + * curve types are stdlib types (e.g. field_t instead of field) and 2) it does not specify any Prover related types + * (e.g. Polynomial, ExtendedEdges, etc.) since we do not emulate prover computation in circuits, i.e. it only makes + * sense to instantiate a Verifier with this flavor. + * + * @note Unlike conventional flavors, "recursive" flavors are templated by a builder (much like native vs stdlib types). + * This is because the flavor itself determines the details of the underlying verifier algorithm (i.e. the set of + * relations), while the Builder determines the arithmetization of that algorithm into a circuit. + * + * @tparam BuilderType Determines the arithmetization of the verifier circuit defined based on this flavor. + */ +template class UltraRollupRecursiveFlavor_ : public UltraRecursiveFlavor_ { + public: + using CircuitBuilder = BuilderType; // Determines arithmetization of circuit instantiated with this flavor + using NativeFlavor = UltraRollupFlavor; + using Curve = UltraRecursiveFlavor_::Curve; + using PCS = KZG; + using GroupElement = typename Curve::Element; + using Commitment = typename Curve::Element; + using FF = typename Curve::ScalarField; + using VerifierCommitmentKey = bb::VerifierCommitmentKey; + using NativeVerificationKey = NativeFlavor::VerificationKey; + + /** + * @brief The verification key is responsible for storing the commitments to the precomputed (non-witnessk) + * polynomials used by the verifier. + * + * @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to resolve + * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our + * circuits. + */ + class VerificationKey + : public VerificationKey_, VerifierCommitmentKey> { + public: + bool contains_ipa_claim; // needs to be a circuit constant + IPAClaimPubInputIndices ipa_claim_public_input_indices; // needs to be a circuit constant + + VerificationKey(const size_t circuit_size, const size_t num_public_inputs) + { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/983): Think about if these should be witnesses + this->circuit_size = circuit_size; + this->log_circuit_size = numeric::get_msb(circuit_size); + this->num_public_inputs = num_public_inputs; + }; + /** + * @brief Construct a new Verification Key with stdlib types from a provided native verification key + * + * @param builder + * @param native_key Native verification key from which to extract the precomputed commitments + */ + VerificationKey(CircuitBuilder* builder, const std::shared_ptr& native_key) + : contains_ipa_claim(native_key->contains_ipa_claim) + , ipa_claim_public_input_indices(native_key->ipa_claim_public_input_indices) + { + this->pcs_verification_key = native_key->pcs_verification_key; + this->circuit_size = native_key->circuit_size; + this->log_circuit_size = numeric::get_msb(this->circuit_size); + this->num_public_inputs = native_key->num_public_inputs; + this->pub_inputs_offset = native_key->pub_inputs_offset; + this->contains_pairing_point_accumulator = native_key->contains_pairing_point_accumulator; + this->pairing_point_accumulator_public_input_indices = + native_key->pairing_point_accumulator_public_input_indices; + + // Generate stdlib commitments (biggroup) from the native counterparts + for (auto [commitment, native_commitment] : zip_view(this->get_all(), native_key->get_all())) { + commitment = Commitment::from_witness(builder, native_commitment); + } + }; + + /** + * @brief Deserialize a verification key from a vector of field elements + * + * @param builder + * @param elements + */ + VerificationKey(CircuitBuilder& builder, std::span elements) + { + using namespace bb::stdlib::field_conversion; + + size_t num_frs_read = 0; + + this->circuit_size = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->num_public_inputs = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->pub_inputs_offset = uint64_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + this->contains_pairing_point_accumulator = + bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + for (uint32_t& idx : this->pairing_point_accumulator_public_input_indices) { + idx = uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + } + contains_ipa_claim = bool(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + for (uint32_t& idx : this->ipa_claim_public_input_indices) { + idx = uint32_t(deserialize_from_frs(builder, elements, num_frs_read).get_value()); + } + + for (Commitment& commitment : this->get_all()) { + commitment = deserialize_from_frs(builder, elements, num_frs_read); + } + } + + /** + * @brief Construct a VerificationKey from a set of corresponding witness indices + * + * @param builder + * @param witness_indices + * @return VerificationKey + */ + static VerificationKey from_witness_indices(CircuitBuilder& builder, + const std::span witness_indices) + { + std::vector vkey_fields; + vkey_fields.reserve(witness_indices.size()); + for (const auto& idx : witness_indices) { + vkey_fields.emplace_back(FF::from_witness_index(&builder, idx)); + } + return VerificationKey(builder, vkey_fields); + } + }; + + // Reuse the VerifierCommitments from Ultra + using VerifierCommitments = UltraFlavor::VerifierCommitments_; +}; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp index ad9f2eacb99..c706a8e69ad 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp @@ -310,7 +310,7 @@ template class DeciderProvingKey_ { proving_key.public_inputs.emplace_back(proving_key.polynomials.w_r[idx]); } - if constexpr (HasIPAAccumulatorFlavor) { // Set the IPA claim indices + if constexpr (HasIPAAccumulator) { // Set the IPA claim indices proving_key.ipa_claim_public_input_indices = circuit.ipa_claim_public_input_indices; proving_key.contains_ipa_claim = circuit.contains_ipa_claim; proving_key.ipa_proof = circuit.ipa_proof; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index ad8ed0139ee..b14c4a6774d 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -32,7 +32,7 @@ template bool UltraVerifier_::verify_proof(const HonkP }; // Parse out the nested IPA claim using key->ipa_claim_public_input_indices and runs the native IPA verifier. - if constexpr (HasIPAAccumulatorFlavor) { + if constexpr (HasIPAAccumulator) { if (verification_key->verification_key->contains_ipa_claim) { OpeningClaim ipa_claim; std::array bigfield_limbs;