From 7950c3c8223fd81f24bb04866d9a9b38bc0e3e02 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 27 Nov 2023 22:45:29 +0000 Subject: [PATCH 01/23] codys baseline changes --- .../goblin/full_goblin_composer.test.cpp | 85 ++++++++++--------- .../cpp/src/barretenberg/goblin/goblin.hpp | 84 ++++++++++++++++++ 2 files changed, 130 insertions(+), 39 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/goblin/goblin.hpp diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index 09563987010..0eb3719ca72 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -1,4 +1,5 @@ #include "barretenberg/eccvm/eccvm_composer.hpp" +#include "barretenberg/goblin/goblin.hpp" #include "barretenberg/goblin/translation_evaluations.hpp" #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" @@ -8,14 +9,12 @@ #include +#pragma GCC diagnostic ignored "-Wunused-variable" + using namespace proof_system::honk; namespace test_full_goblin_composer { -namespace { -auto& engine = numeric::random::get_debug_engine(); -} - class FullGoblinComposerTests : public ::testing::Test { protected: static void SetUpTestSuite() @@ -30,9 +29,15 @@ class FullGoblinComposerTests : public ::testing::Test { using Point = Curve::AffineElement; using CommitmentKey = pcs::CommitmentKey; using OpQueue = proof_system::ECCOpQueue; + using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder; using ECCVMFlavor = flavor::ECCVM; using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; using ECCVMComposer = ECCVMComposer_; + using TranslatorFlavor = flavor::GoblinTranslator; + using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; + using TranslatorComposer = GoblinTranslatorComposer; + using TranslatorConsistencyData = barretenberg::TranslationEvaluations; + using Proof = proof_system::plonk::proof; static constexpr size_t NUM_OP_QUEUE_COLUMNS = flavor::GoblinUltra::NUM_WIRES; @@ -41,7 +46,7 @@ class FullGoblinComposerTests : public ::testing::Test { * * @param builder */ - static void generate_test_circuit(proof_system::GoblinUltraCircuitBuilder& builder) + static void generate_test_circuit(GoblinUltraBuilder& builder, [[maybe_unused]] const Proof& previous_proof = {}) { // Add some arbitrary ecc op gates for (size_t i = 0; i < 3; ++i) { @@ -104,36 +109,6 @@ class FullGoblinComposerTests : public ::testing::Test { // Store the commitment data for use by the prover of the next circuit op_queue->set_commitment_data(op_queue_commitments); } - - /** - * @brief Construct and a verify a Honk proof - * - */ - static bool construct_and_verify_honk_proof(GoblinUltraComposer& composer, - proof_system::GoblinUltraCircuitBuilder& builder) - { - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto verifier = composer.create_verifier(instance); - auto proof = prover.construct_proof(); - bool verified = verifier.verify_proof(proof); - - return verified; - } - - /** - * @brief Construct and verify a Goblin ECC op queue merge proof - * - */ - static bool construct_and_verify_merge_proof(GoblinUltraComposer& composer, std::shared_ptr& op_queue) - { - auto merge_prover = composer.create_merge_prover(op_queue); - auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); - auto merge_proof = merge_prover.construct_proof(); - bool verified = merge_verifier.verify_proof(merge_proof); - - return verified; - } }; /** @@ -150,22 +125,31 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) // Add mock data to op queue to simulate interaction with a "first" circuit perform_op_queue_interactions_for_mock_first_circuit(op_queue); + proof_system::plonk::proof previous_proof; + // Construct a series of simple Goblin circuits; generate and verify their proofs - size_t NUM_CIRCUITS = 3; + size_t NUM_CIRCUITS = 4; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { proof_system::GoblinUltraCircuitBuilder builder{ op_queue }; - generate_test_circuit(builder); + generate_test_circuit(builder, previous_proof); // The same composer is used to manage Honk and Merge prover/verifier proof_system::honk::GoblinUltraComposer composer; // Construct and verify Ultra Goblin Honk proof - bool honk_verified = construct_and_verify_honk_proof(composer, builder); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto verifier = composer.create_verifier(instance); + auto honk_proof = prover.construct_proof(); + bool honk_verified = verifier.verify_proof(honk_proof); EXPECT_TRUE(honk_verified); // Construct and verify op queue merge proof - bool merge_verified = construct_and_verify_merge_proof(composer, op_queue); + auto merge_prover = composer.create_merge_prover(op_queue); + auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this + auto merge_proof = merge_prover.construct_proof(); + bool merge_verified = merge_verifier.verify_proof(merge_proof); EXPECT_TRUE(merge_verified); } @@ -192,5 +176,28 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); EXPECT_TRUE(accumulator_construction_verified && translation_verified); } + +TEST_F(FullGoblinComposerTests, Pseudo) +{ + barretenberg::Goblin goblin; + + perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue); + + const auto folding_verifier = [](GoblinUltraBuilder& builder) { generate_test_circuit(builder); }; + + // Construct a series of simple Goblin circuits; generate and verify their proofs + size_t NUM_CIRCUITS = 4; + for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { + GoblinUltraBuilder circuit_builder{ goblin.op_queue }; + folding_verifier(/* goblin. */ circuit_builder); // WORKTODO + goblin.accumulate(circuit_builder); // merge prover done in here + } + + auto vms_verified = goblin.prove(); + bool verified = goblin.verified && vms_verified; + // bool verified = goblin.verify(proof) + EXPECT_TRUE(verified); +} + // TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. } // namespace test_full_goblin_composer diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp new file mode 100644 index 00000000000..b6c5d0d13f3 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include "barretenberg/eccvm/eccvm_composer.hpp" +#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/translator_vm/goblin_translator_composer.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +namespace barretenberg { + +class Goblin { + public: + using PartialProof = bool; + // // WORKTODO + // struct PartialProof { + // proof_system::plonk::proof ultra_proof; + // proof_system::plonk::proof merge_proof; + // }; + + using Fr = barretenberg::fr; + using Fq = barretenberg::fq; + + using Transcript = proof_system::honk::BaseTranscript; + using GoblinUltraComposer = proof_system::honk::GoblinUltraComposer; + using GoblinUltraCircuitBuilder = proof_system::GoblinUltraCircuitBuilder; + using OpQueue = proof_system::ECCOpQueue; + using ECCVMFlavor = proof_system::honk::flavor::ECCVM; + using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; + using ECCVMComposer = proof_system::honk::ECCVMComposer; + using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; + using TranslatorComposer = proof_system::honk::GoblinTranslatorComposer; + using TranslatorConsistencyData = barretenberg::TranslationEvaluations; + + std::shared_ptr op_queue = std::make_shared(); + bool verified{ true }; + + // GoblinUltraCircuitBuilder circuit_builder{op_queue}; // WORKTODO: need to remove reference-type data members + + void accumulate(GoblinUltraCircuitBuilder& circuit_builder) + { + GoblinUltraComposer composer; + auto instance = composer.create_instance(circuit_builder); + auto prover = composer.create_prover(instance); + auto verifier = composer.create_verifier(instance); + auto honk_proof = prover.construct_proof(); + verified = verified && verifier.verify_proof(honk_proof); + + // Construct and verify op queue merge proof + auto merge_prover = composer.create_merge_prover(op_queue); + auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this + auto merge_proof = merge_prover.construct_proof(); + verified = verified && merge_verifier.verify_proof(merge_proof); + + // circuit_builder = GoblinUltraCircuitBuilder(); // WORKTODO: need to remove reference-type data members + }; + + PartialProof prove() + { + // Execute the ECCVM + // TODO(https://github.com/AztecProtocol/barretenberg/issues/785) Properly initialize transcript + auto eccvm_builder = ECCVMBuilder(op_queue); + auto eccvm_composer = ECCVMComposer(); + auto eccvm_prover = eccvm_composer.create_prover(eccvm_builder); + auto eccvm_verifier = eccvm_composer.create_verifier(eccvm_builder); + auto eccvm_proof = eccvm_prover.construct_proof(); + bool eccvm_verified = eccvm_verifier.verify_proof(eccvm_proof); + + // Execute the Translator + // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge + auto batching_challenge = Fq::random_element(); + auto evaluation_input = eccvm_prover.evaluation_challenge_x; + auto translator_builder = TranslatorBuilder(batching_challenge, evaluation_input, op_queue); + auto translator_composer = TranslatorComposer(); + auto translator_prover = translator_composer.create_prover(translator_builder); + auto translator_verifier = translator_composer.create_verifier(translator_builder); + auto translator_proof = translator_prover.construct_proof(); + bool accumulator_construction_verified = translator_verifier.verify_proof(translator_proof); + bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); + + return eccvm_verified && accumulator_construction_verified && translation_verified; + }; +}; +} // namespace barretenberg \ No newline at end of file From d0314a5bcb97c75e449656e0c62cd2a00bf94b61 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 30 Nov 2023 18:04:37 +0000 Subject: [PATCH 02/23] updates to test structure; passing; no recursion --- .../goblin/full_goblin_composer.test.cpp | 71 +++++++++++++++++-- .../cpp/src/barretenberg/goblin/goblin.hpp | 26 +++++-- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index 0eb3719ca72..a795088c78c 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -38,6 +38,12 @@ class FullGoblinComposerTests : public ::testing::Test { using TranslatorComposer = GoblinTranslatorComposer; using TranslatorConsistencyData = barretenberg::TranslationEvaluations; using Proof = proof_system::plonk::proof; + using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; + + struct VerifierInput { + Proof proof; + std::shared_ptr verification_key; + }; static constexpr size_t NUM_OP_QUEUE_COLUMNS = flavor::GoblinUltra::NUM_WIRES; @@ -177,26 +183,77 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) EXPECT_TRUE(accumulator_construction_verified && translation_verified); } +/** + * @brief A full Goblin test that mimicks the basic aztec client architecture + * + */ TEST_F(FullGoblinComposerTests, Pseudo) { barretenberg::Goblin goblin; + // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still + // have to manually compute and call set_commitments since we can call prove with no prior data. perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue); - const auto folding_verifier = [](GoblinUltraBuilder& builder) { generate_test_circuit(builder); }; + // Construct an initial goblin ultra circuit + GoblinUltraBuilder initial_circuit_builder{ goblin.op_queue }; + generate_test_circuit(initial_circuit_builder); + + // Construct a proof of the initial circuit to be recursively verified + auto composer = GoblinUltraComposer(); + auto instance = composer.create_instance(initial_circuit_builder); + auto prover = composer.create_prover(instance); + auto proof = prover.construct_proof(); + auto verification_key = instance->compute_verification_key(); + VerifierInput verifier_input = { proof, verification_key }; + { // Natively verify for testing purposes only + auto verifier = composer.create_verifier(instance); + bool honk_verified = verifier.verify_proof(proof); + EXPECT_TRUE(honk_verified); + } + + // Construct a merge proof to be recursively verified + auto merge_prover = composer.create_merge_prover(goblin.op_queue); + auto merge_proof = merge_prover.construct_proof(); + { // Natively verify for testing purposes only + auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this + bool merge_verified = merge_verifier.verify_proof(merge_proof); + EXPECT_TRUE(merge_verified); + } + + // const auto folding_verifier = [](GoblinUltraBuilder& builder) { generate_test_circuit(builder); }; + + // WORKTODO: possible construct the proof of a "first" circuit here. then the first kernel has something to + // recursively verify. This resembles the actual aztec architecture which defines an initial_kernel as something + // distinct from the inner_kernel // Construct a series of simple Goblin circuits; generate and verify their proofs size_t NUM_CIRCUITS = 4; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { GoblinUltraBuilder circuit_builder{ goblin.op_queue }; - folding_verifier(/* goblin. */ circuit_builder); // WORKTODO - goblin.accumulate(circuit_builder); // merge prover done in here + + // Construct a circuit with logic resembling that of the "kernel circuit" + { + // generic operations e.g. state updates (just arith gates for now) + generate_test_circuit(circuit_builder); + + // execute recursive aggregation of previous kernel + // auto verification_key = std::make_shared(&circuit_builder, native_verification_key); + // RecursiveVerifier verifier(&circuit_builder, verification_key); + // auto pairing_points = verifier.verify_proof(prev_kernel_proof); + + // execute recursive aggregation of app circuit (ignore this for now) + + // Possibly use lambda syntax like this: folding_verifier(/* goblin. */ circuit_builder); // WORKTODO + } + // Complete kernel circuit logic by with recursive verification of merge proof then construct proof/instance + goblin.accumulate(circuit_builder); // merge prover done in here } - auto vms_verified = goblin.prove(); - bool verified = goblin.verified && vms_verified; - // bool verified = goblin.verify(proof) - EXPECT_TRUE(verified); + // auto vms_verified = goblin.prove(); + // bool verified = goblin.verified && vms_verified; + // // bool verified = goblin.verify(proof) + // EXPECT_TRUE(verified); } // TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index b6c5d0d13f3..6e06abb7487 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -37,22 +37,40 @@ class Goblin { // GoblinUltraCircuitBuilder circuit_builder{op_queue}; // WORKTODO: need to remove reference-type data members + /** + * @brief + * + * @param circuit_builder + */ void accumulate(GoblinUltraCircuitBuilder& circuit_builder) { + // Complete the "kernel" logic by recursively verifying previous merge proof + // WORKTODO: auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); + // WORKTODO: verified = verified && merge_verifier.verify_proof(merge_proof); + + // Construct proof of the "kernel" circuit GoblinUltraComposer composer; auto instance = composer.create_instance(circuit_builder); auto prover = composer.create_prover(instance); - auto verifier = composer.create_verifier(instance); auto honk_proof = prover.construct_proof(); - verified = verified && verifier.verify_proof(honk_proof); + // WORKTODO: for now, do a native verification here for good measure. + auto verifier = composer.create_verifier(instance); + bool honk_verified = verifier.verify_proof(honk_proof); + ASSERT(honk_verified); // Construct and verify op queue merge proof auto merge_prover = composer.create_merge_prover(op_queue); - auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this auto merge_proof = merge_prover.construct_proof(); - verified = verified && merge_verifier.verify_proof(merge_proof); + // WORKTODO: for now, do a native verification here for good measure. + auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); + bool merge_verified = merge_verifier.verify_proof(merge_proof); + ASSERT(merge_verified); + // WORKTODO: reset the circuit builder? Is this better than just creating a new one? // circuit_builder = GoblinUltraCircuitBuilder(); // WORKTODO: need to remove reference-type data members + + // WORKTODO: this needs to return a proof and a verification key for use by the next circuit. Make a struct for + // this? }; PartialProof prove() From 2e8ced68d00c907e66fbc75b57536b5608869abe Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 30 Nov 2023 20:38:47 +0000 Subject: [PATCH 03/23] construct recursive ver directly from native vkey --- .../flavor/goblin_ultra_recursive.hpp | 3 +- .../barretenberg/flavor/ultra_recursive.hpp | 3 +- .../honk/verifier/goblin_verifier.test.cpp | 28 +++++++++---------- .../verifier/ultra_recursive_verifier.cpp | 4 +-- .../verifier/ultra_recursive_verifier.hpp | 3 +- .../recursion/honk/verifier/verifier.test.cpp | 24 ++++++++-------- 6 files changed, 32 insertions(+), 33 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp index 691e99fdda3..343d1a35dd7 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp @@ -54,6 +54,7 @@ template class GoblinUltraRecursive_ { using Commitment = typename Curve::Element; using CommitmentHandle = typename Curve::Element; using FF = typename Curve::ScalarField; + using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; // Note(luke): Eventually this may not be needed at all using VerifierCommitmentKey = pcs::VerifierCommitmentKey; @@ -324,7 +325,7 @@ template class GoblinUltraRecursive_ { * @param builder * @param native_key Native verification key from which to extract the precomputed commitments */ - VerificationKey(CircuitBuilder* builder, auto native_key) + VerificationKey(CircuitBuilder* builder, std::shared_ptr native_key) : VerificationKey_>(native_key->circuit_size, native_key->num_public_inputs) { this->q_m = Commitment::from_witness(builder, native_key->q_m); diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp index def614604f9..6cc0628b50e 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp @@ -54,6 +54,7 @@ template class UltraRecursive_ { using Commitment = typename Curve::Element; using CommitmentHandle = typename Curve::Element; using FF = typename Curve::ScalarField; + using NativeVerificationKey = flavor::Ultra::VerificationKey; // Note(luke): Eventually this may not be needed at all using VerifierCommitmentKey = pcs::VerifierCommitmentKey; @@ -256,7 +257,7 @@ template class UltraRecursive_ { * @param builder * @param native_key Native verification key from which to extract the precomputed commitments */ - VerificationKey(CircuitBuilder* builder, auto native_key) + VerificationKey(CircuitBuilder* builder, std::shared_ptr native_key) : VerificationKey_>(native_key->circuit_size, native_key->num_public_inputs) { this->q_m = Commitment::from_witness(builder, native_key->q_m); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp index 4dbdf3bc178..12890cb4449 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp @@ -130,6 +130,7 @@ template class GoblinRecursiveVerifierTest : public testi { // Create an arbitrary inner circuit auto inner_circuit = create_inner_circuit(); + OuterBuilder outer_circuit; // Compute native verification key InnerComposer inner_composer; @@ -137,19 +138,18 @@ template class GoblinRecursiveVerifierTest : public testi auto prover = inner_composer.create_prover(instance); // A prerequisite for computing VK const auto native_verification_key = instance->compute_verification_key(); - // Instantiate the recursive verification key from the native verification key - OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); + // Instantiate the recursive verifier using the native verification key + RecursiveVerifier verifier{ &outer_circuit, native_verification_key }; // Spot check some values in the recursive VK to ensure it was constructed correctly - EXPECT_EQ(verification_key->circuit_size, native_verification_key->circuit_size); - EXPECT_EQ(verification_key->log_circuit_size, native_verification_key->log_circuit_size); - EXPECT_EQ(verification_key->num_public_inputs, native_verification_key->num_public_inputs); - EXPECT_EQ(verification_key->q_m.get_value(), native_verification_key->q_m); - EXPECT_EQ(verification_key->q_r.get_value(), native_verification_key->q_r); - EXPECT_EQ(verification_key->sigma_1.get_value(), native_verification_key->sigma_1); - EXPECT_EQ(verification_key->id_3.get_value(), native_verification_key->id_3); - EXPECT_EQ(verification_key->lagrange_ecc_op.get_value(), native_verification_key->lagrange_ecc_op); + EXPECT_EQ(verifier.key->circuit_size, native_verification_key->circuit_size); + EXPECT_EQ(verifier.key->log_circuit_size, native_verification_key->log_circuit_size); + EXPECT_EQ(verifier.key->num_public_inputs, native_verification_key->num_public_inputs); + EXPECT_EQ(verifier.key->q_m.get_value(), native_verification_key->q_m); + EXPECT_EQ(verifier.key->q_r.get_value(), native_verification_key->q_r); + EXPECT_EQ(verifier.key->sigma_1.get_value(), native_verification_key->sigma_1); + EXPECT_EQ(verifier.key->id_3.get_value(), native_verification_key->id_3); + EXPECT_EQ(verifier.key->lagrange_ecc_op.get_value(), native_verification_key->lagrange_ecc_op); } /** @@ -170,8 +170,7 @@ template class GoblinRecursiveVerifierTest : public testi // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); - RecursiveVerifier verifier(&outer_circuit, verification_key); + RecursiveVerifier verifier{ &outer_circuit, native_verification_key }; auto pairing_points = verifier.verify_proof(inner_proof); // Check the recursive verifier circuit @@ -223,8 +222,7 @@ template class GoblinRecursiveVerifierTest : public testi // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); - RecursiveVerifier verifier(&outer_circuit, verification_key); + RecursiveVerifier verifier{ &outer_circuit, native_verification_key }; verifier.verify_proof(inner_proof); // We expect the circuit check to fail due to the bad proof diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp index 6a79ecfe890..573d63d077d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp @@ -9,8 +9,8 @@ namespace proof_system::plonk::stdlib::recursion::honk { template UltraRecursiveVerifier_::UltraRecursiveVerifier_(Builder* builder, - std::shared_ptr verifier_key) - : key(verifier_key) + std::shared_ptr native_verifier_key) + : key(std::make_shared(builder, native_verifier_key)) , builder(builder) {} diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp index 0e61739e771..6a1a35abbef 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp @@ -14,11 +14,12 @@ template class UltraRecursiveVerifier_ { using Commitment = typename Flavor::Commitment; using GroupElement = typename Flavor::GroupElement; using VerificationKey = typename Flavor::VerificationKey; + using NativeVerificationKey = typename Flavor::NativeVerificationKey; using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; using Builder = typename Flavor::CircuitBuilder; using PairingPoints = std::array; - explicit UltraRecursiveVerifier_(Builder* builder, std::shared_ptr verifier_key = nullptr); + explicit UltraRecursiveVerifier_(Builder* builder, std::shared_ptr native_verifier_key); UltraRecursiveVerifier_(UltraRecursiveVerifier_&& other) = delete; UltraRecursiveVerifier_(const UltraRecursiveVerifier_& other) = delete; UltraRecursiveVerifier_& operator=(const UltraRecursiveVerifier_& other) = delete; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp index 29c5b9bd639..9178e4528f9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp @@ -122,17 +122,17 @@ template class RecursiveVerifierTest : public testing::Te auto prover = inner_composer.create_prover(instance); // A prerequisite for computing VK const auto native_verification_key = instance->compute_verification_key(); - // Instantiate the recursive verification key from the native verification key - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); + // Instantiate the recursive verifier using the native verification key + RecursiveVerifier verifier{ &outer_circuit, native_verification_key }; // Spot check some values in the recursive VK to ensure it was constructed correctly - EXPECT_EQ(verification_key->circuit_size, native_verification_key->circuit_size); - EXPECT_EQ(verification_key->log_circuit_size, native_verification_key->log_circuit_size); - EXPECT_EQ(verification_key->num_public_inputs, native_verification_key->num_public_inputs); - EXPECT_EQ(verification_key->q_m.get_value(), native_verification_key->q_m); - EXPECT_EQ(verification_key->q_r.get_value(), native_verification_key->q_r); - EXPECT_EQ(verification_key->sigma_1.get_value(), native_verification_key->sigma_1); - EXPECT_EQ(verification_key->id_3.get_value(), native_verification_key->id_3); + EXPECT_EQ(verifier.key->circuit_size, native_verification_key->circuit_size); + EXPECT_EQ(verifier.key->log_circuit_size, native_verification_key->log_circuit_size); + EXPECT_EQ(verifier.key->num_public_inputs, native_verification_key->num_public_inputs); + EXPECT_EQ(verifier.key->q_m.get_value(), native_verification_key->q_m); + EXPECT_EQ(verifier.key->q_r.get_value(), native_verification_key->q_r); + EXPECT_EQ(verifier.key->sigma_1.get_value(), native_verification_key->sigma_1); + EXPECT_EQ(verifier.key->id_3.get_value(), native_verification_key->id_3); } /** @@ -154,8 +154,7 @@ template class RecursiveVerifierTest : public testing::Te // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); - RecursiveVerifier verifier(&outer_circuit, verification_key); + RecursiveVerifier verifier{ &outer_circuit, native_verification_key }; auto pairing_points = verifier.verify_proof(inner_proof); // Check the recursive verifier circuit @@ -208,8 +207,7 @@ template class RecursiveVerifierTest : public testing::Te // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); - RecursiveVerifier verifier(&outer_circuit, verification_key); + RecursiveVerifier verifier{ &outer_circuit, native_verification_key }; verifier.verify_proof(inner_proof); // We expect the circuit check to fail due to the bad proof From 3ebd00562b4085e68b5a4528402c6be19fb7c2f4 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 30 Nov 2023 22:54:04 +0000 Subject: [PATCH 04/23] new test suite; passes with 2 layers of recusion --- .../goblin/full_goblin_composer.test.cpp | 26 +- .../goblin/full_goblin_recursion.test.cpp | 226 ++++++++++++++++++ 2 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index a795088c78c..7c4d6efee56 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -4,6 +4,7 @@ #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp" #include "barretenberg/translator_vm/goblin_translator_composer.hpp" #include "barretenberg/ultra_honk/ultra_composer.hpp" @@ -40,6 +41,9 @@ class FullGoblinComposerTests : public ::testing::Test { using Proof = proof_system::plonk::proof; using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; + using RecursiveFlavor = ::proof_system::honk::flavor::GoblinUltraRecursive_; + using RecursiveVerifier = ::proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; + struct VerifierInput { Proof proof; std::shared_ptr verification_key; @@ -205,8 +209,10 @@ TEST_F(FullGoblinComposerTests, Pseudo) auto prover = composer.create_prover(instance); auto proof = prover.construct_proof(); auto verification_key = instance->compute_verification_key(); + VerifierInput verifier_input = { proof, verification_key }; - { // Natively verify for testing purposes only + + { // Natively verify proof for testing purposes only auto verifier = composer.create_verifier(instance); bool honk_verified = verifier.verify_proof(proof); EXPECT_TRUE(honk_verified); @@ -215,7 +221,8 @@ TEST_F(FullGoblinComposerTests, Pseudo) // Construct a merge proof to be recursively verified auto merge_prover = composer.create_merge_prover(goblin.op_queue); auto merge_proof = merge_prover.construct_proof(); - { // Natively verify for testing purposes only + + { // Natively verify merge for testing purposes only auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this bool merge_verified = merge_verifier.verify_proof(merge_proof); EXPECT_TRUE(merge_verified); @@ -223,10 +230,6 @@ TEST_F(FullGoblinComposerTests, Pseudo) // const auto folding_verifier = [](GoblinUltraBuilder& builder) { generate_test_circuit(builder); }; - // WORKTODO: possible construct the proof of a "first" circuit here. then the first kernel has something to - // recursively verify. This resembles the actual aztec architecture which defines an initial_kernel as something - // distinct from the inner_kernel - // Construct a series of simple Goblin circuits; generate and verify their proofs size_t NUM_CIRCUITS = 4; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { @@ -238,14 +241,11 @@ TEST_F(FullGoblinComposerTests, Pseudo) generate_test_circuit(circuit_builder); // execute recursive aggregation of previous kernel - // auto verification_key = std::make_shared(&circuit_builder, native_verification_key); - // RecursiveVerifier verifier(&circuit_builder, verification_key); - // auto pairing_points = verifier.verify_proof(prev_kernel_proof); - - // execute recursive aggregation of app circuit (ignore this for now) - - // Possibly use lambda syntax like this: folding_verifier(/* goblin. */ circuit_builder); // WORKTODO + // RecursiveVerifier verifier{ &circuit_builder, verifier_input.verification_key }; + // auto pairing_points = verifier.verify_proof(verifier_input.proof); + // (void)pairing_points; // WORKTODO: aggregate } + // Complete kernel circuit logic by with recursive verification of merge proof then construct proof/instance goblin.accumulate(circuit_builder); // merge prover done in here } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp new file mode 100644 index 00000000000..683b183a819 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -0,0 +1,226 @@ +#include "barretenberg/eccvm/eccvm_composer.hpp" +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/translation_evaluations.hpp" +#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp" +#include "barretenberg/translator_vm/goblin_translator_composer.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" + +// using namespace proof_system::honk; + +namespace goblin_recursion_tests { + +class GoblinRecursionTests : public ::testing::Test { + protected: + static void SetUpTestSuite() + { + barretenberg::srs::init_crs_factory("../srs_db/ignition"); + barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } + + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using Fbase = Curve::BaseField; + using Point = Curve::AffineElement; + using CommitmentKey = proof_system::honk::pcs::CommitmentKey; + using OpQueue = proof_system::ECCOpQueue; + using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder; + using ECCVMFlavor = proof_system::honk::flavor::ECCVM; + using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; + using ECCVMComposer = proof_system::honk::ECCVMComposer_; + using TranslatorFlavor = proof_system::honk::flavor::GoblinTranslator; + using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; + using TranslatorComposer = proof_system::honk::GoblinTranslatorComposer; + using TranslatorConsistencyData = barretenberg::TranslationEvaluations; + using Proof = proof_system::plonk::proof; + using NativeVerificationKey = proof_system::honk::flavor::GoblinUltra::VerificationKey; + using GoblinUltraComposer = proof_system::honk::GoblinUltraComposer; + + using RecursiveFlavor = ::proof_system::honk::flavor::GoblinUltraRecursive_; + using RecursiveVerifier = ::proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; + + struct VerifierInput { + Proof proof; + std::shared_ptr verification_key; + }; + + static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; + + /** + * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates + * + * @param builder + */ + static void generate_test_circuit(GoblinUltraBuilder& builder, [[maybe_unused]] const Proof& previous_proof = {}) + { + // Add some arbitrary ecc op gates + for (size_t i = 0; i < 3; ++i) { + auto point = Point::random_element(); + auto scalar = FF::random_element(); + builder.queue_ecc_add_accum(point); + builder.queue_ecc_mul_accum(point, scalar); + } + // queues the result of the preceding ECC + builder.queue_ecc_eq(); // should be eq and reset + + // Add some conventional gates that utilize public inputs + for (size_t i = 0; i < 10; ++i) { + FF a = FF::random_element(); + FF b = FF::random_element(); + FF c = FF::random_element(); + FF d = a + b + c; + uint32_t a_idx = builder.add_public_variable(a); + uint32_t b_idx = builder.add_variable(b); + uint32_t c_idx = builder.add_variable(c); + uint32_t d_idx = builder.add_variable(d); + + builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); + } + } + + /** + * @brief Mock the interactions of a simple curcuit with the op_queue + * @details The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous + * transcript" (see issue #723). This function mocks the interactions with the op queue of a fictional "first" + * circuit. This way, when we go to generate a proof over our first "real" circuit, the transcript aggregation + * protocol can proceed nominally. The mock data is valid in the sense that it can be processed by all stages of + * Goblin as if it came from a genuine circuit. + * + * @todo WOKTODO: this is a zero commitments issue + * + * @param op_queue + */ + static void perform_op_queue_interactions_for_mock_first_circuit( + std::shared_ptr& op_queue) + { + proof_system::GoblinUltraCircuitBuilder builder{ op_queue }; + + // Add a mul accum op and an equality op + auto point = Point::one() * FF::random_element(); + auto scalar = FF::random_element(); + builder.queue_ecc_mul_accum(point, scalar); + builder.queue_ecc_eq(); + + op_queue->set_size_data(); + + // Manually compute the op queue transcript commitments (which would normally be done by the prover) + auto crs_factory_ = barretenberg::srs::get_crs_factory(); + auto commitment_key = CommitmentKey(op_queue->get_current_size(), crs_factory_); + std::array op_queue_commitments; + size_t idx = 0; + for (auto& entry : op_queue->get_aggregate_transcript()) { + op_queue_commitments[idx++] = commitment_key.commit(entry); + } + // Store the commitment data for use by the prover of the next circuit + op_queue->set_commitment_data(op_queue_commitments); + } +}; + +/** + * @brief A full Goblin test that mimicks the basic aztec client architecture + * + */ +TEST_F(GoblinRecursionTests, Pseudo) +{ + barretenberg::Goblin goblin; + + // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still + // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call + // merge prove with an previous empty aggregate transcript. + perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue); + + info("Generating initial circuit."); + + // Construct an initial goblin ultra circuit + GoblinUltraBuilder initial_circuit_builder{ goblin.op_queue }; + generate_test_circuit(initial_circuit_builder); + + info("Proving initial circuit."); + + // Construct a proof of the initial circuit to be recursively verified + auto composer = GoblinUltraComposer(); + auto instance = composer.create_instance(initial_circuit_builder); + auto prover = composer.create_prover(instance); + auto proof = prover.construct_proof(); + auto verification_key = instance->compute_verification_key(); + + VerifierInput verifier_input = { proof, verification_key }; + + { // Natively verify proof for testing purposes only + info("Verifying initial circuit."); + auto verifier = composer.create_verifier(instance); + bool honk_verified = verifier.verify_proof(proof); + EXPECT_TRUE(honk_verified); + } + + info("Constructing merge proof."); + + // Construct a merge proof to be recursively verified + auto merge_prover = composer.create_merge_prover(goblin.op_queue); + auto merge_proof = merge_prover.construct_proof(); + + { // Natively verify merge for testing purposes only + info("Verifying merge proof."); + auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this + bool merge_verified = merge_verifier.verify_proof(merge_proof); + EXPECT_TRUE(merge_verified); + } + + // const auto folding_verifier = [](GoblinUltraBuilder& builder) { generate_test_circuit(builder); }; + + // Construct a series of simple Goblin circuits; generate and verify their proofs + size_t NUM_CIRCUITS = 2; + for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { + GoblinUltraBuilder circuit_builder{ goblin.op_queue }; + + info(); + + // Construct a circuit with logic resembling that of the "kernel circuit" + { + info("Kernel circuit ", circuit_idx); + info("Adding general logic."); + // generic operations e.g. state updates (just arith gates for now) + generate_test_circuit(circuit_builder); + + info("Adding recursive aggregation logic."); + // execute recursive aggregation of previous kernel + RecursiveVerifier verifier{ &circuit_builder, verifier_input.verification_key }; + auto pairing_points = verifier.verify_proof(verifier_input.proof); + (void)pairing_points; // WORKTODO: aggregate + } + + info("Constructing proof of Kernel circuit ", circuit_idx); + + // Construct proof of the "kernel" circuit + // WORKTODO: Eventually the below block should be the contents of a method like + // "goblin.accumulate(circuit_builder)". Should the return be a VerifierInput? + { + GoblinUltraComposer composer; + auto instance = composer.create_instance(circuit_builder); + auto prover = composer.create_prover(instance); + auto honk_proof = prover.construct_proof(); + // WORKTODO: for now, do a native verification here for good measure. + info("Verifying proof of Kernel circuit ", circuit_idx); + auto verifier = composer.create_verifier(instance); + bool honk_verified = verifier.verify_proof(honk_proof); + ASSERT(honk_verified); + + verifier_input.proof = honk_proof; + verifier_input.verification_key = instance->compute_verification_key(); + } + } + + // auto vms_verified = goblin.prove(); + // bool verified = goblin.verified && vms_verified; + // // bool verified = goblin.verify(proof) + // EXPECT_TRUE(verified); +} + +// TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. +} // namespace goblin_recursion_tests From cfdbc3b0a28e642dfd3996cb5f6f17673a58edf6 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 1 Dec 2023 22:05:55 +0000 Subject: [PATCH 05/23] full test with recursion is passing through trans --- .../cpp/src/barretenberg/goblin/goblin.hpp | 44 +++-- .../stdlib/recursion/CMakeLists.txt | 2 +- .../goblin/full_goblin_recursion.test.cpp | 170 +++++++----------- 3 files changed, 97 insertions(+), 119 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 6e06abb7487..8b90189fa6a 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -18,6 +18,12 @@ class Goblin { // proof_system::plonk::proof merge_proof; // }; + struct AccumulationOutput { + using NativeVerificationKey = proof_system::honk::flavor::GoblinUltra::VerificationKey; + proof_system::plonk::proof proof; + std::shared_ptr verification_key; + }; + using Fr = barretenberg::fr; using Fq = barretenberg::fq; @@ -42,61 +48,69 @@ class Goblin { * * @param circuit_builder */ - void accumulate(GoblinUltraCircuitBuilder& circuit_builder) + AccumulationOutput accumulate(GoblinUltraCircuitBuilder& circuit_builder) { // Complete the "kernel" logic by recursively verifying previous merge proof // WORKTODO: auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO: verified = verified && merge_verifier.verify_proof(merge_proof); // Construct proof of the "kernel" circuit + info("Goblin: Constructing proof of circuit."); GoblinUltraComposer composer; auto instance = composer.create_instance(circuit_builder); auto prover = composer.create_prover(instance); auto honk_proof = prover.construct_proof(); - // WORKTODO: for now, do a native verification here for good measure. - auto verifier = composer.create_verifier(instance); - bool honk_verified = verifier.verify_proof(honk_proof); - ASSERT(honk_verified); // Construct and verify op queue merge proof + info("Goblin: Constructing merge proof."); auto merge_prover = composer.create_merge_prover(op_queue); auto merge_proof = merge_prover.construct_proof(); - // WORKTODO: for now, do a native verification here for good measure. - auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); - bool merge_verified = merge_verifier.verify_proof(merge_proof); - ASSERT(merge_verified); - // WORKTODO: reset the circuit builder? Is this better than just creating a new one? - // circuit_builder = GoblinUltraCircuitBuilder(); // WORKTODO: need to remove reference-type data members + { // DEBUG only: Native verification of kernel proof and merge proof + info("Goblin: Natively verifying circuit proof."); + auto verifier = composer.create_verifier(instance); + bool honk_verified = verifier.verify_proof(honk_proof); + ASSERT(honk_verified); + info("Goblin: Natively verifying merge proof."); + auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); + bool merge_verified = merge_verifier.verify_proof(merge_proof); + ASSERT(merge_verified); + } - // WORKTODO: this needs to return a proof and a verification key for use by the next circuit. Make a struct for - // this? + return { honk_proof, instance->compute_verification_key() }; }; PartialProof prove() { // Execute the ECCVM // TODO(https://github.com/AztecProtocol/barretenberg/issues/785) Properly initialize transcript + info("Goblin: Constucting ECCVM."); auto eccvm_builder = ECCVMBuilder(op_queue); auto eccvm_composer = ECCVMComposer(); auto eccvm_prover = eccvm_composer.create_prover(eccvm_builder); auto eccvm_verifier = eccvm_composer.create_verifier(eccvm_builder); + info("Goblin: Proving ECCVM."); auto eccvm_proof = eccvm_prover.construct_proof(); + info("Goblin: Verifying ECCVM."); bool eccvm_verified = eccvm_verifier.verify_proof(eccvm_proof); // Execute the Translator // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge + info("Goblin: Constucting Translator."); auto batching_challenge = Fq::random_element(); auto evaluation_input = eccvm_prover.evaluation_challenge_x; auto translator_builder = TranslatorBuilder(batching_challenge, evaluation_input, op_queue); auto translator_composer = TranslatorComposer(); auto translator_prover = translator_composer.create_prover(translator_builder); auto translator_verifier = translator_composer.create_verifier(translator_builder); + info("Goblin: Proving Translator."); auto translator_proof = translator_prover.construct_proof(); + info("Goblin: Verifying Translator."); bool accumulator_construction_verified = translator_verifier.verify_proof(translator_proof); - bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); + // bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); - return eccvm_verified && accumulator_construction_verified && translation_verified; + // return eccvm_verified && accumulator_construction_verified && translation_verified; + return eccvm_verified && accumulator_construction_verified; }; }; } // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt index 7ba574b2604..3b7a634c740 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(stdlib_recursion ecc proof_system stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s ultra_honk) \ No newline at end of file +barretenberg_module(stdlib_recursion ecc proof_system stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s ultra_honk eccvm translator_vm) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index 683b183a819..b69d9e4e4a0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -45,20 +45,39 @@ class GoblinRecursionTests : public ::testing::Test { using RecursiveFlavor = ::proof_system::honk::flavor::GoblinUltraRecursive_; using RecursiveVerifier = ::proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; - struct VerifierInput { - Proof proof; - std::shared_ptr verification_key; - }; + using KernelInput = Goblin::AccumulationOutput; static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; + static void construct_arithmetic_circuit(GoblinUltraBuilder& builder) + { + // Add some arithmetic gates that utilize public inputs + for (size_t i = 0; i < 10; ++i) { + FF a = FF::random_element(); + FF b = FF::random_element(); + FF c = FF::random_element(); + FF d = a + b + c; + uint32_t a_idx = builder.add_public_variable(a); + uint32_t b_idx = builder.add_variable(b); + uint32_t c_idx = builder.add_variable(c); + uint32_t d_idx = builder.add_variable(d); + + builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); + } + } + /** * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates * * @param builder */ - static void generate_test_circuit(GoblinUltraBuilder& builder, [[maybe_unused]] const Proof& previous_proof = {}) + static void construct_simple_initial_circuit(GoblinUltraBuilder& builder) { + // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still + // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call + // merge prove with an previous empty aggregate transcript. + perform_op_queue_interactions_for_mock_first_circuit(builder.op_queue); + // Add some arbitrary ecc op gates for (size_t i = 0; i < 3; ++i) { auto point = Point::random_element(); @@ -69,30 +88,18 @@ class GoblinRecursionTests : public ::testing::Test { // queues the result of the preceding ECC builder.queue_ecc_eq(); // should be eq and reset - // Add some conventional gates that utilize public inputs - for (size_t i = 0; i < 10; ++i) { - FF a = FF::random_element(); - FF b = FF::random_element(); - FF c = FF::random_element(); - FF d = a + b + c; - uint32_t a_idx = builder.add_public_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); - } + construct_arithmetic_circuit(builder); } /** * @brief Mock the interactions of a simple curcuit with the op_queue - * @details The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous - * transcript" (see issue #723). This function mocks the interactions with the op queue of a fictional "first" - * circuit. This way, when we go to generate a proof over our first "real" circuit, the transcript aggregation - * protocol can proceed nominally. The mock data is valid in the sense that it can be processed by all stages of - * Goblin as if it came from a genuine circuit. + * @todo The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous + * transcript" (see issue #723) because the corresponding commitments are zero / the point at infinity. This + * function mocks the interactions with the op queue of a fictional "first" circuit. This way, when we go to + * generate a proof over our first "real" circuit, the transcript aggregation protocol can proceed nominally. The + * mock data is valid in the sense that it can be processed by all stages of Goblin as if it came from a genuine + * circuit. * - * @todo WOKTODO: this is a zero commitments issue * * @param op_queue */ @@ -109,7 +116,7 @@ class GoblinRecursionTests : public ::testing::Test { op_queue->set_size_data(); - // Manually compute the op queue transcript commitments (which would normally be done by the prover) + // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) auto crs_factory_ = barretenberg::srs::get_crs_factory(); auto commitment_key = CommitmentKey(op_queue->get_current_size(), crs_factory_); std::array op_queue_commitments; @@ -120,6 +127,27 @@ class GoblinRecursionTests : public ::testing::Test { // Store the commitment data for use by the prover of the next circuit op_queue->set_commitment_data(op_queue_commitments); } + + /** + * @brief Construct a mock kernel circuit + * @details This circuit contains (1) some basic/arbitrary arithmetic gates, (2) a genuine recursive verification of + * the proof provided as input. It does not contain any other real kernel logic. + * + * @param builder + * @param kernel_input A proof to be recursively verified and the corresponding native verification key + */ + static void construct_mock_kernel_circuit(GoblinUltraBuilder& builder, KernelInput& kernel_input) + { + // Generic operations e.g. state updates (just arith gates for now) + info("Kernel: Adding general logic."); + construct_arithmetic_circuit(builder); + + // Execute recursive aggregation of previous kernel proof + info("Kernel: Adding recursive aggregation logic."); + RecursiveVerifier verifier{ &builder, kernel_input.verification_key }; + auto pairing_points = verifier.verify_proof(kernel_input.proof); + (void)pairing_points; // WORKTODO: aggregate + } }; /** @@ -130,95 +158,31 @@ TEST_F(GoblinRecursionTests, Pseudo) { barretenberg::Goblin goblin; - // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still - // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call - // merge prove with an previous empty aggregate transcript. - perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue); - - info("Generating initial circuit."); - - // Construct an initial goblin ultra circuit - GoblinUltraBuilder initial_circuit_builder{ goblin.op_queue }; - generate_test_circuit(initial_circuit_builder); - - info("Proving initial circuit."); - - // Construct a proof of the initial circuit to be recursively verified - auto composer = GoblinUltraComposer(); - auto instance = composer.create_instance(initial_circuit_builder); - auto prover = composer.create_prover(instance); - auto proof = prover.construct_proof(); - auto verification_key = instance->compute_verification_key(); - - VerifierInput verifier_input = { proof, verification_key }; - - { // Natively verify proof for testing purposes only - info("Verifying initial circuit."); - auto verifier = composer.create_verifier(instance); - bool honk_verified = verifier.verify_proof(proof); - EXPECT_TRUE(honk_verified); - } - - info("Constructing merge proof."); - - // Construct a merge proof to be recursively verified - auto merge_prover = composer.create_merge_prover(goblin.op_queue); - auto merge_proof = merge_prover.construct_proof(); - - { // Natively verify merge for testing purposes only - info("Verifying merge proof."); - auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this - bool merge_verified = merge_verifier.verify_proof(merge_proof); - EXPECT_TRUE(merge_verified); - } - - // const auto folding_verifier = [](GoblinUltraBuilder& builder) { generate_test_circuit(builder); }; + // Construct an initial circuit; its proof will be recursively verified by the first kernel + info("Initial circuit."); + GoblinUltraBuilder initial_circuit{ goblin.op_queue }; + construct_simple_initial_circuit(initial_circuit); + KernelInput kernel_input = goblin.accumulate(initial_circuit); // Construct a series of simple Goblin circuits; generate and verify their proofs size_t NUM_CIRCUITS = 2; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - GoblinUltraBuilder circuit_builder{ goblin.op_queue }; - - info(); // Construct a circuit with logic resembling that of the "kernel circuit" - { - info("Kernel circuit ", circuit_idx); - info("Adding general logic."); - // generic operations e.g. state updates (just arith gates for now) - generate_test_circuit(circuit_builder); - - info("Adding recursive aggregation logic."); - // execute recursive aggregation of previous kernel - RecursiveVerifier verifier{ &circuit_builder, verifier_input.verification_key }; - auto pairing_points = verifier.verify_proof(verifier_input.proof); - (void)pairing_points; // WORKTODO: aggregate - } + info("\nKernel circuit ", circuit_idx); + GoblinUltraBuilder circuit_builder{ goblin.op_queue }; + construct_mock_kernel_circuit(circuit_builder, kernel_input); - info("Constructing proof of Kernel circuit ", circuit_idx); - - // Construct proof of the "kernel" circuit - // WORKTODO: Eventually the below block should be the contents of a method like - // "goblin.accumulate(circuit_builder)". Should the return be a VerifierInput? - { - GoblinUltraComposer composer; - auto instance = composer.create_instance(circuit_builder); - auto prover = composer.create_prover(instance); - auto honk_proof = prover.construct_proof(); - // WORKTODO: for now, do a native verification here for good measure. - info("Verifying proof of Kernel circuit ", circuit_idx); - auto verifier = composer.create_verifier(instance); - bool honk_verified = verifier.verify_proof(honk_proof); - ASSERT(honk_verified); - - verifier_input.proof = honk_proof; - verifier_input.verification_key = instance->compute_verification_key(); - } + // Construct proof of the current kernel circuit to be recursively verified by the next one + kernel_input = goblin.accumulate(circuit_builder); } - // auto vms_verified = goblin.prove(); + // WORKTODO: verify the final kernel proof as part of verifying Goblin at large + + auto vms_verified = goblin.prove(); // bool verified = goblin.verified && vms_verified; // // bool verified = goblin.verify(proof) + EXPECT_TRUE(vms_verified); // EXPECT_TRUE(verified); } From 178f6460e07ef87c1295e8b824c68914dcd47dfa Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 1 Dec 2023 22:09:06 +0000 Subject: [PATCH 06/23] remove pseudo from composer tests --- .../goblin/full_goblin_composer.test.cpp | 69 ------------------- 1 file changed, 69 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index 7c4d6efee56..b17f63a3df7 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -187,74 +187,5 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) EXPECT_TRUE(accumulator_construction_verified && translation_verified); } -/** - * @brief A full Goblin test that mimicks the basic aztec client architecture - * - */ -TEST_F(FullGoblinComposerTests, Pseudo) -{ - barretenberg::Goblin goblin; - - // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still - // have to manually compute and call set_commitments since we can call prove with no prior data. - perform_op_queue_interactions_for_mock_first_circuit(goblin.op_queue); - - // Construct an initial goblin ultra circuit - GoblinUltraBuilder initial_circuit_builder{ goblin.op_queue }; - generate_test_circuit(initial_circuit_builder); - - // Construct a proof of the initial circuit to be recursively verified - auto composer = GoblinUltraComposer(); - auto instance = composer.create_instance(initial_circuit_builder); - auto prover = composer.create_prover(instance); - auto proof = prover.construct_proof(); - auto verification_key = instance->compute_verification_key(); - - VerifierInput verifier_input = { proof, verification_key }; - - { // Natively verify proof for testing purposes only - auto verifier = composer.create_verifier(instance); - bool honk_verified = verifier.verify_proof(proof); - EXPECT_TRUE(honk_verified); - } - - // Construct a merge proof to be recursively verified - auto merge_prover = composer.create_merge_prover(goblin.op_queue); - auto merge_proof = merge_prover.construct_proof(); - - { // Natively verify merge for testing purposes only - auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this - bool merge_verified = merge_verifier.verify_proof(merge_proof); - EXPECT_TRUE(merge_verified); - } - - // const auto folding_verifier = [](GoblinUltraBuilder& builder) { generate_test_circuit(builder); }; - - // Construct a series of simple Goblin circuits; generate and verify their proofs - size_t NUM_CIRCUITS = 4; - for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - GoblinUltraBuilder circuit_builder{ goblin.op_queue }; - - // Construct a circuit with logic resembling that of the "kernel circuit" - { - // generic operations e.g. state updates (just arith gates for now) - generate_test_circuit(circuit_builder); - - // execute recursive aggregation of previous kernel - // RecursiveVerifier verifier{ &circuit_builder, verifier_input.verification_key }; - // auto pairing_points = verifier.verify_proof(verifier_input.proof); - // (void)pairing_points; // WORKTODO: aggregate - } - - // Complete kernel circuit logic by with recursive verification of merge proof then construct proof/instance - goblin.accumulate(circuit_builder); // merge prover done in here - } - - // auto vms_verified = goblin.prove(); - // bool verified = goblin.verified && vms_verified; - // // bool verified = goblin.verify(proof) - // EXPECT_TRUE(verified); -} - // TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. } // namespace test_full_goblin_composer From 6ef21ac8efd989f21bd31aeb8974a2afe3b21112 Mon Sep 17 00:00:00 2001 From: codygunton Date: Mon, 4 Dec 2023 15:49:07 +0000 Subject: [PATCH 07/23] const& --- barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp | 2 +- barretenberg/cpp/src/barretenberg/goblin/goblin.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp index 5f068a5c2d4..df0ac96c120 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp @@ -251,7 +251,7 @@ template class UltraRecursive_ { * @param builder * @param native_key Native verification key from which to extract the precomputed commitments */ - VerificationKey(CircuitBuilder* builder, std::shared_ptr native_key) + VerificationKey(CircuitBuilder* builder, const std::shared_ptr& native_key) : VerificationKey_>(native_key->circuit_size, native_key->num_public_inputs) { this->q_m = Commitment::from_witness(builder, native_key->q_m); diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 8b90189fa6a..a6690847c91 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -27,7 +27,7 @@ class Goblin { using Fr = barretenberg::fr; using Fq = barretenberg::fq; - using Transcript = proof_system::honk::BaseTranscript; + using Transcript = proof_system::honk::BaseTranscript; using GoblinUltraComposer = proof_system::honk::GoblinUltraComposer; using GoblinUltraCircuitBuilder = proof_system::GoblinUltraCircuitBuilder; using OpQueue = proof_system::ECCOpQueue; @@ -77,7 +77,7 @@ class Goblin { ASSERT(merge_verified); } - return { honk_proof, instance->compute_verification_key() }; + return { honk_proof, instance->verification_key }; }; PartialProof prove() From 91f3b8cc3c367237a8595b59cf19f5ac702faeb3 Mon Sep 17 00:00:00 2001 From: codygunton Date: Mon, 4 Dec 2023 15:52:28 +0000 Subject: [PATCH 08/23] const& --- .../recursion/honk/verifier/ultra_recursive_verifier.cpp | 4 ++-- .../recursion/honk/verifier/ultra_recursive_verifier.hpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp index 785f2c8331a..6c303d15e25 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp @@ -8,8 +8,8 @@ namespace proof_system::plonk::stdlib::recursion::honk { template -UltraRecursiveVerifier_::UltraRecursiveVerifier_(Builder* builder, - std::shared_ptr native_verifier_key) +UltraRecursiveVerifier_::UltraRecursiveVerifier_( + Builder* builder, const std::shared_ptr& native_verifier_key) : key(std::make_shared(builder, native_verifier_key)) , builder(builder) {} diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp index 67b5411025b..62803746d5d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp @@ -19,7 +19,8 @@ template class UltraRecursiveVerifier_ { using Builder = typename Flavor::CircuitBuilder; using PairingPoints = std::array; - explicit UltraRecursiveVerifier_(Builder* builder, std::shared_ptr native_verifier_key); + explicit UltraRecursiveVerifier_(Builder* builder, + const std::shared_ptr& native_verifier_key); UltraRecursiveVerifier_(UltraRecursiveVerifier_&& other) = delete; UltraRecursiveVerifier_(const UltraRecursiveVerifier_& other) = delete; UltraRecursiveVerifier_& operator=(const UltraRecursiveVerifier_& other) = delete; From 466cbf0174c3c5f18d8fd5d8042a1b1f519b4997 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 4 Dec 2023 19:25:51 +0000 Subject: [PATCH 09/23] basic goblin prove and verify structure --- .../cpp/src/barretenberg/goblin/goblin.hpp | 79 +++++++++++++------ .../goblin/full_goblin_recursion.test.cpp | 5 +- 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index a6690847c91..9d3f76e1c2e 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -11,19 +11,30 @@ namespace barretenberg { class Goblin { public: + using Proof = proof_system::plonk::proof; using PartialProof = bool; - // // WORKTODO - // struct PartialProof { - // proof_system::plonk::proof ultra_proof; - // proof_system::plonk::proof merge_proof; - // }; + /** + * @brief Output of goblin::accumulate; an Ultra proof and the corresponding verification key + * + */ struct AccumulationOutput { using NativeVerificationKey = proof_system::honk::flavor::GoblinUltra::VerificationKey; - proof_system::plonk::proof proof; + Proof proof; std::shared_ptr verification_key; }; + /** + * @brief A full goblin proof + * + */ + struct GoblinProof { + Proof ultra_proof; + Proof merge_proof; + Proof eccvm_proof; + Proof translator_proof; + }; + using Fr = barretenberg::fr; using Fq = barretenberg::fq; @@ -41,8 +52,10 @@ class Goblin { std::shared_ptr op_queue = std::make_shared(); bool verified{ true }; - // GoblinUltraCircuitBuilder circuit_builder{op_queue}; // WORKTODO: need to remove reference-type data members + private: + GoblinProof proof; + public: /** * @brief * @@ -59,28 +72,28 @@ class Goblin { GoblinUltraComposer composer; auto instance = composer.create_instance(circuit_builder); auto prover = composer.create_prover(instance); - auto honk_proof = prover.construct_proof(); + proof.ultra_proof = prover.construct_proof(); // Construct and verify op queue merge proof info("Goblin: Constructing merge proof."); auto merge_prover = composer.create_merge_prover(op_queue); - auto merge_proof = merge_prover.construct_proof(); + proof.merge_proof = merge_prover.construct_proof(); { // DEBUG only: Native verification of kernel proof and merge proof info("Goblin: Natively verifying circuit proof."); auto verifier = composer.create_verifier(instance); - bool honk_verified = verifier.verify_proof(honk_proof); + bool honk_verified = verifier.verify_proof(proof.ultra_proof); ASSERT(honk_verified); info("Goblin: Natively verifying merge proof."); auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); - bool merge_verified = merge_verifier.verify_proof(merge_proof); + bool merge_verified = merge_verifier.verify_proof(proof.merge_proof); ASSERT(merge_verified); } - return { honk_proof, instance->verification_key }; + return { proof.ultra_proof, instance->verification_key }; }; - PartialProof prove() + GoblinProof prove() { // Execute the ECCVM // TODO(https://github.com/AztecProtocol/barretenberg/issues/785) Properly initialize transcript @@ -88,11 +101,9 @@ class Goblin { auto eccvm_builder = ECCVMBuilder(op_queue); auto eccvm_composer = ECCVMComposer(); auto eccvm_prover = eccvm_composer.create_prover(eccvm_builder); - auto eccvm_verifier = eccvm_composer.create_verifier(eccvm_builder); + info("Goblin: Proving ECCVM."); - auto eccvm_proof = eccvm_prover.construct_proof(); - info("Goblin: Verifying ECCVM."); - bool eccvm_verified = eccvm_verifier.verify_proof(eccvm_proof); + proof.eccvm_proof = eccvm_prover.construct_proof(); // Execute the Translator // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge @@ -102,15 +113,35 @@ class Goblin { auto translator_builder = TranslatorBuilder(batching_challenge, evaluation_input, op_queue); auto translator_composer = TranslatorComposer(); auto translator_prover = translator_composer.create_prover(translator_builder); - auto translator_verifier = translator_composer.create_verifier(translator_builder); + info("Goblin: Proving Translator."); - auto translator_proof = translator_prover.construct_proof(); - info("Goblin: Verifying Translator."); - bool accumulator_construction_verified = translator_verifier.verify_proof(translator_proof); - // bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); + proof.translator_proof = translator_prover.construct_proof(); + + { // DEBUG only native verification + auto eccvm_verifier = eccvm_composer.create_verifier(eccvm_builder); + info("Goblin: Verifying ECCVM."); + bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); + ASSERT(eccvm_verified); + + auto translator_verifier = translator_composer.create_verifier(translator_builder); + info("Goblin: Verifying Translator."); + bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); + ASSERT(accumulator_construction_verified); + // WORKTODO: This needs to be part of the verifier. evals extracted from eccvm proof? + bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); + ASSERT(translation_verified); + } - // return eccvm_verified && accumulator_construction_verified && translation_verified; - return eccvm_verified && accumulator_construction_verified; + return proof; + }; + + bool verify() + { + // Construct ultra verifier and verify ultra proof + // Construct merge verifier and verify merge proof + // Construct eccvm verifier and verify eccvm proof + // Construct translator verifier and verify translator proof + return true; }; }; } // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index b69d9e4e4a0..31a88b4abbd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -46,6 +46,7 @@ class GoblinRecursionTests : public ::testing::Test { using RecursiveVerifier = ::proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; using KernelInput = Goblin::AccumulationOutput; + using GoblinProof = barretenberg::Goblin::GoblinProof; static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; @@ -179,10 +180,10 @@ TEST_F(GoblinRecursionTests, Pseudo) // WORKTODO: verify the final kernel proof as part of verifying Goblin at large - auto vms_verified = goblin.prove(); + GoblinProof goblin_proof = goblin.prove(); // bool verified = goblin.verified && vms_verified; // // bool verified = goblin.verify(proof) - EXPECT_TRUE(vms_verified); + // EXPECT_TRUE(vms_verified); // EXPECT_TRUE(verified); } From d2db965d787dd8661f9d49459382a6a1d7b0e214 Mon Sep 17 00:00:00 2001 From: codygunton Date: Mon, 4 Dec 2023 20:31:13 +0000 Subject: [PATCH 10/23] It works! --- .../cpp/src/barretenberg/eccvm/eccvm_prover.cpp | 9 ++++++--- .../cpp/src/barretenberg/eccvm/eccvm_prover.hpp | 1 + .../cpp/src/barretenberg/eccvm/eccvm_verifier.cpp | 7 ++++--- barretenberg/cpp/src/barretenberg/goblin/goblin.hpp | 11 +++++------ .../recursion/goblin/full_goblin_recursion.test.cpp | 8 +------- .../translator_vm/goblin_translator_prover.cpp | 12 ++++++------ .../translator_vm/goblin_translator_prover.hpp | 1 + .../translator_vm/goblin_translator_verifier.cpp | 6 ++---- 8 files changed, 26 insertions(+), 29 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 16d3f3a9cfb..8a74e0aade4 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -345,7 +345,7 @@ template void ECCVMProver_::execute_transcript_cons transcript->send_to_verifier("Translation:hack_evaluation", hack.evaluate(evaluation_challenge_x)); // Get another challenge for batching the univariate claims - FF batching_challenge = transcript->get_challenge("Translation:batching_challenge"); + FF ipa_batching_challenge = transcript->get_challenge("Translation:ipa_batching_challenge"); // Collect the polynomials and evaluations to be batched RefArray univariate_polynomials{ key->transcript_op, key->transcript_Px, key->transcript_Py, @@ -359,17 +359,20 @@ template void ECCVMProver_::execute_transcript_cons for (auto [polynomial, eval] : zip_view(univariate_polynomials, univariate_evaluations)) { batched_univariate.add_scaled(polynomial, batching_scalar); batched_evaluation += eval * batching_scalar; - batching_scalar *= batching_challenge; + batching_scalar *= ipa_batching_challenge; } // Compute a proof for the batched univariate opening PCS::compute_opening_proof( commitment_key, { evaluation_challenge_x, batched_evaluation }, batched_univariate, transcript); + + // Get another challenge for batching the univariate claims + translation_batching_challenge_v = transcript->get_challenge("Translation:batching_challenge"); } template plonk::proof& ECCVMProver_::export_proof() { - proof.proof_data = transcript->proof_data; + proof.proof_data = transcript->export_proof(); return proof; } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index 39b42b89688..af6f4ec457f 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -69,6 +69,7 @@ template class ECCVMProver_ { Polynomial quotient_W; FF evaluation_challenge_x; + FF translation_batching_challenge_v; // to be rederived by the translator verifier sumcheck::SumcheckOutput sumcheck_output; pcs::gemini::ProverOutput gemini_output; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index d7f26ce7299..c7880125ace 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -253,16 +253,17 @@ template bool ECCVMVerifier_::verify_proof(const plonk transcript->template receive_from_prover("Translation:hack_evaluation") }; - FF batching_challenge = transcript->get_challenge("Translation:batching_challenge"); + // Get another challenge for batching the univariate claims + FF ipa_batching_challenge = transcript->get_challenge("Translation:ipa_batching_challenge"); // Constuct batched commitment and batched evaluation auto batched_commitment = transcript_commitments[0]; auto batched_transcript_eval = transcript_evaluations[0]; - auto batching_scalar = batching_challenge; + auto batching_scalar = ipa_batching_challenge; for (size_t idx = 1; idx < transcript_commitments.size(); ++idx) { batched_commitment = batched_commitment + transcript_commitments[idx] * batching_scalar; batched_transcript_eval += batching_scalar * transcript_evaluations[idx]; - batching_scalar *= batching_challenge; + batching_scalar *= ipa_batching_challenge; } // Construct and verify batched opening claim diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 9d3f76e1c2e..0d7f028aa59 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -12,7 +12,6 @@ namespace barretenberg { class Goblin { public: using Proof = proof_system::plonk::proof; - using PartialProof = bool; /** * @brief Output of goblin::accumulate; an Ultra proof and the corresponding verification key @@ -108,11 +107,10 @@ class Goblin { // Execute the Translator // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge info("Goblin: Constucting Translator."); - auto batching_challenge = Fq::random_element(); - auto evaluation_input = eccvm_prover.evaluation_challenge_x; - auto translator_builder = TranslatorBuilder(batching_challenge, evaluation_input, op_queue); + auto translator_builder = TranslatorBuilder( + eccvm_prover.translation_batching_challenge_v, eccvm_prover.evaluation_challenge_x, op_queue); auto translator_composer = TranslatorComposer(); - auto translator_prover = translator_composer.create_prover(translator_builder); + auto translator_prover = translator_composer.create_prover(translator_builder, eccvm_prover.transcript); info("Goblin: Proving Translator."); proof.translator_proof = translator_prover.construct_proof(); @@ -123,7 +121,8 @@ class Goblin { bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); ASSERT(eccvm_verified); - auto translator_verifier = translator_composer.create_verifier(translator_builder); + auto translator_verifier = + translator_composer.create_verifier(translator_builder, eccvm_verifier.transcript); info("Goblin: Verifying Translator."); bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); ASSERT(accumulator_construction_verified); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index 31a88b4abbd..fd03d0d0e0a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -178,13 +178,7 @@ TEST_F(GoblinRecursionTests, Pseudo) kernel_input = goblin.accumulate(circuit_builder); } - // WORKTODO: verify the final kernel proof as part of verifying Goblin at large - - GoblinProof goblin_proof = goblin.prove(); - // bool verified = goblin.verified && vms_verified; - // // bool verified = goblin.verify(proof) - // EXPECT_TRUE(vms_verified); - // EXPECT_TRUE(verified); + goblin.prove(); } // TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp index cd3e010b0d9..cc71ce7b172 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp @@ -256,13 +256,13 @@ void GoblinTranslatorProver::execute_preamble_round() const auto SHIFT = uint256_t(1) << Flavor::NUM_LIMB_BITS; const auto SHIFTx2 = uint256_t(1) << (Flavor::NUM_LIMB_BITS * 2); const auto SHIFTx3 = uint256_t(1) << (Flavor::NUM_LIMB_BITS * 3); - const auto accumulated_result = typename Flavor::BF(uint256_t(key->accumulators_binary_limbs_0[1]) + - uint256_t(key->accumulators_binary_limbs_1[1]) * SHIFT + - uint256_t(key->accumulators_binary_limbs_2[1]) * SHIFTx2 + - uint256_t(key->accumulators_binary_limbs_3[1]) * SHIFTx3); + const auto accumulated_result = + BF(uint256_t(key->accumulators_binary_limbs_0[1]) + uint256_t(key->accumulators_binary_limbs_1[1]) * SHIFT + + uint256_t(key->accumulators_binary_limbs_2[1]) * SHIFTx2 + + uint256_t(key->accumulators_binary_limbs_3[1]) * SHIFTx3); transcript->send_to_verifier("circuit_size", circuit_size); transcript->send_to_verifier("evaluation_input_x", key->evaluation_input_x); - transcript->send_to_verifier("batching_challenge_v", key->batching_challenge_v); + // transcript->send_to_verifier("batching_challenge_v", key->batching_challenge_v); transcript->send_to_verifier("accumulated_result", accumulated_result); } @@ -366,7 +366,7 @@ void GoblinTranslatorProver::execute_zeromorph_rounds() plonk::proof& GoblinTranslatorProver::export_proof() { - proof.proof_data = transcript->proof_data; + proof.proof_data = transcript->export_proof(); return proof; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp index 3a2db24407d..99bf48c490d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.hpp @@ -12,6 +12,7 @@ class GoblinTranslatorProver { using Flavor = honk::flavor::GoblinTranslator; using FF = typename Flavor::FF; + using BF = typename Flavor::BF; using Commitment = typename Flavor::Commitment; using CommitmentKey = typename Flavor::CommitmentKey; using ProvingKey = typename Flavor::ProvingKey; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp index 089c2c37451..44e736b71d5 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_verifier.cpp @@ -68,9 +68,8 @@ void GoblinTranslatorVerifier::put_translation_data_in_relation_parameters(const */ bool GoblinTranslatorVerifier::verify_proof(const plonk::proof& proof) { - transcript = std::make_shared(proof.proof_data); - - transcript = std::make_shared(proof.proof_data); + batching_challenge_v = transcript->get_challenge("Translation:batching_challenge"); + transcript->load_proof(proof.proof_data); Flavor::VerifierCommitments commitments{ key }; Flavor::CommitmentLabels commitment_labels; @@ -78,7 +77,6 @@ bool GoblinTranslatorVerifier::verify_proof(const plonk::proof& proof) // TODO(Adrian): Change the initialization of the transcript to take the VK hash? const auto circuit_size = transcript->template receive_from_prover("circuit_size"); evaluation_input_x = transcript->template receive_from_prover("evaluation_input_x"); - batching_challenge_v = transcript->template receive_from_prover("batching_challenge_v"); const BF accumulated_result = transcript->template receive_from_prover("accumulated_result"); From 385edee7677e35b4863faa14c27f13a01f360657 Mon Sep 17 00:00:00 2001 From: codygunton Date: Mon, 4 Dec 2023 21:48:06 +0000 Subject: [PATCH 11/23] VM verification split out --- .../honk_bench/benchmark_utilities.hpp | 2 +- .../src/barretenberg/eccvm/eccvm_prover.cpp | 2 +- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 2 +- .../cpp/src/barretenberg/goblin/goblin.hpp | 59 +++++++++---------- .../goblin_translator_circuit_builder.hpp | 1 + .../protogalaxy/protogalaxy_prover.hpp | 4 +- .../goblin/full_goblin_recursion.test.cpp | 2 + .../barretenberg/sumcheck/sumcheck_round.hpp | 4 +- .../barretenberg/ultra_honk/merge_prover.cpp | 2 +- .../ultra_honk/merge_verifier.cpp | 2 +- 10 files changed, 39 insertions(+), 41 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp index 6f223939a4b..0ef9fabfa0a 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp @@ -218,7 +218,7 @@ void construct_proof_with_specified_num_iterations( Composer composer; for (auto _ : state) { - // Constuct circuit and prover; don't include this part in measurement + // Construct circuit and prover; don't include this part in measurement state.PauseTiming(); auto prover = get_prover(composer, test_circuit_function, num_iterations); state.ResumeTiming(); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 8a74e0aade4..f9b9fb6ea46 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -352,7 +352,7 @@ template void ECCVMProver_::execute_transcript_cons key->transcript_z1, key->transcript_z2, hack }; std::array univariate_evaluations; - // Constuct the batched polynomial and batched evaluation + // Construct the batched polynomial and batched evaluation Polynomial batched_univariate{ key->circuit_size }; FF batched_evaluation{ 0 }; auto batching_scalar = FF(1); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index c7880125ace..76058a9c800 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -256,7 +256,7 @@ template bool ECCVMVerifier_::verify_proof(const plonk // Get another challenge for batching the univariate claims FF ipa_batching_challenge = transcript->get_challenge("Translation:ipa_batching_challenge"); - // Constuct batched commitment and batched evaluation + // Construct batched commitment and batched evaluation auto batched_commitment = transcript_commitments[0]; auto batched_transcript_eval = transcript_evaluations[0]; auto batching_scalar = ipa_batching_challenge; diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 0d7f028aa59..9a617e3a74f 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -32,6 +32,7 @@ class Goblin { Proof merge_proof; Proof eccvm_proof; Proof translator_proof; + TranslationEvaluations translation_evaluations; }; using Fr = barretenberg::fr; @@ -53,6 +54,11 @@ class Goblin { private: GoblinProof proof; + // WORKTODOD: ew + std::unique_ptr eccvm_builder; + std::unique_ptr translator_builder; + std::unique_ptr eccvm_composer; + std::unique_ptr translator_composer; public: /** @@ -92,55 +98,44 @@ class Goblin { return { proof.ultra_proof, instance->verification_key }; }; - GoblinProof prove() + void prove() { // Execute the ECCVM // TODO(https://github.com/AztecProtocol/barretenberg/issues/785) Properly initialize transcript - info("Goblin: Constucting ECCVM."); - auto eccvm_builder = ECCVMBuilder(op_queue); - auto eccvm_composer = ECCVMComposer(); - auto eccvm_prover = eccvm_composer.create_prover(eccvm_builder); + info("Goblin: Constructing ECCVM."); + eccvm_builder = std::make_unique(op_queue); + eccvm_composer = std::make_unique(); + auto eccvm_prover = eccvm_composer->create_prover(*eccvm_builder); info("Goblin: Proving ECCVM."); proof.eccvm_proof = eccvm_prover.construct_proof(); + proof.translation_evaluations = eccvm_prover.translation_evaluations; // Execute the Translator // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge - info("Goblin: Constucting Translator."); - auto translator_builder = TranslatorBuilder( + info("Goblin: Constructing Translator."); + translator_builder = std::make_unique( eccvm_prover.translation_batching_challenge_v, eccvm_prover.evaluation_challenge_x, op_queue); - auto translator_composer = TranslatorComposer(); - auto translator_prover = translator_composer.create_prover(translator_builder, eccvm_prover.transcript); + translator_composer = std::make_unique(); + auto translator_prover = translator_composer->create_prover(*translator_builder, eccvm_prover.transcript); info("Goblin: Proving Translator."); proof.translator_proof = translator_prover.construct_proof(); - - { // DEBUG only native verification - auto eccvm_verifier = eccvm_composer.create_verifier(eccvm_builder); - info("Goblin: Verifying ECCVM."); - bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); - ASSERT(eccvm_verified); - - auto translator_verifier = - translator_composer.create_verifier(translator_builder, eccvm_verifier.transcript); - info("Goblin: Verifying Translator."); - bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); - ASSERT(accumulator_construction_verified); - // WORKTODO: This needs to be part of the verifier. evals extracted from eccvm proof? - bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); - ASSERT(translation_verified); - } - - return proof; }; bool verify() { - // Construct ultra verifier and verify ultra proof - // Construct merge verifier and verify merge proof - // Construct eccvm verifier and verify eccvm proof - // Construct translator verifier and verify translator proof - return true; + // WORKTODO: do we verify Ultra & Merge here? + auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder); + info("Goblin: Verifying ECCVM."); + bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); + + auto translator_verifier = translator_composer->create_verifier(*translator_builder, eccvm_verifier.transcript); + info("Goblin: Verifying Translator."); + bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); + // WORKTODO: Make an issue about validing the translation evaluations as inputs here. + bool translation_verified = translator_verifier.verify_translation(proof.translation_evaluations); + return eccvm_verified && accumulator_construction_verified && translation_verified; }; }; } // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp index 92164873e44..9527e5283d3 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp @@ -367,6 +367,7 @@ class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase class ProtoGalaxyProver_ { num_threads = num_threads > 0 ? num_threads : 1; // ensure num threads is >= 1 size_t iterations_per_thread = common_circuit_size / num_threads; // actual iterations per thread - // Constuct univariate accumulator containers; one per thread + // Construct univariate accumulator containers; one per thread std::vector thread_univariate_accumulators(num_threads); for (auto& accum : thread_univariate_accumulators) { Utils::zero_univariates(accum); } - // Constuct extended univariates containers; one per thread + // Construct extended univariates containers; one per thread std::vector extended_univariates; extended_univariates.resize(num_threads); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index fd03d0d0e0a..3ef9cef9238 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -179,6 +179,8 @@ TEST_F(GoblinRecursionTests, Pseudo) } goblin.prove(); + bool verified = goblin.verify(); + EXPECT_TRUE(verified); } // TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index b5c366be750..7ec78a73799 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -123,13 +123,13 @@ template class SumcheckProverRound { barretenberg::thread_utils::calculate_num_threads_pow2(round_size, min_iterations_per_thread); size_t iterations_per_thread = round_size / num_threads; // actual iterations per thread - // Constuct univariate accumulator containers; one per thread + // Construct univariate accumulator containers; one per thread std::vector thread_univariate_accumulators(num_threads); for (auto& accum : thread_univariate_accumulators) { Utils::zero_univariates(accum); } - // Constuct extended edge containers; one per thread + // Construct extended edge containers; one per thread std::vector extended_edges; extended_edges.resize(num_threads); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index a27b2091f3a..671634a3073 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -94,7 +94,7 @@ template plonk::proof& MergeProver_::construct_proof() FF alpha = transcript->get_challenge("alpha"); - // Constuct batched polynomial to opened via KZG + // Construct batched polynomial to opened via KZG auto batched_polynomial = Polynomial(N); auto batched_eval = FF(0); auto alpha_pow = FF(1); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp index 1d913b342fb..c93257af7de 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp @@ -62,7 +62,7 @@ template bool MergeVerifier_::verify_proof(const plonk FF alpha = transcript->get_challenge("alpha"); - // Constuct batched commitment and evaluation from constituents + // Construct batched commitment and evaluation from constituents auto batched_commitment = opening_claims[0].commitment; auto batched_eval = opening_claims[0].opening_pair.evaluation; auto alpha_pow = alpha; From b1df3ae8831df9095dcfe7f1ebd69c879a5679f5 Mon Sep 17 00:00:00 2001 From: codygunton Date: Tue, 5 Dec 2023 15:00:09 +0000 Subject: [PATCH 12/23] Bring tests in line w/ e/o --- .../goblin/full_goblin_composer.test.cpp | 143 ++++++++---------- .../cpp/src/barretenberg/goblin/goblin.hpp | 18 +-- 2 files changed, 68 insertions(+), 93 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index b17f63a3df7..89f6acb2fdc 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -4,7 +4,6 @@ #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" -#include "barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp" #include "barretenberg/translator_vm/goblin_translator_composer.hpp" #include "barretenberg/ultra_honk/ultra_composer.hpp" @@ -12,6 +11,7 @@ #pragma GCC diagnostic ignored "-Wunused-variable" +using namespace barretenberg; using namespace proof_system::honk; namespace test_full_goblin_composer { @@ -41,23 +41,40 @@ class FullGoblinComposerTests : public ::testing::Test { using Proof = proof_system::plonk::proof; using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; - using RecursiveFlavor = ::proof_system::honk::flavor::GoblinUltraRecursive_; - using RecursiveVerifier = ::proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; + using KernelInput = Goblin::AccumulationOutput; + using GoblinProof = barretenberg::Goblin::GoblinProof; - struct VerifierInput { - Proof proof; - std::shared_ptr verification_key; - }; + static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; - static constexpr size_t NUM_OP_QUEUE_COLUMNS = flavor::GoblinUltra::NUM_WIRES; + static void construct_arithmetic_circuit(GoblinUltraBuilder& builder) + { + // Add some arithmetic gates that utilize public inputs + for (size_t i = 0; i < 10; ++i) { + FF a = FF::random_element(); + FF b = FF::random_element(); + FF c = FF::random_element(); + FF d = a + b + c; + uint32_t a_idx = builder.add_public_variable(a); + uint32_t b_idx = builder.add_variable(b); + uint32_t c_idx = builder.add_variable(c); + uint32_t d_idx = builder.add_variable(d); + + builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); + } + } /** * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates * * @param builder */ - static void generate_test_circuit(GoblinUltraBuilder& builder, [[maybe_unused]] const Proof& previous_proof = {}) + static void construct_simple_initial_circuit(GoblinUltraBuilder& builder) { + // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still + // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call + // merge prove with an previous empty aggregate transcript. + perform_op_queue_interactions_for_mock_first_circuit(builder.op_queue); + // Add some arbitrary ecc op gates for (size_t i = 0; i < 3; ++i) { auto point = Point::random_element(); @@ -68,30 +85,18 @@ class FullGoblinComposerTests : public ::testing::Test { // queues the result of the preceding ECC builder.queue_ecc_eq(); // should be eq and reset - // Add some conventional gates that utilize public inputs - for (size_t i = 0; i < 10; ++i) { - FF a = FF::random_element(); - FF b = FF::random_element(); - FF c = FF::random_element(); - FF d = a + b + c; - uint32_t a_idx = builder.add_public_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); - } + construct_arithmetic_circuit(builder); } /** * @brief Mock the interactions of a simple curcuit with the op_queue - * @details The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous - * transcript" (see issue #723). This function mocks the interactions with the op queue of a fictional "first" - * circuit. This way, when we go to generate a proof over our first "real" circuit, the transcript aggregation - * protocol can proceed nominally. The mock data is valid in the sense that it can be processed by all stages of - * Goblin as if it came from a genuine circuit. + * @todo The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous + * transcript" (see issue #723) because the corresponding commitments are zero / the point at infinity. This + * function mocks the interactions with the op queue of a fictional "first" circuit. This way, when we go to + * generate a proof over our first "real" circuit, the transcript aggregation protocol can proceed nominally. The + * mock data is valid in the sense that it can be processed by all stages of Goblin as if it came from a genuine + * circuit. * - * @todo WOKTODO: this is a zero commitments issue * * @param op_queue */ @@ -108,7 +113,7 @@ class FullGoblinComposerTests : public ::testing::Test { op_queue->set_size_data(); - // Manually compute the op queue transcript commitments (which would normally be done by the prover) + // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) auto crs_factory_ = barretenberg::srs::get_crs_factory(); auto commitment_key = CommitmentKey(op_queue->get_current_size(), crs_factory_); std::array op_queue_commitments; @@ -119,6 +124,21 @@ class FullGoblinComposerTests : public ::testing::Test { // Store the commitment data for use by the prover of the next circuit op_queue->set_commitment_data(op_queue_commitments); } + + /** + * @brief Construct a mock kernel circuit + * @details This circuit contains (1) some basic/arbitrary arithmetic gates, (2) a genuine recursive verification of + * the proof provided as input. It does not contain any other real kernel logic. + * + * @param builder + * @param kernel_input A proof to be recursively verified and the corresponding native verification key + */ + static void construct_mock_kernel_circuit(GoblinUltraBuilder& builder, [[maybe_unused]] KernelInput& kernel_input) + { + // Generic operations e.g. state updates (just arith gates for now) + info("Kernel: Adding general logic."); + construct_arithmetic_circuit(builder); + } }; /** @@ -130,61 +150,30 @@ class FullGoblinComposerTests : public ::testing::Test { */ TEST_F(FullGoblinComposerTests, SimpleCircuit) { - auto op_queue = std::make_shared(); - - // Add mock data to op queue to simulate interaction with a "first" circuit - perform_op_queue_interactions_for_mock_first_circuit(op_queue); + barretenberg::Goblin goblin; - proof_system::plonk::proof previous_proof; + // Construct an initial circuit; its proof will be recursively verified by the first kernel + info("Initial circuit."); + GoblinUltraBuilder initial_circuit{ goblin.op_queue }; + construct_simple_initial_circuit(initial_circuit); + KernelInput kernel_input = goblin.accumulate(initial_circuit); // Construct a series of simple Goblin circuits; generate and verify their proofs - size_t NUM_CIRCUITS = 4; + size_t NUM_CIRCUITS = 2; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - proof_system::GoblinUltraCircuitBuilder builder{ op_queue }; - generate_test_circuit(builder, previous_proof); - - // The same composer is used to manage Honk and Merge prover/verifier - proof_system::honk::GoblinUltraComposer composer; - - // Construct and verify Ultra Goblin Honk proof - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto verifier = composer.create_verifier(instance); - auto honk_proof = prover.construct_proof(); - bool honk_verified = verifier.verify_proof(honk_proof); - EXPECT_TRUE(honk_verified); - - // Construct and verify op queue merge proof - auto merge_prover = composer.create_merge_prover(op_queue); - auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); // WORKTODO set this - auto merge_proof = merge_prover.construct_proof(); - bool merge_verified = merge_verifier.verify_proof(merge_proof); - EXPECT_TRUE(merge_verified); + // Construct a circuit with logic resembling that of the "kernel circuit" + info("\nKernel circuit ", circuit_idx); + GoblinUltraBuilder circuit_builder{ goblin.op_queue }; + construct_mock_kernel_circuit(circuit_builder, kernel_input); + + // Construct proof of the current kernel circuit to be recursively verified by the next one + kernel_input = goblin.accumulate(circuit_builder); } - // Execute the ECCVM - // TODO(https://github.com/AztecProtocol/barretenberg/issues/785) Properly initialize transcript - auto eccvm_builder = ECCVMBuilder(op_queue); - auto eccvm_composer = ECCVMComposer(); - auto eccvm_prover = eccvm_composer.create_prover(eccvm_builder); - auto eccvm_verifier = eccvm_composer.create_verifier(eccvm_builder); - auto eccvm_proof = eccvm_prover.construct_proof(); - bool eccvm_verified = eccvm_verifier.verify_proof(eccvm_proof); - EXPECT_TRUE(eccvm_verified); - - // Execute the Translator - // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge - auto batching_challenge = Fbase::random_element(); - auto evaluation_input = eccvm_prover.evaluation_challenge_x; - proof_system::GoblinTranslatorCircuitBuilder translator_builder{ batching_challenge, evaluation_input, op_queue }; - GoblinTranslatorComposer translator_composer; - GoblinTranslatorProver translator_prover = translator_composer.create_prover(translator_builder); - GoblinTranslatorVerifier translator_verifier = translator_composer.create_verifier(translator_builder); - proof_system::plonk::proof translator_proof = translator_prover.construct_proof(); - bool accumulator_construction_verified = translator_verifier.verify_proof(translator_proof); - bool translation_verified = translator_verifier.verify_translation(eccvm_prover.translation_evaluations); - EXPECT_TRUE(accumulator_construction_verified && translation_verified); + goblin.prove(); + bool verified = goblin.verify(); + EXPECT_TRUE(verified); } // TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 9a617e3a74f..d11ca3fbd26 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -68,9 +68,8 @@ class Goblin { */ AccumulationOutput accumulate(GoblinUltraCircuitBuilder& circuit_builder) { - // Complete the "kernel" logic by recursively verifying previous merge proof - // WORKTODO: auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); - // WORKTODO: verified = verified && merge_verifier.verify_proof(merge_proof); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/797) Complete the "kernel" logic by recursively + // verifying previous merge proof // Construct proof of the "kernel" circuit info("Goblin: Constructing proof of circuit."); @@ -84,24 +83,12 @@ class Goblin { auto merge_prover = composer.create_merge_prover(op_queue); proof.merge_proof = merge_prover.construct_proof(); - { // DEBUG only: Native verification of kernel proof and merge proof - info("Goblin: Natively verifying circuit proof."); - auto verifier = composer.create_verifier(instance); - bool honk_verified = verifier.verify_proof(proof.ultra_proof); - ASSERT(honk_verified); - info("Goblin: Natively verifying merge proof."); - auto merge_verifier = composer.create_merge_verifier(/*srs_size=*/10); - bool merge_verified = merge_verifier.verify_proof(proof.merge_proof); - ASSERT(merge_verified); - } - return { proof.ultra_proof, instance->verification_key }; }; void prove() { // Execute the ECCVM - // TODO(https://github.com/AztecProtocol/barretenberg/issues/785) Properly initialize transcript info("Goblin: Constructing ECCVM."); eccvm_builder = std::make_unique(op_queue); eccvm_composer = std::make_unique(); @@ -112,7 +99,6 @@ class Goblin { proof.translation_evaluations = eccvm_prover.translation_evaluations; // Execute the Translator - // TODO(https://github.com/AztecProtocol/barretenberg/issues/786) Properly derive batching_challenge info("Goblin: Constructing Translator."); translator_builder = std::make_unique( eccvm_prover.translation_batching_challenge_v, eccvm_prover.evaluation_challenge_x, op_queue); From 4e332f45e844649b6edce146d944491e8815f9de Mon Sep 17 00:00:00 2001 From: codygunton Date: Tue, 5 Dec 2023 20:44:32 +0000 Subject: [PATCH 13/23] WIP --- .../cpp/src/barretenberg/goblin/goblin.hpp | 13 ------- .../barretenberg/transcript/transcript.hpp | 16 ++++++++- .../goblin_translator_composer.test.cpp | 34 ++++++++++++------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index d11ca3fbd26..6178b45d493 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -72,14 +72,12 @@ class Goblin { // verifying previous merge proof // Construct proof of the "kernel" circuit - info("Goblin: Constructing proof of circuit."); GoblinUltraComposer composer; auto instance = composer.create_instance(circuit_builder); auto prover = composer.create_prover(instance); proof.ultra_proof = prover.construct_proof(); // Construct and verify op queue merge proof - info("Goblin: Constructing merge proof."); auto merge_prover = composer.create_merge_prover(op_queue); proof.merge_proof = merge_prover.construct_proof(); @@ -88,36 +86,25 @@ class Goblin { void prove() { - // Execute the ECCVM - info("Goblin: Constructing ECCVM."); eccvm_builder = std::make_unique(op_queue); eccvm_composer = std::make_unique(); auto eccvm_prover = eccvm_composer->create_prover(*eccvm_builder); - - info("Goblin: Proving ECCVM."); proof.eccvm_proof = eccvm_prover.construct_proof(); proof.translation_evaluations = eccvm_prover.translation_evaluations; - // Execute the Translator - info("Goblin: Constructing Translator."); translator_builder = std::make_unique( eccvm_prover.translation_batching_challenge_v, eccvm_prover.evaluation_challenge_x, op_queue); translator_composer = std::make_unique(); auto translator_prover = translator_composer->create_prover(*translator_builder, eccvm_prover.transcript); - - info("Goblin: Proving Translator."); proof.translator_proof = translator_prover.construct_proof(); }; bool verify() { - // WORKTODO: do we verify Ultra & Merge here? auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder); - info("Goblin: Verifying ECCVM."); bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); auto translator_verifier = translator_composer->create_verifier(*translator_builder, eccvm_verifier.transcript); - info("Goblin: Verifying Translator."); bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); // WORKTODO: Make an issue about validing the translation evaluations as inputs here. bool translation_verified = translator_verifier.verify_translation(proof.translation_evaluations); diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp index 018001ec101..8b03dddf8e4 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp @@ -268,6 +268,11 @@ class BaseTranscript { auto element_bytes = to_buffer(element); proof_data.insert(proof_data.end(), element_bytes.begin(), element_bytes.end()); + if constexpr (std::same_as || std::same_as || + std::same_as) { + info("sent: ", label, ": ", element); + } + BaseTranscript::consume_prover_element_bytes(label, element_bytes); } @@ -289,6 +294,10 @@ class BaseTranscript { T element = from_buffer(element_bytes); + if constexpr (std::same_as || std::same_as || + std::same_as) { + info("received: ", label, ": ", element); + } return element; } @@ -320,7 +329,12 @@ class BaseTranscript { return verifier_transcript; }; - uint256_t get_challenge(const std::string& label) { return get_challenges(label)[0]; } + uint256_t get_challenge(const std::string& label) + { + uint256_t result = get_challenges(label)[0]; + info(label, ": ", result); + return result; + } [[nodiscard]] TranscriptManifest get_manifest() const { return manifest; }; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp index ed7c1274d5e..4a8546b75c3 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp @@ -9,6 +9,9 @@ #include using namespace proof_system::honk; +using CircuitBuilder = flavor::GoblinTranslator::CircuitBuilder; +using Transcript = flavor::GoblinTranslator::Transcript; +using OpQueue = proof_system::ECCOpQueue; namespace test_goblin_translator_composer { @@ -25,15 +28,6 @@ std::vector add_variables(auto& circuit_constructor, std::vectoradd_accumulate(P1); op_queue->mul_accumulate(P2, z); } - Fq batching_challenge = Fq::random_element(); - Fq x = Fq::random_element(); - auto circuit_builder = proof_system::GoblinTranslatorCircuitBuilder(batching_challenge, x); + + auto prover_transcript = std::make_shared(); + prover_transcript->send_to_verifier("init", Fq(1377)); + Fq translation_batching_challenge = prover_transcript->get_challenge("Translation:batching_challenge"); + Fq translation_evaluation_challenge = Fq::random_element(); + auto circuit_builder = CircuitBuilder(translation_batching_challenge, translation_evaluation_challenge, op_queue); circuit_builder.feed_ecc_op_queue_into_circuit(op_queue); EXPECT_TRUE(circuit_builder.check_circuit()); auto composer = GoblinTranslatorComposer(); - prove_and_verify(circuit_builder, composer, /*expected_result=*/true); + auto prover = composer.create_prover(circuit_builder, prover_transcript); + info("PROVER TRANSCRIPT: "); + auto proof = prover.construct_proof(); + // prover_transcript->print(); + + auto verifier_transcript = std::make_shared(); + verifier_transcript->send_to_verifier("init", Fq(1377)); + auto verifier = composer.create_verifier(circuit_builder, verifier_transcript); + info("VERIFIER TRANSCRIPT: "); + bool verified = verifier.verify_proof(proof); + // verifier_transcript->print(); + EXPECT_TRUE(verified); } } // namespace test_goblin_translator_composer From c02db5a3d882dd09b77b6b6d3e27f5dd1d42ee1a Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 05:56:28 +0000 Subject: [PATCH 14/23] Fix Translator test --- .../src/barretenberg/goblin/CMakeLists.txt | 2 +- .../barretenberg/transcript/transcript.hpp | 25 +++++++++++++------ .../goblin_translator_composer.test.cpp | 22 +++++++--------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt index 248b05c02e6..a6c3c61383a 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(goblin ultra_honk eccvm translator_vm) \ No newline at end of file +barretenberg_module(goblin ultra_honk eccvm translator_vm transcript) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp index 8b03dddf8e4..e734829460c 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp @@ -4,8 +4,16 @@ #include "barretenberg/crypto/blake3s/blake3s.hpp" #include "barretenberg/crypto/pedersen_hash/pedersen.hpp" +// #define LOG_CHALLENGES +// #define LOG_INTERACTIONS + namespace proof_system::honk { +template +concept Loggable = (std::same_as || std::same_as || + std::same_as || + std::same_as || std::same_as); + // class TranscriptManifest; class TranscriptManifest { struct RoundData { @@ -268,11 +276,11 @@ class BaseTranscript { auto element_bytes = to_buffer(element); proof_data.insert(proof_data.end(), element_bytes.begin(), element_bytes.end()); - if constexpr (std::same_as || std::same_as || - std::same_as) { - info("sent: ", label, ": ", element); +#ifdef LOG_INTERACTIONS + if constexpr (Loggable) { + info("sent: ", label, ": ", element); } - +#endif BaseTranscript::consume_prover_element_bytes(label, element_bytes); } @@ -294,10 +302,11 @@ class BaseTranscript { T element = from_buffer(element_bytes); - if constexpr (std::same_as || std::same_as || - std::same_as) { +#ifdef LOG_INTERACTIONS + if constexpr (Loggable) { info("received: ", label, ": ", element); } +#endif return element; } @@ -332,7 +341,9 @@ class BaseTranscript { uint256_t get_challenge(const std::string& label) { uint256_t result = get_challenges(label)[0]; - info(label, ": ", result); +#if defined LOG_CHALLENGES || defined LOG_INTERACTIONS + info("challenge: ", label, ": ", result); +#endif return result; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp index 4a8546b75c3..d186ebc6eb7 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_composer.test.cpp @@ -48,13 +48,13 @@ class GoblinTranslatorComposerTests : public ::testing::Test { */ TEST_F(GoblinTranslatorComposerTests, Basic) { - using point = barretenberg::g1::affine_element; - using scalar = barretenberg::fr; + using G1 = barretenberg::g1::affine_element; + using Fr = barretenberg::fr; using Fq = barretenberg::fq; - auto P1 = point::random_element(); - auto P2 = point::random_element(); - auto z = scalar::random_element(); + auto P1 = G1::random_element(); + auto P2 = G1::random_element(); + auto z = Fr::random_element(); // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); @@ -64,25 +64,21 @@ TEST_F(GoblinTranslatorComposerTests, Basic) } auto prover_transcript = std::make_shared(); - prover_transcript->send_to_verifier("init", Fq(1377)); + prover_transcript->send_to_verifier("init", Fq::random_element()); + prover_transcript->export_proof(); Fq translation_batching_challenge = prover_transcript->get_challenge("Translation:batching_challenge"); Fq translation_evaluation_challenge = Fq::random_element(); auto circuit_builder = CircuitBuilder(translation_batching_challenge, translation_evaluation_challenge, op_queue); - circuit_builder.feed_ecc_op_queue_into_circuit(op_queue); EXPECT_TRUE(circuit_builder.check_circuit()); auto composer = GoblinTranslatorComposer(); auto prover = composer.create_prover(circuit_builder, prover_transcript); - info("PROVER TRANSCRIPT: "); auto proof = prover.construct_proof(); - // prover_transcript->print(); - auto verifier_transcript = std::make_shared(); - verifier_transcript->send_to_verifier("init", Fq(1377)); + auto verifier_transcript = std::make_shared(prover_transcript->proof_data); + verifier_transcript->template receive_from_prover("init"); auto verifier = composer.create_verifier(circuit_builder, verifier_transcript); - info("VERIFIER TRANSCRIPT: "); bool verified = verifier.verify_proof(proof); - // verifier_transcript->print(); EXPECT_TRUE(verified); } From a4b5e2f06a73889596fde97f0f1fb5b85938226f Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 06:33:34 +0000 Subject: [PATCH 15/23] Share testing code --- .../goblin/full_goblin_composer.test.cpp | 99 +---------------- .../cpp/src/barretenberg/goblin/utils.hpp | 103 ++++++++++++++++++ .../goblin/full_goblin_recursion.test.cpp | 86 +-------------- 3 files changed, 109 insertions(+), 179 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/goblin/utils.hpp diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index 89f6acb2fdc..b8706b105b8 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -1,6 +1,7 @@ #include "barretenberg/eccvm/eccvm_composer.hpp" #include "barretenberg/goblin/goblin.hpp" #include "barretenberg/goblin/translation_evaluations.hpp" +#include "barretenberg/goblin/utils.hpp" #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" @@ -45,100 +46,6 @@ class FullGoblinComposerTests : public ::testing::Test { using GoblinProof = barretenberg::Goblin::GoblinProof; static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; - - static void construct_arithmetic_circuit(GoblinUltraBuilder& builder) - { - // Add some arithmetic gates that utilize public inputs - for (size_t i = 0; i < 10; ++i) { - FF a = FF::random_element(); - FF b = FF::random_element(); - FF c = FF::random_element(); - FF d = a + b + c; - uint32_t a_idx = builder.add_public_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); - } - } - - /** - * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates - * - * @param builder - */ - static void construct_simple_initial_circuit(GoblinUltraBuilder& builder) - { - // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still - // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call - // merge prove with an previous empty aggregate transcript. - perform_op_queue_interactions_for_mock_first_circuit(builder.op_queue); - - // Add some arbitrary ecc op gates - for (size_t i = 0; i < 3; ++i) { - auto point = Point::random_element(); - auto scalar = FF::random_element(); - builder.queue_ecc_add_accum(point); - builder.queue_ecc_mul_accum(point, scalar); - } - // queues the result of the preceding ECC - builder.queue_ecc_eq(); // should be eq and reset - - construct_arithmetic_circuit(builder); - } - - /** - * @brief Mock the interactions of a simple curcuit with the op_queue - * @todo The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous - * transcript" (see issue #723) because the corresponding commitments are zero / the point at infinity. This - * function mocks the interactions with the op queue of a fictional "first" circuit. This way, when we go to - * generate a proof over our first "real" circuit, the transcript aggregation protocol can proceed nominally. The - * mock data is valid in the sense that it can be processed by all stages of Goblin as if it came from a genuine - * circuit. - * - * - * @param op_queue - */ - static void perform_op_queue_interactions_for_mock_first_circuit( - std::shared_ptr& op_queue) - { - proof_system::GoblinUltraCircuitBuilder builder{ op_queue }; - - // Add a mul accum op and an equality op - auto point = Point::one() * FF::random_element(); - auto scalar = FF::random_element(); - builder.queue_ecc_mul_accum(point, scalar); - builder.queue_ecc_eq(); - - op_queue->set_size_data(); - - // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) - auto crs_factory_ = barretenberg::srs::get_crs_factory(); - auto commitment_key = CommitmentKey(op_queue->get_current_size(), crs_factory_); - std::array op_queue_commitments; - size_t idx = 0; - for (auto& entry : op_queue->get_aggregate_transcript()) { - op_queue_commitments[idx++] = commitment_key.commit(entry); - } - // Store the commitment data for use by the prover of the next circuit - op_queue->set_commitment_data(op_queue_commitments); - } - - /** - * @brief Construct a mock kernel circuit - * @details This circuit contains (1) some basic/arbitrary arithmetic gates, (2) a genuine recursive verification of - * the proof provided as input. It does not contain any other real kernel logic. - * - * @param builder - * @param kernel_input A proof to be recursively verified and the corresponding native verification key - */ - static void construct_mock_kernel_circuit(GoblinUltraBuilder& builder, [[maybe_unused]] KernelInput& kernel_input) - { - // Generic operations e.g. state updates (just arith gates for now) - info("Kernel: Adding general logic."); - construct_arithmetic_circuit(builder); - } }; /** @@ -155,7 +62,7 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) // Construct an initial circuit; its proof will be recursively verified by the first kernel info("Initial circuit."); GoblinUltraBuilder initial_circuit{ goblin.op_queue }; - construct_simple_initial_circuit(initial_circuit); + GoblinTestingUtils::construct_simple_initial_circuit(initial_circuit); KernelInput kernel_input = goblin.accumulate(initial_circuit); // Construct a series of simple Goblin circuits; generate and verify their proofs @@ -165,7 +72,7 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) // Construct a circuit with logic resembling that of the "kernel circuit" info("\nKernel circuit ", circuit_idx); GoblinUltraBuilder circuit_builder{ goblin.op_queue }; - construct_mock_kernel_circuit(circuit_builder, kernel_input); + GoblinTestingUtils::construct_arithmetic_circuit(circuit_builder); // Construct proof of the current kernel circuit to be recursively verified by the next one kernel_input = goblin.accumulate(circuit_builder); diff --git a/barretenberg/cpp/src/barretenberg/goblin/utils.hpp b/barretenberg/cpp/src/barretenberg/goblin/utils.hpp new file mode 100644 index 00000000000..a582a34dd58 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/goblin/utils.hpp @@ -0,0 +1,103 @@ +#include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/eccvm/eccvm_composer.hpp" +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/translation_evaluations.hpp" +#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/translator_vm/goblin_translator_composer.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +namespace barretenberg { +class GoblinTestingUtils { + public: + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using Fbase = Curve::BaseField; + using Point = Curve::AffineElement; + using CommitmentKey = proof_system::honk::pcs::CommitmentKey; + using OpQueue = proof_system::ECCOpQueue; + using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder; + using Flavor = proof_system::honk::flavor::GoblinUltra; + static constexpr size_t NUM_OP_QUEUE_COLUMNS = Flavor::NUM_WIRES; + + static void construct_arithmetic_circuit(GoblinUltraBuilder& builder) + { + // Add some arithmetic gates that utilize public inputs + for (size_t i = 0; i < 10; ++i) { + FF a = FF::random_element(); + FF b = FF::random_element(); + FF c = FF::random_element(); + FF d = a + b + c; + uint32_t a_idx = builder.add_public_variable(a); + uint32_t b_idx = builder.add_variable(b); + uint32_t c_idx = builder.add_variable(c); + uint32_t d_idx = builder.add_variable(d); + + builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); + } + } + + /** + * @brief Mock the interactions of a simple curcuit with the op_queue + * @todo The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous + * transcript" (see issue #723) because the corresponding commitments are zero / the point at infinity. This + * function mocks the interactions with the op queue of a fictional "first" circuit. This way, when we go to + * generate a proof over our first "real" circuit, the transcript aggregation protocol can proceed nominally. The + * mock data is valid in the sense that it can be processed by all stages of Goblin as if it came from a genuine + * circuit. + * + * + * @param op_queue + */ + static void perform_op_queue_interactions_for_mock_first_circuit( + std::shared_ptr& op_queue) + { + proof_system::GoblinUltraCircuitBuilder builder{ op_queue }; + + // Add a mul accum op and an equality op + auto point = Point::one() * FF::random_element(); + auto scalar = FF::random_element(); + builder.queue_ecc_mul_accum(point, scalar); + builder.queue_ecc_eq(); + + op_queue->set_size_data(); + + // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) + auto crs_factory_ = barretenberg::srs::get_crs_factory(); + auto commitment_key = CommitmentKey(op_queue->get_current_size(), crs_factory_); + std::array op_queue_commitments; + size_t idx = 0; + for (auto& entry : op_queue->get_aggregate_transcript()) { + op_queue_commitments[idx++] = commitment_key.commit(entry); + } + // Store the commitment data for use by the prover of the next circuit + op_queue->set_commitment_data(op_queue_commitments); + } + + /** + * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates + * + * @param builder + */ + static void construct_simple_initial_circuit(GoblinUltraBuilder& builder) + { + // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still + // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call + // merge prove with an previous empty aggregate transcript. + perform_op_queue_interactions_for_mock_first_circuit(builder.op_queue); + + // Add some arbitrary ecc op gates + for (size_t i = 0; i < 3; ++i) { + auto point = Point::random_element(); + auto scalar = FF::random_element(); + builder.queue_ecc_add_accum(point); + builder.queue_ecc_mul_accum(point, scalar); + } + // queues the result of the preceding ECC + builder.queue_ecc_eq(); // should be eq and reset + + construct_arithmetic_circuit(builder); + } +}; +} // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index 3ef9cef9238..c5b6b974cbc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -1,6 +1,7 @@ #include "barretenberg/eccvm/eccvm_composer.hpp" #include "barretenberg/goblin/goblin.hpp" #include "barretenberg/goblin/translation_evaluations.hpp" +#include "barretenberg/goblin/utils.hpp" #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" @@ -48,87 +49,6 @@ class GoblinRecursionTests : public ::testing::Test { using KernelInput = Goblin::AccumulationOutput; using GoblinProof = barretenberg::Goblin::GoblinProof; - static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; - - static void construct_arithmetic_circuit(GoblinUltraBuilder& builder) - { - // Add some arithmetic gates that utilize public inputs - for (size_t i = 0; i < 10; ++i) { - FF a = FF::random_element(); - FF b = FF::random_element(); - FF c = FF::random_element(); - FF d = a + b + c; - uint32_t a_idx = builder.add_public_variable(a); - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - - builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) }); - } - } - - /** - * @brief Generate a simple test circuit with some ECC op gates and conventional arithmetic gates - * - * @param builder - */ - static void construct_simple_initial_circuit(GoblinUltraBuilder& builder) - { - // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still - // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call - // merge prove with an previous empty aggregate transcript. - perform_op_queue_interactions_for_mock_first_circuit(builder.op_queue); - - // Add some arbitrary ecc op gates - for (size_t i = 0; i < 3; ++i) { - auto point = Point::random_element(); - auto scalar = FF::random_element(); - builder.queue_ecc_add_accum(point); - builder.queue_ecc_mul_accum(point, scalar); - } - // queues the result of the preceding ECC - builder.queue_ecc_eq(); // should be eq and reset - - construct_arithmetic_circuit(builder); - } - - /** - * @brief Mock the interactions of a simple curcuit with the op_queue - * @todo The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous - * transcript" (see issue #723) because the corresponding commitments are zero / the point at infinity. This - * function mocks the interactions with the op queue of a fictional "first" circuit. This way, when we go to - * generate a proof over our first "real" circuit, the transcript aggregation protocol can proceed nominally. The - * mock data is valid in the sense that it can be processed by all stages of Goblin as if it came from a genuine - * circuit. - * - * - * @param op_queue - */ - static void perform_op_queue_interactions_for_mock_first_circuit( - std::shared_ptr& op_queue) - { - proof_system::GoblinUltraCircuitBuilder builder{ op_queue }; - - // Add a mul accum op and an equality op - auto point = Point::one() * FF::random_element(); - auto scalar = FF::random_element(); - builder.queue_ecc_mul_accum(point, scalar); - builder.queue_ecc_eq(); - - op_queue->set_size_data(); - - // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) - auto crs_factory_ = barretenberg::srs::get_crs_factory(); - auto commitment_key = CommitmentKey(op_queue->get_current_size(), crs_factory_); - std::array op_queue_commitments; - size_t idx = 0; - for (auto& entry : op_queue->get_aggregate_transcript()) { - op_queue_commitments[idx++] = commitment_key.commit(entry); - } - // Store the commitment data for use by the prover of the next circuit - op_queue->set_commitment_data(op_queue_commitments); - } - /** * @brief Construct a mock kernel circuit * @details This circuit contains (1) some basic/arbitrary arithmetic gates, (2) a genuine recursive verification of @@ -141,7 +61,7 @@ class GoblinRecursionTests : public ::testing::Test { { // Generic operations e.g. state updates (just arith gates for now) info("Kernel: Adding general logic."); - construct_arithmetic_circuit(builder); + GoblinTestingUtils::construct_arithmetic_circuit(builder); // Execute recursive aggregation of previous kernel proof info("Kernel: Adding recursive aggregation logic."); @@ -162,7 +82,7 @@ TEST_F(GoblinRecursionTests, Pseudo) // Construct an initial circuit; its proof will be recursively verified by the first kernel info("Initial circuit."); GoblinUltraBuilder initial_circuit{ goblin.op_queue }; - construct_simple_initial_circuit(initial_circuit); + GoblinTestingUtils::construct_simple_initial_circuit(initial_circuit); KernelInput kernel_input = goblin.accumulate(initial_circuit); // Construct a series of simple Goblin circuits; generate and verify their proofs From 4f5d1ea90d070c8101ef00b4315a2ea58b7d3328 Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 06:41:16 +0000 Subject: [PATCH 16/23] Cleanup --- .../goblin/full_goblin_composer.test.cpp | 12 --------- .../goblin/full_goblin_recursion.test.cpp | 25 ++++++++----------- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index b8706b105b8..5e7e036cf10 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -10,8 +10,6 @@ #include -#pragma GCC diagnostic ignored "-Wunused-variable" - using namespace barretenberg; using namespace proof_system::honk; @@ -35,17 +33,7 @@ class FullGoblinComposerTests : public ::testing::Test { using ECCVMFlavor = flavor::ECCVM; using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; using ECCVMComposer = ECCVMComposer_; - using TranslatorFlavor = flavor::GoblinTranslator; - using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; - using TranslatorComposer = GoblinTranslatorComposer; - using TranslatorConsistencyData = barretenberg::TranslationEvaluations; - using Proof = proof_system::plonk::proof; - using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; - using KernelInput = Goblin::AccumulationOutput; - using GoblinProof = barretenberg::Goblin::GoblinProof; - - static constexpr size_t NUM_OP_QUEUE_COLUMNS = proof_system::honk::flavor::GoblinUltra::NUM_WIRES; }; /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index c5b6b974cbc..f49313d210a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -11,10 +11,7 @@ #include -#pragma GCC diagnostic ignored "-Wunused-variable" - -// using namespace proof_system::honk; - +using namespace proof_system::honk; namespace goblin_recursion_tests { class GoblinRecursionTests : public ::testing::Test { @@ -29,23 +26,21 @@ class GoblinRecursionTests : public ::testing::Test { using FF = Curve::ScalarField; using Fbase = Curve::BaseField; using Point = Curve::AffineElement; - using CommitmentKey = proof_system::honk::pcs::CommitmentKey; + using CommitmentKey = pcs::CommitmentKey; using OpQueue = proof_system::ECCOpQueue; using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder; - using ECCVMFlavor = proof_system::honk::flavor::ECCVM; + using ECCVMFlavor = flavor::ECCVM; using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; - using ECCVMComposer = proof_system::honk::ECCVMComposer_; - using TranslatorFlavor = proof_system::honk::flavor::GoblinTranslator; + using ECCVMComposer = ECCVMComposer_; + using TranslatorFlavor = flavor::GoblinTranslator; using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; - using TranslatorComposer = proof_system::honk::GoblinTranslatorComposer; + using TranslatorComposer = GoblinTranslatorComposer; using TranslatorConsistencyData = barretenberg::TranslationEvaluations; using Proof = proof_system::plonk::proof; - using NativeVerificationKey = proof_system::honk::flavor::GoblinUltra::VerificationKey; - using GoblinUltraComposer = proof_system::honk::GoblinUltraComposer; - - using RecursiveFlavor = ::proof_system::honk::flavor::GoblinUltraRecursive_; - using RecursiveVerifier = ::proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; - + using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; + using GoblinUltraComposer = GoblinUltraComposer; + using RecursiveFlavor = flavor::GoblinUltraRecursive_; + using RecursiveVerifier = proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; using KernelInput = Goblin::AccumulationOutput; using GoblinProof = barretenberg::Goblin::GoblinProof; From ba98a33d0775b311b76ba4c6cc57968a71ba0b09 Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 06:54:01 +0000 Subject: [PATCH 17/23] Cleanup --- .../goblin/full_goblin_composer.test.cpp | 4 +-- .../cpp/src/barretenberg/goblin/goblin.hpp | 27 +++++++++---------- .../goblin/full_goblin_recursion.test.cpp | 6 ++--- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index 5e7e036cf10..de6f59724ca 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -66,8 +66,8 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) kernel_input = goblin.accumulate(circuit_builder); } - goblin.prove(); - bool verified = goblin.verify(); + Goblin::Proof proof = goblin.prove(); + bool verified = goblin.verify(proof); EXPECT_TRUE(verified); } diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 6178b45d493..1b0616a5d53 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -10,16 +10,16 @@ namespace barretenberg { class Goblin { - public: - using Proof = proof_system::plonk::proof; + using HonkProof = proof_system::plonk::proof; + public: /** * @brief Output of goblin::accumulate; an Ultra proof and the corresponding verification key * */ struct AccumulationOutput { using NativeVerificationKey = proof_system::honk::flavor::GoblinUltra::VerificationKey; - Proof proof; + HonkProof proof; std::shared_ptr verification_key; }; @@ -27,11 +27,9 @@ class Goblin { * @brief A full goblin proof * */ - struct GoblinProof { - Proof ultra_proof; - Proof merge_proof; - Proof eccvm_proof; - Proof translator_proof; + struct Proof { + HonkProof eccvm_proof; + HonkProof translator_proof; TranslationEvaluations translation_evaluations; }; @@ -53,7 +51,6 @@ class Goblin { bool verified{ true }; private: - GoblinProof proof; // WORKTODOD: ew std::unique_ptr eccvm_builder; std::unique_ptr translator_builder; @@ -75,17 +72,18 @@ class Goblin { GoblinUltraComposer composer; auto instance = composer.create_instance(circuit_builder); auto prover = composer.create_prover(instance); - proof.ultra_proof = prover.construct_proof(); + auto ultra_proof = prover.construct_proof(); // Construct and verify op queue merge proof auto merge_prover = composer.create_merge_prover(op_queue); - proof.merge_proof = merge_prover.construct_proof(); + [[maybe_unused]] auto merge_proof = merge_prover.construct_proof(); - return { proof.ultra_proof, instance->verification_key }; + return { ultra_proof, instance->verification_key }; }; - void prove() + Proof prove() { + Proof proof; eccvm_builder = std::make_unique(op_queue); eccvm_composer = std::make_unique(); auto eccvm_prover = eccvm_composer->create_prover(*eccvm_builder); @@ -97,9 +95,10 @@ class Goblin { translator_composer = std::make_unique(); auto translator_prover = translator_composer->create_prover(*translator_builder, eccvm_prover.transcript); proof.translator_proof = translator_prover.construct_proof(); + return proof; }; - bool verify() + bool verify(const Proof& proof) { auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder); bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index f49313d210a..b1626f7bb3c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -42,7 +42,6 @@ class GoblinRecursionTests : public ::testing::Test { using RecursiveFlavor = flavor::GoblinUltraRecursive_; using RecursiveVerifier = proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; using KernelInput = Goblin::AccumulationOutput; - using GoblinProof = barretenberg::Goblin::GoblinProof; /** * @brief Construct a mock kernel circuit @@ -83,7 +82,6 @@ TEST_F(GoblinRecursionTests, Pseudo) // Construct a series of simple Goblin circuits; generate and verify their proofs size_t NUM_CIRCUITS = 2; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - // Construct a circuit with logic resembling that of the "kernel circuit" info("\nKernel circuit ", circuit_idx); GoblinUltraBuilder circuit_builder{ goblin.op_queue }; @@ -93,8 +91,8 @@ TEST_F(GoblinRecursionTests, Pseudo) kernel_input = goblin.accumulate(circuit_builder); } - goblin.prove(); - bool verified = goblin.verify(); + Goblin::Proof proof = goblin.prove(); + bool verified = goblin.verify(proof); EXPECT_TRUE(verified); } From 55ec02026e9b978366177be541808f2ff7d7de27 Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 07:09:35 +0000 Subject: [PATCH 18/23] Spawn todos. --- barretenberg/cpp/src/barretenberg/goblin/goblin.hpp | 5 +++-- barretenberg/cpp/src/barretenberg/goblin/utils.hpp | 4 +--- .../stdlib/recursion/goblin/full_goblin_recursion.test.cpp | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 1b0616a5d53..8202d5082a0 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -51,7 +51,7 @@ class Goblin { bool verified{ true }; private: - // WORKTODOD: ew + // TODO(https://github.com/AztecProtocol/barretenberg/issues/798) unique_ptr use is a hack std::unique_ptr eccvm_builder; std::unique_ptr translator_builder; std::unique_ptr eccvm_composer; @@ -105,7 +105,8 @@ class Goblin { auto translator_verifier = translator_composer->create_verifier(*translator_builder, eccvm_verifier.transcript); bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); - // WORKTODO: Make an issue about validing the translation evaluations as inputs here. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/799): + // Ensure translation_evaluations are passed correctly bool translation_verified = translator_verifier.verify_translation(proof.translation_evaluations); return eccvm_verified && accumulator_construction_verified && translation_verified; }; diff --git a/barretenberg/cpp/src/barretenberg/goblin/utils.hpp b/barretenberg/cpp/src/barretenberg/goblin/utils.hpp index a582a34dd58..cb12bb08c37 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/utils.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/utils.hpp @@ -82,9 +82,7 @@ class GoblinTestingUtils { */ static void construct_simple_initial_circuit(GoblinUltraBuilder& builder) { - // WORKTODO: In theory we could use the ops from the first circuit instead of these fake ops but then we'd still - // have to manually compute and call set_commitments (normally performed in the merge prover) since we can call - // merge prove with an previous empty aggregate transcript. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/800) Testing cleanup perform_op_queue_interactions_for_mock_first_circuit(builder.op_queue); // Add some arbitrary ecc op gates diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index b1626f7bb3c..5c1a149c465 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -60,8 +60,8 @@ class GoblinRecursionTests : public ::testing::Test { // Execute recursive aggregation of previous kernel proof info("Kernel: Adding recursive aggregation logic."); RecursiveVerifier verifier{ &builder, kernel_input.verification_key }; - auto pairing_points = verifier.verify_proof(kernel_input.proof); - (void)pairing_points; // WORKTODO: aggregate + // TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Aggregation + [[maybe_unused]] auto pairing_points = verifier.verify_proof(kernel_input.proof); } }; From e075d931649bf0edabee190553a296d90113519f Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 07:12:40 +0000 Subject: [PATCH 19/23] Remove comment --- .../src/barretenberg/translator_vm/goblin_translator_prover.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp index cc71ce7b172..aeaa9a2719a 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/goblin_translator_prover.cpp @@ -262,7 +262,6 @@ void GoblinTranslatorProver::execute_preamble_round() uint256_t(key->accumulators_binary_limbs_3[1]) * SHIFTx3); transcript->send_to_verifier("circuit_size", circuit_size); transcript->send_to_verifier("evaluation_input_x", key->evaluation_input_x); - // transcript->send_to_verifier("batching_challenge_v", key->batching_challenge_v); transcript->send_to_verifier("accumulated_result", accumulated_result); } From 9d9f735c5767b9cf2ff6c6441072b1b708c9dfdd Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 07:19:34 +0000 Subject: [PATCH 20/23] Remove stupid alias. --- .../stdlib/recursion/goblin/full_goblin_recursion.test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index 5c1a149c465..d871cd3c2b3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -38,7 +38,6 @@ class GoblinRecursionTests : public ::testing::Test { using TranslatorConsistencyData = barretenberg::TranslationEvaluations; using Proof = proof_system::plonk::proof; using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; - using GoblinUltraComposer = GoblinUltraComposer; using RecursiveFlavor = flavor::GoblinUltraRecursive_; using RecursiveVerifier = proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; using KernelInput = Goblin::AccumulationOutput; From c90e3bf26f6db5c089cc9b299df71d471c667796 Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 15:48:04 +0000 Subject: [PATCH 21/23] Adjust comments per review. --- .../src/barretenberg/goblin/full_goblin_composer.test.cpp | 8 -------- barretenberg/cpp/src/barretenberg/goblin/goblin.hpp | 8 -------- .../recursion/goblin/full_goblin_recursion.test.cpp | 4 ---- 3 files changed, 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index de6f59724ca..13432046202 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -46,9 +46,6 @@ class FullGoblinComposerTests : public ::testing::Test { TEST_F(FullGoblinComposerTests, SimpleCircuit) { barretenberg::Goblin goblin; - - // Construct an initial circuit; its proof will be recursively verified by the first kernel - info("Initial circuit."); GoblinUltraBuilder initial_circuit{ goblin.op_queue }; GoblinTestingUtils::construct_simple_initial_circuit(initial_circuit); KernelInput kernel_input = goblin.accumulate(initial_circuit); @@ -56,13 +53,8 @@ TEST_F(FullGoblinComposerTests, SimpleCircuit) // Construct a series of simple Goblin circuits; generate and verify their proofs size_t NUM_CIRCUITS = 2; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - - // Construct a circuit with logic resembling that of the "kernel circuit" - info("\nKernel circuit ", circuit_idx); GoblinUltraBuilder circuit_builder{ goblin.op_queue }; GoblinTestingUtils::construct_arithmetic_circuit(circuit_builder); - - // Construct proof of the current kernel circuit to be recursively verified by the next one kernel_input = goblin.accumulate(circuit_builder); } diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 8202d5082a0..315b66657f3 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -23,10 +23,6 @@ class Goblin { std::shared_ptr verification_key; }; - /** - * @brief A full goblin proof - * - */ struct Proof { HonkProof eccvm_proof; HonkProof translator_proof; @@ -45,10 +41,8 @@ class Goblin { using ECCVMComposer = proof_system::honk::ECCVMComposer; using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; using TranslatorComposer = proof_system::honk::GoblinTranslatorComposer; - using TranslatorConsistencyData = barretenberg::TranslationEvaluations; std::shared_ptr op_queue = std::make_shared(); - bool verified{ true }; private: // TODO(https://github.com/AztecProtocol/barretenberg/issues/798) unique_ptr use is a hack @@ -68,13 +62,11 @@ class Goblin { // TODO(https://github.com/AztecProtocol/barretenberg/issues/797) Complete the "kernel" logic by recursively // verifying previous merge proof - // Construct proof of the "kernel" circuit GoblinUltraComposer composer; auto instance = composer.create_instance(circuit_builder); auto prover = composer.create_prover(instance); auto ultra_proof = prover.construct_proof(); - // Construct and verify op queue merge proof auto merge_prover = composer.create_merge_prover(op_queue); [[maybe_unused]] auto merge_proof = merge_prover.construct_proof(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index d871cd3c2b3..3d4dcaf7863 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -53,11 +53,9 @@ class GoblinRecursionTests : public ::testing::Test { static void construct_mock_kernel_circuit(GoblinUltraBuilder& builder, KernelInput& kernel_input) { // Generic operations e.g. state updates (just arith gates for now) - info("Kernel: Adding general logic."); GoblinTestingUtils::construct_arithmetic_circuit(builder); // Execute recursive aggregation of previous kernel proof - info("Kernel: Adding recursive aggregation logic."); RecursiveVerifier verifier{ &builder, kernel_input.verification_key }; // TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Aggregation [[maybe_unused]] auto pairing_points = verifier.verify_proof(kernel_input.proof); @@ -73,7 +71,6 @@ TEST_F(GoblinRecursionTests, Pseudo) barretenberg::Goblin goblin; // Construct an initial circuit; its proof will be recursively verified by the first kernel - info("Initial circuit."); GoblinUltraBuilder initial_circuit{ goblin.op_queue }; GoblinTestingUtils::construct_simple_initial_circuit(initial_circuit); KernelInput kernel_input = goblin.accumulate(initial_circuit); @@ -82,7 +79,6 @@ TEST_F(GoblinRecursionTests, Pseudo) size_t NUM_CIRCUITS = 2; for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { // Construct a circuit with logic resembling that of the "kernel circuit" - info("\nKernel circuit ", circuit_idx); GoblinUltraBuilder circuit_builder{ goblin.op_queue }; construct_mock_kernel_circuit(circuit_builder, kernel_input); From 60d7f562909557e52ca87a3dc2e9ee819a9bdc60 Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 16:36:56 +0000 Subject: [PATCH 22/23] Better modeling of kernel --- .../stdlib/recursion/goblin/full_goblin_recursion.test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index 3d4dcaf7863..67ec62eeb62 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -58,7 +58,8 @@ class GoblinRecursionTests : public ::testing::Test { // Execute recursive aggregation of previous kernel proof RecursiveVerifier verifier{ &builder, kernel_input.verification_key }; // TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Aggregation - [[maybe_unused]] auto pairing_points = verifier.verify_proof(kernel_input.proof); + auto pairing_points = verifier.verify_proof(kernel_input.proof); // app function proof + pairing_points = verifier.verify_proof(kernel_input.proof); // previous kernel proof } }; From 791ff7d84c2c72b924902244701fddedd988e950 Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 6 Dec 2023 16:43:11 +0000 Subject: [PATCH 23/23] Rename utils.hpp --- .../cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp | 2 +- .../src/barretenberg/goblin/{utils.hpp => mock_circuits.hpp} | 0 .../stdlib/recursion/goblin/full_goblin_recursion.test.cpp | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename barretenberg/cpp/src/barretenberg/goblin/{utils.hpp => mock_circuits.hpp} (100%) diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp index 13432046202..7503307881a 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp @@ -1,7 +1,7 @@ #include "barretenberg/eccvm/eccvm_composer.hpp" #include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/goblin/translation_evaluations.hpp" -#include "barretenberg/goblin/utils.hpp" #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" diff --git a/barretenberg/cpp/src/barretenberg/goblin/utils.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp similarity index 100% rename from barretenberg/cpp/src/barretenberg/goblin/utils.hpp rename to barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp index 67ec62eeb62..51d9f1943cb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp @@ -1,7 +1,7 @@ #include "barretenberg/eccvm/eccvm_composer.hpp" #include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/goblin/translation_evaluations.hpp" -#include "barretenberg/goblin/utils.hpp" #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp"