From 564e7eb6dc34037b7925475ed33bc1094d4a64c0 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 23 Aug 2024 14:39:23 +0000 Subject: [PATCH 01/10] first accumulation uses oink, basic test passes --- .../src/barretenberg/aztec_ivc/aztec_ivc.cpp | 63 ++++++++++++++----- .../src/barretenberg/aztec_ivc/aztec_ivc.hpp | 9 ++- .../honk_verifier/oink_recursive_verifier.cpp | 25 +++++++- .../honk_verifier/oink_recursive_verifier.hpp | 8 ++- .../stdlib/primitives/databus/databus.hpp | 58 ++++++----------- .../barretenberg/ultra_honk/oink_prover.hpp | 12 ++-- 6 files changed, 108 insertions(+), 67 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index a0414baa0f7..ffaedfdd316 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -1,4 +1,5 @@ #include "barretenberg/aztec_ivc/aztec_ivc.hpp" +#include "barretenberg/ultra_honk/oink_prover.hpp" namespace bb { @@ -13,23 +14,44 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) { circuit.databus_propagation_data.is_kernel = true; - // The folding verification queue should be either empty or contain two fold proofs - ASSERT(verification_queue.empty() || verification_queue.size() == 2); - - for (auto& [proof, vkey] : verification_queue) { - - // Construct stdlib accumulator, vkey and proof - auto stdlib_verifier_accum = std::make_shared(&circuit, verifier_accumulator); - auto stdlib_vkey = std::make_shared(&circuit, vkey); + for (auto& [proof, vkey, type] : verification_queue) { + // Construct stdlib vkey and proof auto stdlib_proof = bb::convert_proof_to_witness(&circuit, proof); + auto stdlib_vkey = std::make_shared(&circuit, vkey); - // Perform folding recursive verification - FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { stdlib_vkey } }; - auto verifier_accum = verifier.verify_folding_proof(stdlib_proof); - verifier_accumulator = std::make_shared(verifier_accum->get_value()); - - // Perform databus commitment consistency checks and propagate return data commitments via public inputs - bus_depot.execute(verifier.instances); + switch (type) { + case QUEUE_TYPE::PG: { + // Construct stdlib accumulator + auto stdlib_verifier_accum = std::make_shared(&circuit, verifier_accumulator); + + // Perform folding recursive verification + FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { stdlib_vkey } }; + auto verifier_accum = verifier.verify_folding_proof(stdlib_proof); + verifier_accumulator = std::make_shared(verifier_accum->get_value()); + + // Perform databus commitment consistency checks and propagate return data commitments via public inputs + bus_depot.execute(verifier.instances[1]->witness_commitments, + verifier.instances[1]->public_inputs, + verifier.instances[1]->verification_key->databus_propagation_data); + break; + } + case QUEUE_TYPE::OINK: { + auto verifier_accum = std::make_shared(&circuit, stdlib_vkey); + OinkRecursiveVerifier verifier{ &circuit, stdlib_vkey }; + auto [relation_parameters, witness_commitments, public_inputs, alphas] = + verifier.verify_proof(stdlib_proof); + verifier_accum->relation_parameters = std::move(relation_parameters); + verifier_accum->witness_commitments = std::move(witness_commitments); + verifier_accum->public_inputs = std::move(public_inputs); + verifier_accum->alphas = std::move(alphas); + verifier_accumulator = std::make_shared(verifier_accum->get_value()); + + // Perform databus commitment consistency checks and propagate return data commitments via public inputs + bus_depot.execute(witness_commitments, public_inputs, stdlib_vkey->databus_propagation_data); + + break; + } + } } verification_queue.clear(); @@ -67,15 +89,22 @@ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr oink_prover{ prover_instance->proving_key }; + auto [proving_key, relation_params, alphas] = oink_prover.prove(); + prover_instance->proving_key = std::move(proving_key); + prover_instance->relation_parameters = relation_params; + prover_instance->alphas = alphas; fold_output.accumulator = prover_instance; - verifier_accumulator = std::make_shared(instance_vk); + + verification_queue.emplace_back(oink_prover.transcript->proof_data, instance_vk, QUEUE_TYPE::OINK); + initialized = true; } else { // Otherwise, fold the new instance into the accumulator FoldingProver folding_prover({ fold_output.accumulator, prover_instance }); fold_output = folding_prover.prove(); // Add fold proof and corresponding verification key to the verification queue - verification_queue.emplace_back(fold_output.proof, instance_vk); + verification_queue.emplace_back(fold_output.proof, instance_vk, QUEUE_TYPE::PG); } // Track the maximum size of each block for all circuits porcessed (for debugging purposes only) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp index c203e6036b7..03872223ed5 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp @@ -42,12 +42,13 @@ class AztecIVC { using ECCVMVerificationKey = bb::ECCVMFlavor::VerificationKey; using TranslatorVerificationKey = bb::TranslatorFlavor::VerificationKey; - using GURecursiveFlavor = MegaRecursiveFlavor_; - using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_; + using RecursiveFlavor = MegaRecursiveFlavor_; + using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_; using RecursiveVerifierInstance = RecursiveVerifierInstances::Instance; - using RecursiveVerificationKey = RecursiveVerifierInstances::VerificationKey; + using RecursiveVerificationKey = RecursiveFlavor::VerificationKey; using FoldingRecursiveVerifier = bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_; + using OinkRecursiveVerifier = stdlib::recursion::honk::OinkRecursiveVerifier_; using DataBusDepot = stdlib::DataBusDepot; @@ -62,9 +63,11 @@ class AztecIVC { MSGPACK_FIELDS(folding_proof, decider_proof, goblin_proof); }; + enum class QUEUE_TYPE { OINK, PG }; struct FoldingVerifierInputs { FoldProof proof; std::shared_ptr instance_vk; + QUEUE_TYPE type; }; // Utility for tracking the max size of each block across the full IVC 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 25f225796a7..d279198e52b 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 @@ -18,9 +18,30 @@ OinkRecursiveVerifier_::OinkRecursiveVerifier_(Builder* builder, , domain_separator(std::move(domain_separator)) {} +template +OinkRecursiveVerifier_::OinkRecursiveVerifier_(Builder* builder, + const std::shared_ptr& vkey, + std::string domain_separator) + : key(vkey) + , builder(builder) + , domain_separator(std::move(domain_separator)) +{} + +/** + * @brief This function constructs a recursive oink verifier circuit for an oink proof. + * + */ +template +OinkRecursiveVerifier_::Output OinkRecursiveVerifier_::verify_proof(OinkProof& proof) +{ + transcript = std::make_shared(proof); + return verify(); +} + /** - * @brief This function constructs a recursive verifier circuit for a native Ultra Honk proof of a given flavor. - * @return Output aggregation object + * @brief This function constructs a recursive oink verifier circuit for an oink proof assumed to be contained in the + * transcript. + * */ template OinkRecursiveVerifier_::Output OinkRecursiveVerifier_::verify() { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp index 33a392398f6..5c33fe12ca1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp @@ -15,6 +15,7 @@ template class OinkRecursiveVerifier_ { using RelationSeparator = typename Flavor::RelationSeparator; using Transcript = bb::BaseTranscript>; using WitnessCommitments = typename Flavor::WitnessCommitments; + using OinkProof = std::vector; struct Output { bb::RelationParameters relation_parameters; @@ -28,11 +29,16 @@ template class OinkRecursiveVerifier_ { std::shared_ptr transcript, std::string domain_separator = ""); + explicit OinkRecursiveVerifier_(Builder* builder, + const std::shared_ptr& vkey, + std::string domain_separator = ""); + Output verify(); + Output verify_proof(OinkProof& proof); std::shared_ptr key; Builder* builder; - std::shared_ptr transcript; + std::shared_ptr transcript{ nullptr }; std::string domain_separator; // used in PG to distinguish between instances in transcript }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp index c9b0fcb751d..a1ad6e11b47 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp @@ -71,6 +71,7 @@ template class DataBusDepot { using RecursiveFlavor = MegaRecursiveFlavor_; using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_; + using WitnessCommitments = RecursiveFlavor::WitnessCommitments; static constexpr size_t NUM_FR_LIMBS_PER_FQ = Fq::NUM_LIMBS; static constexpr size_t NUM_FR_LIMBS_PER_COMMITMENT = NUM_FR_LIMBS_PER_FQ * 2; @@ -93,48 +94,29 @@ template class DataBusDepot { * * @param instances Completed verifier instances corresponding to prover instances that have been folded */ - void execute(RecursiveVerifierInstances& instances) + void execute(WitnessCommitments& commitments, + std::vector& public_inputs, + DatabusPropagationData& propagation_data) { - // Upon completion of folding recursive verfication, the verifier contains two completed verifier instances - // which store data from a fold proof. The first is the instance into which we're folding and the second - // corresponds to an instance being folded. - auto inst_1 = instances[0]; // instance into which we're folding (an accumulator, except on the initial round) - auto inst_2 = instances[1]; // instance that has been folded - - // The first folding round is a special case in that it folds an instance into a non-accumulator instance. The - // fold proof thus contains two oink proofs. The first oink proof (stored in first instance) contains the return - // data R_0' from the first app, and its calldata counterpart C_0' in the kernel will be contained in the second - // oink proof (stored in second instance). In this special case, we can check directly that \pi_0.R_0' = - // \pi_0.C_0', without having had to propagate the return data commitment via the public inputs. - if (!inst_1->is_accumulator) { - // Assert equality of \pi_0.R_0' and \pi_0.C_0' - auto& app_return_data = inst_1->witness_commitments.return_data; // \pi_0.R_0' - auto& secondary_calldata = inst_2->witness_commitments.secondary_calldata; // \pi_0.C_0' - assert_equality_of_commitments(app_return_data, secondary_calldata); // assert equality R_0' == C_0' - } - - // Define aliases for members in the second (non-accumulator) instance - bool is_kernel_instance = inst_2->verification_key->databus_propagation_data.is_kernel; - auto& propagation_data = inst_2->verification_key->databus_propagation_data; - auto& public_inputs = inst_2->public_inputs; - auto& commitments = inst_2->witness_commitments; + // Is this data coming from a kernel? Only kernels can contain commitments propagated via public inputs + bool is_kernel_instance = propagation_data.is_kernel; // Assert equality between return data commitments propagated via the public inputs and the corresponding // calldata commitment - if (is_kernel_instance) { // only kernels can contain commitments propagated via public inputs - if (propagation_data.contains_app_return_data_commitment) { - // Assert equality between the app return data commitment and the kernel secondary calldata commitment - size_t start_idx = propagation_data.app_return_data_public_input_idx; - Commitment app_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); - assert_equality_of_commitments(app_return_data, commitments.secondary_calldata); - } - - if (propagation_data.contains_kernel_return_data_commitment) { - // Assert equality between the previous kernel return data commitment and the kernel calldata commitment - size_t start_idx = propagation_data.kernel_return_data_public_input_idx; - Commitment kernel_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); - assert_equality_of_commitments(kernel_return_data, commitments.calldata); - } + if (propagation_data.contains_app_return_data_commitment) { + ASSERT(is_kernel_instance); + // Assert equality between the app return data commitment and the kernel secondary calldata commitment + size_t start_idx = propagation_data.app_return_data_public_input_idx; + Commitment app_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); + assert_equality_of_commitments(app_return_data, commitments.secondary_calldata); + } + + if (propagation_data.contains_kernel_return_data_commitment) { + ASSERT(is_kernel_instance); + // Assert equality between the previous kernel return data commitment and the kernel calldata commitment + size_t start_idx = propagation_data.kernel_return_data_public_input_idx; + Commitment kernel_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); + assert_equality_of_commitments(kernel_return_data, commitments.calldata); } // Propagate the return data commitment via the public inputs mechanism diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp index 245d8256cd6..1482ec98f21 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp @@ -2,12 +2,12 @@ // clang-format off /* )\ /| * .-/'-|_/ | -* __ __,-' ( / \/ -* .-'" "'-..__,-'"" -o.`-._ +* __ __,-' ( / \/ +* .-'" "'-..__,-'"" -o.`-._ * / '/ -* *--._ ./ _.-- -* | _.-' -* : .-/ +* *--._ ./ _.-- +* | _.-' +* : .-/ * \ )_ / * \ _) / \( * `. /-.___.---'( / \\ @@ -57,7 +57,7 @@ template class OinkProver { bb::RelationParameters relation_parameters; OinkProver(ProvingKey& proving_key, - const std::shared_ptr& transcript, + const std::shared_ptr& transcript = std::make_shared(), std::string domain_separator = "") : proving_key(std::move(proving_key)) , transcript(transcript) From c84d232149f2fd46892caecd14661cd227a9821e Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 23 Aug 2024 18:25:24 +0000 Subject: [PATCH 02/10] WiP debugging; solution is oink as an instance completer --- .../src/barretenberg/aztec_ivc/aztec_ivc.cpp | 15 +++++++ .../aztec_ivc/aztec_ivc_integration.test.cpp | 2 +- .../aztec_ivc/mock_circuit_producer.hpp | 26 +++++++++-- .../src/barretenberg/goblin/mock_circuits.hpp | 44 ++++++++++++------- 4 files changed, 66 insertions(+), 21 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index ffaedfdd316..d8d66c77479 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -44,6 +44,14 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) verifier_accum->witness_commitments = std::move(witness_commitments); verifier_accum->public_inputs = std::move(public_inputs); verifier_accum->alphas = std::move(alphas); + verifier_accum->is_accumulator = true; + // WORKTODO: this is wrong because FF is the native field type and we need the stdlib version. Solution is + // probably just for gate_challenges to be handled internally by oink prover/verifier. + auto gate_challenges = std::vector(CONST_PROOF_SIZE_LOG_N); + for (size_t idx = 0; idx < CONST_PROOF_SIZE_LOG_N; idx++) { + gate_challenges[idx] = + verifier.transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); + } verifier_accumulator = std::make_shared(verifier_accum->get_value()); // Perform databus commitment consistency checks and propagate return data commitments via public inputs @@ -73,6 +81,11 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) */ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr& precomputed_vk) { + if (!CircuitChecker::check(circuit)) { + info("CIRCUIT CHECK FAILED!"); + } else { + info("CIRCUIT CHECK PASSED!"); + } // Construct merge proof for the present circuit and add to merge verification queue MergeProof merge_proof = goblin.prove_merge(circuit); merge_verification_queue.emplace_back(merge_proof); @@ -94,6 +107,8 @@ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptrproving_key = std::move(proving_key); prover_instance->relation_parameters = relation_params; prover_instance->alphas = alphas; + prover_instance->gate_challenges = std::vector(prover_instance->proving_key.log_circuit_size, 0); + prover_instance->is_accumulator = true; // this means "is complete" fold_output.accumulator = prover_instance; verification_queue.emplace_back(oink_prover.transcript->proof_data, instance_vk, QUEUE_TYPE::OINK); diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp index 55eca16b126..c76a4f1bdc8 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp @@ -42,7 +42,7 @@ TEST_F(AztecIVCIntegrationTests, BenchmarkCaseSimple) MockCircuitProducer circuit_producer; // Construct and accumulate a series of mocked private function execution circuits - size_t NUM_CIRCUITS = 6; + size_t NUM_CIRCUITS = 2; for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { Builder circuit = circuit_producer.create_next_circuit(ivc); diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp index e6d48e08b32..f49ec558775 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp @@ -91,6 +91,20 @@ class PrivateFunctionExecutionMockCircuitProducer { MockDatabusProducer mock_databus; + static ClientCircuit create_mock_circuit(AztecIVC& ivc, size_t log2_num_gates = 16) + { + ClientCircuit circuit{ ivc.goblin.op_queue }; + MockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates); + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the + // function circuit because we cannot support zero commtiments. While the builder handles this at + // finalisation stage via the add_gates_to_ensure_all_polys_are_non_zero function for other MegaHonk + // circuits (where we don't explicitly need to add goblin ops), in AztecIVC merge proving happens prior to + // folding where the absense of goblin ecc ops will result in zero commitments. + MockCircuits::construct_goblin_ecc_op_circuit(circuit); + return circuit; + } + public: /** * @brief Create a the next circuit (app/kernel) in a mocked private function execution stack @@ -102,14 +116,18 @@ class PrivateFunctionExecutionMockCircuitProducer { bool is_kernel = (circuit_counter % 2 == 0); // Every other circuit is a kernel, starting from the second ClientCircuit circuit{ ivc.goblin.op_queue }; + // ClientCircuit circuit; if (is_kernel) { + // circuit = create_mock_circuit(ivc); GoblinMockCircuits::construct_mock_folding_kernel(circuit); // construct mock base logic - mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs - ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc + // mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs + ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc } else { - bool use_large_circuit = (circuit_counter == 1); // first circuit is size 2^19 + // circuit = create_mock_circuit(ivc); + // bool use_large_circuit = (circuit_counter == 1); // first circuit is size 2^19 + bool use_large_circuit = false; // first circuit is size 2^19 GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app - mock_databus.populate_app_databus(circuit); // populate databus outputs + // mock_databus.populate_app_databus(circuit); // populate databus outputs } return circuit; } diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 241f546cef3..853b6b58da6 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -51,17 +51,23 @@ class GoblinMockCircuits { * @param builder * @param large If true, construct a "large" circuit (2^19), else a medium circuit (2^17) */ - static void construct_mock_app_circuit(MegaBuilder& builder, bool large = false) + static void construct_mock_app_circuit(MegaBuilder& builder, [[maybe_unused]] bool large = false) { - if (large) { // Results in circuit size 2^19 - stdlib::generate_sha256_test_circuit(builder, 12); - stdlib::generate_ecdsa_verification_test_circuit(builder, 11); - stdlib::generate_merkle_membership_test_circuit(builder, 12); - } else { // Results in circuit size 2^17 - stdlib::generate_sha256_test_circuit(builder, 9); - stdlib::generate_ecdsa_verification_test_circuit(builder, 2); - stdlib::generate_merkle_membership_test_circuit(builder, 10); - } + // if (large) { // Results in circuit size 2^19 + // // stdlib::generate_sha256_test_circuit(builder, 12); + // // stdlib::generate_ecdsa_verification_test_circuit(builder, 11); + // // stdlib::generate_merkle_membership_test_circuit(builder, 12); + // } else { // Results in circuit size 2^17 + // // stdlib::generate_sha256_test_circuit(builder, 9); + // // stdlib::generate_ecdsa_verification_test_circuit(builder, 2); + // // stdlib::generate_merkle_membership_test_circuit(builder, 10); + // } + + // stdlib::generate_sha256_test_circuit(builder, 9); + stdlib::generate_ecdsa_verification_test_circuit(builder, 1); + // stdlib::generate_merkle_membership_test_circuit(builder, 10); + + // MockCircuits::construct_arithmetic_circuit(builder, 5); // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the // function circuit because we cannot support zero commtiments. While the builder handles this at @@ -179,12 +185,18 @@ class GoblinMockCircuits { { // Add operations representing general kernel logic e.g. state updates. Note: these are structured to make // the kernel "full" within the dyadic size 2^17 - const size_t NUM_MERKLE_CHECKS = 20; - const size_t NUM_ECDSA_VERIFICATIONS = 1; - const size_t NUM_SHA_HASHES = 1; - stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS); - stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS); - stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES); + // const size_t NUM_MERKLE_CHECKS = 20; + // const size_t NUM_ECDSA_VERIFICATIONS = 1; + // const size_t NUM_SHA_HASHES = 1; + // stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS); + // stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS); + // stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES); + + // stdlib::generate_sha256_test_circuit(builder, 1); + stdlib::generate_ecdsa_verification_test_circuit(builder, 1); + // stdlib::generate_merkle_membership_test_circuit(builder, 20); + + // MockCircuits::construct_arithmetic_circuit(builder, 5); } /** From e2d4143f053f0381e0af1d693e0b8caa69e261ae Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 16:37:24 +0000 Subject: [PATCH 03/10] correctly init gate challanges in oink case --- .../src/barretenberg/aztec_ivc/aztec_ivc.cpp | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index 71e70a59300..6b3fcf6f3b7 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -37,25 +37,17 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) } case QUEUE_TYPE::OINK: { auto verifier_accum = std::make_shared(&circuit, stdlib_vkey); - OinkRecursiveVerifier verifier{ &circuit, stdlib_vkey }; - auto [relation_parameters, witness_commitments, public_inputs, alphas] = - verifier.verify_proof(stdlib_proof); - verifier_accum->relation_parameters = std::move(relation_parameters); - verifier_accum->witness_commitments = std::move(witness_commitments); - verifier_accum->public_inputs = std::move(public_inputs); - verifier_accum->alphas = std::move(alphas); - verifier_accum->is_accumulator = true; - // WORKTODO: this is wrong because FF is the native field type and we need the stdlib version. Solution is - // probably just for gate_challenges to be handled internally by oink prover/verifier. - auto gate_challenges = std::vector(CONST_PROOF_SIZE_LOG_N); - for (size_t idx = 0; idx < CONST_PROOF_SIZE_LOG_N; idx++) { - gate_challenges[idx] = - verifier.transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); - } + OinkRecursiveVerifier oink{ &circuit, verifier_accum }; + oink.verify_proof(stdlib_proof); + verifier_accum->is_accumulator = true; // WORKTODO: using this as a synonym for "is complete" verifier_accumulator = std::make_shared(verifier_accum->get_value()); + verifier_accumulator->gate_challenges = + std::vector(verifier_accum->verification_key->log_circuit_size, 0); // Perform databus commitment consistency checks and propagate return data commitments via public inputs - bus_depot.execute(witness_commitments, public_inputs, stdlib_vkey->databus_propagation_data); + bus_depot.execute(verifier_accum->witness_commitments, + verifier_accum->public_inputs, + verifier_accum->verification_key->databus_propagation_data); break; } @@ -106,17 +98,17 @@ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr(prover_instance->proving_key); - // If this is the first circuit simply initialize the prover and verifier accumulator instances + // If this is the first circuit in the IVC, use oink to compute the completed instance and generate an oink proof if (!initialized) { - OinkProver oink_prover{ prover_instance->proving_key }; - auto [proving_key, relation_params, alphas] = oink_prover.prove(); - prover_instance->proving_key = std::move(proving_key); - prover_instance->relation_parameters = relation_params; - prover_instance->alphas = alphas; + OinkProver oink_prover{ prover_instance }; + oink_prover.prove(); + prover_instance->is_accumulator = true; // WORKTODO: using this as a synonym for "is complete" + // WORKTODO: just default init these in constructor? (same for ver instance) prover_instance->gate_challenges = std::vector(prover_instance->proving_key.log_circuit_size, 0); - prover_instance->is_accumulator = true; // this means "is complete" - fold_output.accumulator = prover_instance; + fold_output.accumulator = prover_instance; // initialize the prover accum with the completed instance + + // Add oink proof and corresponding verification key to the verification queue verification_queue.emplace_back(oink_prover.transcript->proof_data, instance_vk, QUEUE_TYPE::OINK); initialized = true; From e20c77ff20aedfe68ed8d479287efdf84c019883 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 17:10:59 +0000 Subject: [PATCH 04/10] return ivc integration tests to their original state --- .../aztec_ivc/aztec_ivc_integration.test.cpp | 2 +- .../aztec_ivc/mock_circuit_producer.hpp | 26 ++--------- .../src/barretenberg/goblin/mock_circuits.hpp | 44 +++++++------------ 3 files changed, 21 insertions(+), 51 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp index c76a4f1bdc8..55eca16b126 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc_integration.test.cpp @@ -42,7 +42,7 @@ TEST_F(AztecIVCIntegrationTests, BenchmarkCaseSimple) MockCircuitProducer circuit_producer; // Construct and accumulate a series of mocked private function execution circuits - size_t NUM_CIRCUITS = 2; + size_t NUM_CIRCUITS = 6; for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { Builder circuit = circuit_producer.create_next_circuit(ivc); diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp index f49ec558775..e6d48e08b32 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/mock_circuit_producer.hpp @@ -91,20 +91,6 @@ class PrivateFunctionExecutionMockCircuitProducer { MockDatabusProducer mock_databus; - static ClientCircuit create_mock_circuit(AztecIVC& ivc, size_t log2_num_gates = 16) - { - ClientCircuit circuit{ ivc.goblin.op_queue }; - MockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates); - - // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the - // function circuit because we cannot support zero commtiments. While the builder handles this at - // finalisation stage via the add_gates_to_ensure_all_polys_are_non_zero function for other MegaHonk - // circuits (where we don't explicitly need to add goblin ops), in AztecIVC merge proving happens prior to - // folding where the absense of goblin ecc ops will result in zero commitments. - MockCircuits::construct_goblin_ecc_op_circuit(circuit); - return circuit; - } - public: /** * @brief Create a the next circuit (app/kernel) in a mocked private function execution stack @@ -116,18 +102,14 @@ class PrivateFunctionExecutionMockCircuitProducer { bool is_kernel = (circuit_counter % 2 == 0); // Every other circuit is a kernel, starting from the second ClientCircuit circuit{ ivc.goblin.op_queue }; - // ClientCircuit circuit; if (is_kernel) { - // circuit = create_mock_circuit(ivc); GoblinMockCircuits::construct_mock_folding_kernel(circuit); // construct mock base logic - // mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs - ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc + mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs + ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc } else { - // circuit = create_mock_circuit(ivc); - // bool use_large_circuit = (circuit_counter == 1); // first circuit is size 2^19 - bool use_large_circuit = false; // first circuit is size 2^19 + bool use_large_circuit = (circuit_counter == 1); // first circuit is size 2^19 GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app - // mock_databus.populate_app_databus(circuit); // populate databus outputs + mock_databus.populate_app_databus(circuit); // populate databus outputs } return circuit; } diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 853b6b58da6..241f546cef3 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -51,23 +51,17 @@ class GoblinMockCircuits { * @param builder * @param large If true, construct a "large" circuit (2^19), else a medium circuit (2^17) */ - static void construct_mock_app_circuit(MegaBuilder& builder, [[maybe_unused]] bool large = false) + static void construct_mock_app_circuit(MegaBuilder& builder, bool large = false) { - // if (large) { // Results in circuit size 2^19 - // // stdlib::generate_sha256_test_circuit(builder, 12); - // // stdlib::generate_ecdsa_verification_test_circuit(builder, 11); - // // stdlib::generate_merkle_membership_test_circuit(builder, 12); - // } else { // Results in circuit size 2^17 - // // stdlib::generate_sha256_test_circuit(builder, 9); - // // stdlib::generate_ecdsa_verification_test_circuit(builder, 2); - // // stdlib::generate_merkle_membership_test_circuit(builder, 10); - // } - - // stdlib::generate_sha256_test_circuit(builder, 9); - stdlib::generate_ecdsa_verification_test_circuit(builder, 1); - // stdlib::generate_merkle_membership_test_circuit(builder, 10); - - // MockCircuits::construct_arithmetic_circuit(builder, 5); + if (large) { // Results in circuit size 2^19 + stdlib::generate_sha256_test_circuit(builder, 12); + stdlib::generate_ecdsa_verification_test_circuit(builder, 11); + stdlib::generate_merkle_membership_test_circuit(builder, 12); + } else { // Results in circuit size 2^17 + stdlib::generate_sha256_test_circuit(builder, 9); + stdlib::generate_ecdsa_verification_test_circuit(builder, 2); + stdlib::generate_merkle_membership_test_circuit(builder, 10); + } // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the // function circuit because we cannot support zero commtiments. While the builder handles this at @@ -185,18 +179,12 @@ class GoblinMockCircuits { { // Add operations representing general kernel logic e.g. state updates. Note: these are structured to make // the kernel "full" within the dyadic size 2^17 - // const size_t NUM_MERKLE_CHECKS = 20; - // const size_t NUM_ECDSA_VERIFICATIONS = 1; - // const size_t NUM_SHA_HASHES = 1; - // stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS); - // stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS); - // stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES); - - // stdlib::generate_sha256_test_circuit(builder, 1); - stdlib::generate_ecdsa_verification_test_circuit(builder, 1); - // stdlib::generate_merkle_membership_test_circuit(builder, 20); - - // MockCircuits::construct_arithmetic_circuit(builder, 5); + const size_t NUM_MERKLE_CHECKS = 20; + const size_t NUM_ECDSA_VERIFICATIONS = 1; + const size_t NUM_SHA_HASHES = 1; + stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS); + stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS); + stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES); } /** From 6c3ce5ca96bf2a4f3536cb22097919a077287b52 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 18:19:08 +0000 Subject: [PATCH 05/10] coments and cleanup --- .../src/barretenberg/aztec_ivc/aztec_ivc.cpp | 7 +--- .../honk_verifier/oink_recursive_verifier.hpp | 2 +- .../stdlib/primitives/databus/databus.hpp | 42 ++++++++++--------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index 6b3fcf6f3b7..52659aeb0ba 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -15,7 +15,7 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) circuit.databus_propagation_data.is_kernel = true; for (auto& [proof, vkey, type] : verification_queue) { - // Construct stdlib vkey and proof + // Construct stdlib verification key and proof auto stdlib_proof = bb::convert_proof_to_witness(&circuit, proof); auto stdlib_vkey = std::make_shared(&circuit, vkey); @@ -73,11 +73,6 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) */ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr& precomputed_vk) { - if (!CircuitChecker::check(circuit)) { - info("CIRCUIT CHECK FAILED!"); - } else { - info("CIRCUIT CHECK PASSED!"); - } // Construct merge proof for the present circuit and add to merge verification queue MergeProof merge_proof = goblin.prove_merge(circuit); merge_verification_queue.emplace_back(merge_proof); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp index 19b254f4dd5..01498dba0f7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp @@ -33,7 +33,7 @@ template class OinkRecursiveVerifier_ { std::shared_ptr instance; Builder* builder; - std::shared_ptr transcript{ nullptr }; + std::shared_ptr transcript; std::string domain_separator; // used in PG to distinguish between instances in transcript }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp index a1ad6e11b47..61f66d48212 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp @@ -79,48 +79,50 @@ template class DataBusDepot { /** * @brief Execute circuit logic to establish proper transfer of databus data between circuits * @details The databus mechanism establishes the transfer of data between two circuits (i-1 and i) in a third - * circuit (i+1) via commitment equality checks of the form [R_{i-1}] = [C_i]. In practice, circuit (i+1) is given - * access to [R_{i-1}] via the public inputs of \pi_i, and it has access to [C_i] directly from \pi_i. The - * consistency checks in circuit (i+1) are thus of the form \pi_i.public_inputs.[R_{i-1}] = \pi_i.[C_i]. This method - * peforms the two primary operations required for these checks: (1) extract commitments [R] from proofs received as - * private witnesses and propagate them to the next circuit via adding them to the public inputs. (2) Assert - * equality of commitments. + * circuit (i+1) via commitment equality checks of the form [R_{i-1}] = [C_i], where R and C represent return data + * and calldata, respectively. In practice, circuit (i+1) is given access to [R_{i-1}] via the public inputs of + * \pi_i, and it has access to [C_i] directly from \pi_i. The consistency checks in circuit (i+1) are thus of the + * form \pi_i.public_inputs.[R_{i-1}] = \pi_i.[C_i]. This method peforms the two primary operations required for + * these checks: (1) extract commitments [R] from proofs received as private witnesses and propagate them to the + * next circuit via adding them to the public inputs. (2) Assert equality of commitments. * * In Aztec private function execution, this mechanism is used as follows. Kernel circuit K_{i+1} must in general - * perform two databus consistency checks: (1) that the return_data of app circuit A_{i} was calldata to K_{i}, and - * (2) that the return_data of K_{i-1} was calldata to K_{i}. (Note that kernel circuits have two databus calldata - * columns). The relevant databus column commitments are extracted from non-accumulator verifier instances (which - * contain all witness polynomial commitments extracted from a proof in oink). + * perform two databus consistency checks: (1) that the return_data of app circuit A_{i} was secondary calldata to + * K_{i}, and (2) that the return_data of K_{i-1} was calldata to K_{i}. * - * @param instances Completed verifier instances corresponding to prover instances that have been folded + * @param commitments Witness polynomial commitments for an instance that has been accumulated + * @param public_inputs The public inputs of that instance + * @param propagation_data Data indicating what databus commitments are present on the public inputs of the instance */ void execute(WitnessCommitments& commitments, std::vector& public_inputs, DatabusPropagationData& propagation_data) { - // Is this data coming from a kernel? Only kernels can contain commitments propagated via public inputs - bool is_kernel_instance = propagation_data.is_kernel; + // Flag indicating whether the input data corresponds to a kernel instance (else, an app instance). This is + // used to indicate whether the return data commitment being propagated belongs to a kernel or an app so that it + // can be checked against the appropriate calldata commitment in a subsequent round. + bool is_kernel_data = propagation_data.is_kernel; // Assert equality between return data commitments propagated via the public inputs and the corresponding // calldata commitment - if (propagation_data.contains_app_return_data_commitment) { - ASSERT(is_kernel_instance); - // Assert equality between the app return data commitment and the kernel secondary calldata commitment + if (propagation_data.contains_app_return_data_commitment) { // public inputs contain [R]_app + ASSERT(is_kernel_data); // Only kernels should contain databus commitments in their public inputs size_t start_idx = propagation_data.app_return_data_public_input_idx; Commitment app_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); + // App return data should correspond to the secondary calldata of the subsequent kernel assert_equality_of_commitments(app_return_data, commitments.secondary_calldata); } - if (propagation_data.contains_kernel_return_data_commitment) { - ASSERT(is_kernel_instance); - // Assert equality between the previous kernel return data commitment and the kernel calldata commitment + if (propagation_data.contains_kernel_return_data_commitment) { // pub inputs contain [R]_kernel + ASSERT(is_kernel_data); // Only kernels should contain databus commitments in their public inputs size_t start_idx = propagation_data.kernel_return_data_public_input_idx; Commitment kernel_return_data = reconstruct_commitment_from_public_inputs(public_inputs, start_idx); + // Previous kernel return data should correspond to the calldata of the subsequent kernel assert_equality_of_commitments(kernel_return_data, commitments.calldata); } // Propagate the return data commitment via the public inputs mechanism - propagate_commitment_via_public_inputs(commitments.return_data, is_kernel_instance); + propagate_commitment_via_public_inputs(commitments.return_data, is_kernel_data); }; /** From 60f931fd62763205e937e0001026c8e0b34b54ca Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 18:30:36 +0000 Subject: [PATCH 06/10] more comments --- .../src/barretenberg/aztec_ivc/aztec_ivc.cpp | 4 ++++ .../honk_verifier/oink_recursive_verifier.cpp | 9 ------- .../honk_verifier/oink_recursive_verifier.hpp | 24 +++++++++++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index 52659aeb0ba..9265468bc14 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -27,6 +27,8 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // Perform folding recursive verification FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { stdlib_vkey } }; auto verifier_accum = verifier.verify_folding_proof(stdlib_proof); + + // Extract native verifier accumulator from the stdlib accum for use on the next round verifier_accumulator = std::make_shared(verifier_accum->get_value()); // Perform databus commitment consistency checks and propagate return data commitments via public inputs @@ -40,6 +42,8 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) OinkRecursiveVerifier oink{ &circuit, verifier_accum }; oink.verify_proof(stdlib_proof); verifier_accum->is_accumulator = true; // WORKTODO: using this as a synonym for "is complete" + + // Extract native verifier accumulator from the stdlib accum for use on the next round verifier_accumulator = std::make_shared(verifier_accum->get_value()); verifier_accumulator->gate_challenges = std::vector(verifier_accum->verification_key->log_circuit_size, 0); 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 2c25758b3be..2a8401d577e 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 @@ -27,21 +27,12 @@ OinkRecursiveVerifier_::OinkRecursiveVerifier_(Builder* builder, , domain_separator(std::move(domain_separator)) {} -/** - * @brief This function constructs a recursive oink verifier circuit for an oink proof. - * - */ template void OinkRecursiveVerifier_::verify_proof(OinkProof& proof) { transcript = std::make_shared(proof); verify(); } -/** - * @brief This function constructs a recursive oink verifier circuit for an oink proof assumed to be contained in the - * transcript. - * - */ template void OinkRecursiveVerifier_::verify() { using CommitmentLabels = typename Flavor::CommitmentLabels; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp index 01498dba0f7..885520bae75 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp @@ -19,16 +19,40 @@ template class OinkRecursiveVerifier_ { using WitnessCommitments = typename Flavor::WitnessCommitments; using OinkProof = std::vector; + /** + * @brief Constructs an Oink Recursive Verifier with a transcript that has been instantiated externally. + * + * @param builder + * @param instance Incomplete verifier instance to be completed during verification + * @param transcript Transcript instantiated with an Oink proof (or a proof that contains an Oink proof). + * @param domain_separator string used for differentiating instances in the transcript (PG only) + */ explicit OinkRecursiveVerifier_(Builder* builder, const std::shared_ptr& instance, std::shared_ptr transcript, std::string domain_separator = ""); + /** + * @brief Constructs an Oink Recursive Verifier + * + * @param builder + * @param instance Incomplete verifier instance to be completed during verification + * @param domain_separator string used for differentiating instances in the transcript (PG only) + */ explicit OinkRecursiveVerifier_(Builder* builder, const std::shared_ptr& instance, std::string domain_separator = ""); + /** + * @brief Constructs an oink recursive verifier circuit for an oink proof assumed to be contained in the transcript. + * + */ void verify(); + + /** + * @brief Constructs an oink recursive verifier circuit for a provided oink proof. + * + */ void verify_proof(OinkProof& proof); std::shared_ptr instance; From 5a2ab8b4ccff286e3d07dea51465b7c3a06f7bcc Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 18:37:02 +0000 Subject: [PATCH 07/10] more comments and cleanup --- barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp | 5 ++++- .../stdlib/honk_verifier/oink_recursive_verifier.hpp | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index 9265468bc14..bb6f7318c82 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -21,7 +21,7 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) switch (type) { case QUEUE_TYPE::PG: { - // Construct stdlib accumulator + // Construct stdlib verifier accumulator from the native counterpart computed on a previous round auto stdlib_verifier_accum = std::make_shared(&circuit, verifier_accumulator); // Perform folding recursive verification @@ -38,7 +38,10 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) break; } case QUEUE_TYPE::OINK: { + // Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key auto verifier_accum = std::make_shared(&circuit, stdlib_vkey); + + // Perform oink recursive verification (which completes the verifier accumulator) OinkRecursiveVerifier oink{ &circuit, verifier_accum }; oink.verify_proof(stdlib_proof); verifier_accum->is_accumulator = true; // WORKTODO: using this as a synonym for "is complete" diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp index 885520bae75..4147e6908fa 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.hpp @@ -21,6 +21,8 @@ template class OinkRecursiveVerifier_ { /** * @brief Constructs an Oink Recursive Verifier with a transcript that has been instantiated externally. + * @details Used when oink recursive verification is part of a larger protocol for which a transcript already + * exists, e.g. Honk recursive verification. * * @param builder * @param instance Incomplete verifier instance to be completed during verification From 8b8fe337f37a8873b32282f967a83c9d58a10b8d Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 19:10:51 +0000 Subject: [PATCH 08/10] remove spare WORKTODOs --- barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index bb6f7318c82..cb8f421221b 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -44,10 +44,11 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // Perform oink recursive verification (which completes the verifier accumulator) OinkRecursiveVerifier oink{ &circuit, verifier_accum }; oink.verify_proof(stdlib_proof); - verifier_accum->is_accumulator = true; // WORKTODO: using this as a synonym for "is complete" + verifier_accum->is_accumulator = true; // indicate to PG that it should not run oink on this instance // Extract native verifier accumulator from the stdlib accum for use on the next round verifier_accumulator = std::make_shared(verifier_accum->get_value()); + // Initialize the gate challenges to zero for use in first round of folding verifier_accumulator->gate_challenges = std::vector(verifier_accum->verification_key->log_circuit_size, 0); @@ -104,8 +105,8 @@ void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr oink_prover{ prover_instance }; oink_prover.prove(); - prover_instance->is_accumulator = true; // WORKTODO: using this as a synonym for "is complete" - // WORKTODO: just default init these in constructor? (same for ver instance) + prover_instance->is_accumulator = true; // indicate to PG that it should not run oink on this instance + // Initialize the gate challenges to zero for use in first round of folding prover_instance->gate_challenges = std::vector(prover_instance->proving_key.log_circuit_size, 0); fold_output.accumulator = prover_instance; // initialize the prover accum with the completed instance From 073553f9c495e6ee5bf614b31fe93f9b7188a6e7 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 19:18:53 +0000 Subject: [PATCH 09/10] couple more comment corrections --- barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp | 5 +++-- .../src/barretenberg/stdlib/primitives/databus/databus.hpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp index cb8f421221b..98c960ac125 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -14,6 +14,7 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) { circuit.databus_propagation_data.is_kernel = true; + // Peform recursive verification and databus consistency checks for each entry in the verification queue for (auto& [proof, vkey, type] : verification_queue) { // Construct stdlib verification key and proof auto stdlib_proof = bb::convert_proof_to_witness(&circuit, proof); @@ -24,7 +25,7 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // Construct stdlib verifier accumulator from the native counterpart computed on a previous round auto stdlib_verifier_accum = std::make_shared(&circuit, verifier_accumulator); - // Perform folding recursive verification + // Perform folding recursive verification to update the verifier accumulator FoldingRecursiveVerifier verifier{ &circuit, stdlib_verifier_accum, { stdlib_vkey } }; auto verifier_accum = verifier.verify_folding_proof(stdlib_proof); @@ -41,7 +42,7 @@ void AztecIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) // Construct an incomplete stdlib verifier accumulator from the corresponding stdlib verification key auto verifier_accum = std::make_shared(&circuit, stdlib_vkey); - // Perform oink recursive verification (which completes the verifier accumulator) + // Perform oink recursive verification to complete the initial verifier accumulator OinkRecursiveVerifier oink{ &circuit, verifier_accum }; oink.verify_proof(stdlib_proof); verifier_accum->is_accumulator = true; // indicate to PG that it should not run oink on this instance diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp index 61f66d48212..9b19254c174 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp @@ -92,7 +92,7 @@ template class DataBusDepot { * * @param commitments Witness polynomial commitments for an instance that has been accumulated * @param public_inputs The public inputs of that instance - * @param propagation_data Data indicating what databus commitments are present on the public inputs of the instance + * @param propagation_data Data about the presence of databus commitments on the public inputs of the instance */ void execute(WitnessCommitments& commitments, std::vector& public_inputs, From 87f411e2058ccf3dad8a008099afd725ed2ad17e Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 26 Aug 2024 21:21:34 +0000 Subject: [PATCH 10/10] const-ify and do fix some naming in response to review --- .../src/barretenberg/aztec_ivc/aztec_ivc.hpp | 6 ++--- .../stdlib/primitives/databus/databus.hpp | 26 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp index 03872223ed5..ead9390e54f 100644 --- a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp @@ -64,8 +64,8 @@ class AztecIVC { }; enum class QUEUE_TYPE { OINK, PG }; - struct FoldingVerifierInputs { - FoldProof proof; + struct RecursiveVerifierInputs { + std::vector proof; // oink or PG std::shared_ptr instance_vk; QUEUE_TYPE type; }; @@ -85,7 +85,7 @@ class AztecIVC { std::shared_ptr instance_vk; // verification key for instance to be folded // Set of pairs of {fold_proof, verification_key} to be recursively verified - std::vector verification_queue; + std::vector verification_queue; // Set of merge proofs to be recursively verified std::vector merge_verification_queue; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp index 9b19254c174..ed204d91de8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.hpp @@ -94,9 +94,9 @@ template class DataBusDepot { * @param public_inputs The public inputs of that instance * @param propagation_data Data about the presence of databus commitments on the public inputs of the instance */ - void execute(WitnessCommitments& commitments, - std::vector& public_inputs, - DatabusPropagationData& propagation_data) + void execute(const WitnessCommitments& commitments, + const std::vector& public_inputs, + const DatabusPropagationData& propagation_data) { // Flag indicating whether the input data corresponds to a kernel instance (else, an app instance). This is // used to indicate whether the return data commitment being propagated belongs to a kernel or an app so that it @@ -134,7 +134,7 @@ template class DataBusDepot { * @param commitment * @param is_kernel Indicates whether the return data being propagated is from a kernel or an app */ - void propagate_commitment_via_public_inputs(Commitment& commitment, bool is_kernel = false) + void propagate_commitment_via_public_inputs(const Commitment& commitment, bool is_kernel = false) { auto context = commitment.get_context(); @@ -161,11 +161,11 @@ template class DataBusDepot { * @param return_data_commitment_limbs_start_idx Start index for range where commitment limbs are stored * @return Commitment */ - Commitment reconstruct_commitment_from_public_inputs(const std::span public_inputs, - size_t& return_data_commitment_limbs_start_idx) + Commitment reconstruct_commitment_from_public_inputs(std::span public_inputs, + const size_t& return_data_commitment_limbs_start_idx) { // Extract from the public inputs the limbs needed reconstruct a commitment - std::span return_data_commitment_limbs{ + std::span return_data_commitment_limbs{ public_inputs.data() + return_data_commitment_limbs_start_idx, NUM_FR_LIMBS_PER_COMMITMENT }; return reconstruct_commitment_from_fr_limbs(return_data_commitment_limbs); @@ -178,10 +178,10 @@ template class DataBusDepot { * @param limbs * @return Commitment */ - Commitment reconstruct_commitment_from_fr_limbs(std::span limbs) + Commitment reconstruct_commitment_from_fr_limbs(std::span limbs) { - std::span x_limbs{ limbs.data(), NUM_FR_LIMBS_PER_FQ }; - std::span y_limbs{ limbs.data() + NUM_FR_LIMBS_PER_FQ, NUM_FR_LIMBS_PER_FQ }; + std::span x_limbs{ limbs.data(), NUM_FR_LIMBS_PER_FQ }; + std::span y_limbs{ limbs.data() + NUM_FR_LIMBS_PER_FQ, NUM_FR_LIMBS_PER_FQ }; const Fq x = reconstruct_fq_from_fr_limbs(x_limbs); const Fq y = reconstruct_fq_from_fr_limbs(y_limbs); @@ -194,7 +194,7 @@ template class DataBusDepot { * @param limbs * @return Fq */ - Fq reconstruct_fq_from_fr_limbs(std::span& limbs) + Fq reconstruct_fq_from_fr_limbs(std::span& limbs) { const Fr l0 = limbs[0]; const Fr l1 = limbs[1]; @@ -207,7 +207,7 @@ template class DataBusDepot { return Fq(l0, l1, l2, l3, /*can_overflow=*/false); } - void assert_equality_of_commitments(Commitment& P0, Commitment& P1) + void assert_equality_of_commitments(const Commitment& P0, const Commitment& P1) { if (P0.get_value() != P1.get_value()) { // debug print indicating consistency check failure info("DataBusDepot: Databus consistency check failed!"); @@ -222,7 +222,7 @@ template class DataBusDepot { * @param point A biggroup element * @return std::array */ - std::array get_witness_indices_for_commitment(Commitment& point) + std::array get_witness_indices_for_commitment(const Commitment& point) { return { point.x.binary_basis_limbs[0].element.normalize().witness_index, point.x.binary_basis_limbs[1].element.normalize().witness_index,