From 8009652e877be48a9ef16c1729ecc7e781eab82e Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 20 May 2024 13:57:23 +0000 Subject: [PATCH 01/24] WiP fails to verify with any recursive verifier --- .../flows/fold_and_verify_program.sh | 6 ++ ...ve_and_verify_goblin_ultra_honk_program.sh | 6 ++ barretenberg/acir_tests/run_acir_tests.sh | 5 +- barretenberg/cpp/src/CMakeLists.txt | 1 + barretenberg/cpp/src/barretenberg/bb/main.cpp | 71 +++++++++++++++++++ .../barretenberg/client_ivc/client_ivc.cpp | 7 ++ .../client_ivc/client_ivc.test.cpp | 45 +++++++++++- .../dsl/acir_format/acir_format.cpp | 7 +- .../dsl/acir_format/acir_format.hpp | 3 +- 9 files changed, 144 insertions(+), 7 deletions(-) create mode 100755 barretenberg/acir_tests/flows/fold_and_verify_program.sh create mode 100755 barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh diff --git a/barretenberg/acir_tests/flows/fold_and_verify_program.sh b/barretenberg/acir_tests/flows/fold_and_verify_program.sh new file mode 100755 index 000000000000..870873befcdd --- /dev/null +++ b/barretenberg/acir_tests/flows/fold_and_verify_program.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +VFLAG=${VERBOSE:+-v} + +$BIN fold_and_verify_program $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh b/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh new file mode 100755 index 000000000000..c34d2e545298 --- /dev/null +++ b/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +VFLAG=${VERBOSE:+-v} + +$BIN prove_and_verify_goblin_ultra_honk_program $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 0e360a895514..677c86fe01d9 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -11,7 +11,10 @@ source ./bash_helpers/catch.sh trap handle_sigchild SIGCHLD BIN=${BIN:-../cpp/build/bin/bb} -FLOW=${FLOW:-prove_and_verify} +# FLOW=${FLOW:-prove_and_verify} +# FLOW=${FLOW:-prove_and_verify_ultra_honk_program} +# FLOW=${FLOW:-prove_and_verify_goblin_ultra_honk_program} +FLOW=${FLOW:-fold_and_verify_program} CRS_PATH=~/.bb-crs BRANCH=master VERBOSE=${VERBOSE:-} diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index a9809f12c616..5686dc80654c 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -102,6 +102,7 @@ include(GNUInstallDirs) message(STATUS "Compiling all-in-one barretenberg archive") set(BARRETENBERG_TARGET_OBJECTS + $ $ $ $ diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index f8308b5e7c07..32147b60f3c3 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -1,4 +1,5 @@ #include "barretenberg/bb/file_io.hpp" +#include "barretenberg/client_ivc/client_ivc.hpp" #include "barretenberg/common/serialize.hpp" #include "barretenberg/dsl/acir_format/acir_format.hpp" #include "barretenberg/dsl/types.hpp" @@ -208,6 +209,8 @@ bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::strin auto constraint_systems = get_constraint_systems(bytecodePath); auto witness_stack = get_witness_stack(witnessPath); + info("stack depth = ", witness_stack.size()); + while (!witness_stack.empty()) { auto witness_stack_item = witness_stack.back(); auto witness = witness_stack_item.second; @@ -221,6 +224,68 @@ bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::strin return true; } +bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& witnessPath) +{ + using Flavor = GoblinUltraFlavor; // This is the only option + using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = Flavor::VerificationKey; + + init_bn254_crs(1 << 17); + init_grumpkin_crs(1 << 10); + + ClientIVC ivc; + // ivc.structured_flag = true; + auto op_queue = ivc.goblin.op_queue; + + auto constraint_systems = get_constraint_systems(bytecodePath); + auto witness_stack = get_witness_stack(witnessPath); + + info("stack depth = ", witness_stack.size()); + + while (!witness_stack.empty()) { + auto witness_stack_item = witness_stack.back(); + auto witness = witness_stack_item.second; + auto constraint_system = constraint_systems[witness_stack_item.first]; + + bool verified = true; + { + // Construct a bberg circuit from the acir representation + auto builder = acir_format::create_circuit(constraint_system, 0, witness, false, op_queue); + + ivc.accumulate(builder); + + builder.blocks.summarize(); + + // Construct Honk proof + Prover prover{ ivc.prover_instance }; + // Prover prover{ builder }; + info("gates = ", builder.get_num_gates()); + info("circuit size = ", prover.instance->proving_key.circuit_size); + auto proof = prover.construct_proof(); + + // Verify Honk proof + auto verification_key = std::make_shared(prover.instance->proving_key); + // for (auto [val, val_vk] : zip_view(ivc.instance_vk->get_all(), verification_key->get_all())) { + // if (val == val_vk) { + // info("equal."); + // } else { + // info("NOT equal."); + // } + // } + Verifier verifier{ verification_key }; + + verified = verifier.verify_proof(proof); + } + if (!verified) { + return false; + } + witness_stack.pop_back(); + } + return true; +} + /** * @brief Proves and Verifies an ACIR circuit * @@ -834,6 +899,12 @@ int main(int argc, char* argv[]) if (command == "prove_and_verify_ultra_honk_program") { return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; } + if (command == "prove_and_verify_goblin_ultra_honk_program") { + return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; + } + if (command == "fold_and_verify_program") { + return foldAndVerifyProgram(bytecode_path, witness_path) ? 0 : 1; + } if (command == "prove_and_verify_goblin") { return proveAndVerifyGoblin(bytecode_path, witness_path) ? 0 : 1; } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 71b2ef0f9dd1..2cddb31731b1 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -25,6 +25,13 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr(circuit, structured_flag); diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index 6a1676c48833..ac9c167956a0 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -72,14 +72,40 @@ TEST_F(ClientIVCTests, Basic) { ClientIVC ivc; + using Flavor = GoblinUltraFlavor; // This is the only option + using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = Flavor::VerificationKey; + // Initialize the IVC with an arbitrary circuit Builder circuit_0 = create_mock_circuit(ivc); ivc.accumulate(circuit_0); + Prover prover{ ivc.prover_instance }; + info("gates = ", circuit_0.get_num_gates()); + info("circuit size = ", prover.instance->proving_key.circuit_size); + auto proof = prover.construct_proof(); + + auto verification_key = std::make_shared(prover.instance->proving_key); + Verifier verifier{ verification_key }; + + EXPECT_TRUE(verifier.verify_proof(proof)); + // Create another circuit and accumulate Builder circuit_1 = create_mock_circuit(ivc); ivc.accumulate(circuit_1); + Prover prover2{ ivc.prover_instance }; + info("gates = ", circuit_1.get_num_gates()); + info("circuit size = ", prover.instance->proving_key.circuit_size); + auto proof2 = prover2.construct_proof(); + + auto verification_key2 = std::make_shared(prover2.instance->proving_key); + Verifier verifier2{ verification_key2 }; + + EXPECT_TRUE(verifier2.verify_proof(proof2)); + EXPECT_TRUE(prove_and_verify(ivc)); }; @@ -123,19 +149,34 @@ TEST_F(ClientIVCTests, BasicLarge) { ClientIVC ivc; + using Flavor = GoblinUltraFlavor; // This is the only option + using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = Flavor::VerificationKey; + // Construct a set of arbitrary circuits size_t NUM_CIRCUITS = 5; std::vector circuits; for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { - circuits.emplace_back(create_mock_circuit(ivc)); + circuits.emplace_back(create_mock_circuit(ivc, 4)); } // Accumulate each circuit for (auto& circuit : circuits) { ivc.accumulate(circuit); + + info("HERE"); + Prover prover{ ivc.prover_instance }; + info("gates = ", circuit.get_num_gates()); + info("circuit size = ", prover.instance->proving_key.circuit_size); + auto proof = prover.construct_proof(); + auto verification_key = std::make_shared(prover.instance->proving_key); + Verifier verifier{ verification_key }; + EXPECT_TRUE(verifier.verify_proof(proof)); } - EXPECT_TRUE(prove_and_verify(ivc)); + // EXPECT_TRUE(prove_and_verify(ivc)); }; /** diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 3dc7fc15e6c9..3861c325618f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -340,7 +340,8 @@ template <> UltraCircuitBuilder create_circuit(const AcirFormat& constraint_system, size_t size_hint, WitnessVector const& witness, - bool honk_recursion) + bool honk_recursion, + [[maybe_unused]] std::shared_ptr) { Builder builder{ size_hint, witness, constraint_system.public_inputs, constraint_system.varnum, constraint_system.recursive @@ -367,10 +368,10 @@ template <> GoblinUltraCircuitBuilder create_circuit(const AcirFormat& constraint_system, [[maybe_unused]] size_t size_hint, WitnessVector const& witness, - bool honk_recursion) + bool honk_recursion, + std::shared_ptr op_queue) { // Construct a builder using the witness and public input data from acir and with the goblin-owned op_queue - auto op_queue = std::make_shared(); // instantiate empty op_queue auto builder = GoblinUltraCircuitBuilder{ op_queue, witness, constraint_system.public_inputs, constraint_system.varnum }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 35d4d1fe6c1b..358c1b85f7e6 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -108,7 +108,8 @@ template Builder create_circuit(const AcirFormat& constraint_system, size_t size_hint = 0, WitnessVector const& witness = {}, - bool honk_recursion = false); + bool honk_recursion = false, + std::shared_ptr op_queue = std::make_shared()); template void build_constraints(Builder& builder, From 5c1bdf824a23f36cc41bb54d3502d93db02341ed Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 20 May 2024 16:16:51 +0000 Subject: [PATCH 02/24] basic integration test setup --- .../cpp/src/barretenberg/dsl/CMakeLists.txt | 1 + .../dsl/acir_format/acir_integration.test.cpp | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt index 158c5752774a..e385ee6b05ad 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt @@ -1,6 +1,7 @@ barretenberg_module( dsl plonk + ultra_honk stdlib_sha256 stdlib_aes128 stdlib_keccak diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp new file mode 100644 index 000000000000..32081e7710aa --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -0,0 +1,88 @@ +#include +#include +#include + +#include "acir_format.hpp" +#include "barretenberg/bb/exec_pipe.hpp" +#include "barretenberg/common/streams.hpp" +#include "barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp" + +class AcirIntegrationTests : public ::testing::Test { + public: + static std::vector get_bytecode(const std::string& bytecodePath) + { + std::filesystem::path filePath = bytecodePath; + if (filePath.extension() == ".json") { + // Try reading json files as if they are a Nargo build artifact + std::string command = "jq -r '.bytecode' \"" + bytecodePath + "\" | base64 -d | gunzip -c"; + return exec_pipe(command); + } + + // For other extensions, assume file is a raw ACIR program + std::string command = "gunzip -c \"" + bytecodePath + "\""; + return exec_pipe(command); + } + + // Function to check if a file exists + bool file_exists(const std::string& path) + { + std::ifstream file(path); + return file.good(); + } + + struct AcirProgram { + acir_format::AcirFormat constraints; + acir_format::WitnessVector witness; + }; + + AcirProgram get_test_program_data(std::string test_program_name) + { + std::string base_path = "../../acir_tests/acir_tests/" + test_program_name + "/target"; + std::string bytecode_path = base_path + "/program.json"; + std::string witness_path = base_path + "/witness.gz"; + + EXPECT_TRUE(file_exists(bytecode_path)); + EXPECT_TRUE(file_exists(witness_path)); + + auto acir_buf = get_bytecode(bytecode_path); + acir_format::AcirFormat constraint_system = acir_format::circuit_buf_to_acir_format(acir_buf); + + auto witness_buf = get_bytecode(witness_path); + acir_format::WitnessVector witness = acir_format::witness_buf_to_witness_data(witness_buf); + + return { constraint_system, witness }; + } + + protected: + static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); } +}; +TEST_F(AcirIntegrationTests, Basic) +{ + using Flavor = GoblinUltraFlavor; + using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = Flavor::VerificationKey; + + std::string test_name = "6_array"; + auto acir_data = get_test_program_data(test_name); + + // Construct a bberg circuit from the acir representation + auto builder = acir_format::create_circuit(acir_data.constraints, 0, acir_data.witness); + + // Construct Honk proof + Prover prover{ builder }; + builder.blocks.summarize(); + info("num gates = ", builder.get_num_gates()); + info("circuit size = ", prover.instance->proving_key.circuit_size); + info("circuit size = ", prover.instance->proving_key.circuit_size); + auto proof = prover.construct_proof(); + + // Verify Honk proof + auto verification_key = std::make_shared(prover.instance->proving_key); + Verifier verifier{ verification_key }; + + EXPECT_TRUE(verifier.verify_proof(proof)); + + EXPECT_EQ(1, 1); +} From 1e4efca15739c2cb2ef522e260f2b1b122f55dd7 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 20 May 2024 17:06:50 +0000 Subject: [PATCH 03/24] add and use program stack struct --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 18 +++++------ .../dsl/acir_format/acir_format.hpp | 31 +++++++++++++++++++ .../acir_format/acir_to_constraint_buf.hpp | 12 +++++++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 32147b60f3c3..ab12ab0f61bd 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -170,6 +170,9 @@ bool proveAndVerifyHonkAcirFormat(acir_format::AcirFormat constraint_system, aci // Construct Honk proof Prover prover{ builder }; + builder.blocks.summarize(); + info("num gates = ", builder.get_num_gates()); + info("circuit size = ", prover.instance->proving_key.circuit_size); auto proof = prover.construct_proof(); // Verify Honk proof @@ -206,20 +209,15 @@ template bool proveAndVerifyHonk(const std::string& bytec template bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::string& witnessPath) { - auto constraint_systems = get_constraint_systems(bytecodePath); - auto witness_stack = get_witness_stack(witnessPath); + auto program_stack = acir_format::get_acir_program_stack(bytecodePath, witnessPath); - info("stack depth = ", witness_stack.size()); + while (!program_stack.empty()) { + auto stack_item = program_stack.back(); - while (!witness_stack.empty()) { - auto witness_stack_item = witness_stack.back(); - auto witness = witness_stack_item.second; - auto constraint_system = constraint_systems[witness_stack_item.first]; - - if (!proveAndVerifyHonkAcirFormat(constraint_system, witness)) { + if (!proveAndVerifyHonkAcirFormat(stack_item.constraints, stack_item.witness)) { return false; } - witness_stack.pop_back(); + program_stack.pop_back(); } return true; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 358c1b85f7e6..9e5cbe5e138b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -104,6 +104,37 @@ struct AcirFormat { using WitnessVector = std::vector>; using WitnessVectorStack = std::vector>; +/** + * @brief Storage for constaint_systems/witnesses for a stack of acir programs + * @details In general the number of items in the witness stack will be equal or greater than the number of constraint + * systems because the program may consist of multiple calls to the same function. + * + */ +struct AcirProgramStack { + std::vector constraint_systems; + WitnessVectorStack witness_stack; + + struct AcirProgram { + AcirFormat constraints; + WitnessVector witness; + }; + + size_t size() const { return witness_stack.size(); } + + bool empty() const { return witness_stack.empty(); } + + AcirProgram back() + { + auto witness_stack_item = witness_stack.back(); + auto witness = witness_stack_item.second; + auto constraint_system = constraint_systems[witness_stack_item.first]; + + return { constraint_system, witness }; + } + + void pop_back() { witness_stack.pop_back(); } +}; + template Builder create_circuit(const AcirFormat& constraint_system, size_t size_hint = 0, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index d51797034dc6..fde3da2ec5a8 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -1,5 +1,6 @@ #pragma once #include "acir_format.hpp" +#include "barretenberg/bb/get_bytecode.hpp" #include "barretenberg/common/container.hpp" #include "barretenberg/common/throw_or_abort.hpp" #include "barretenberg/dsl/acir_format/aes128_constraint.hpp" @@ -595,4 +596,15 @@ WitnessVectorStack witness_buf_to_witness_stack(std::vector const& buf) return witness_vector_stack; } +acir_format::AcirProgramStack get_acir_program_stack(std::string const& bytecode_path, std::string const& witness_path) +{ + auto bytecode = get_bytecode(bytecode_path); + auto constraint_systems = acir_format::program_buf_to_acir_format(bytecode); + + auto witness_data = get_bytecode(witness_path); + auto witness_stack = acir_format::witness_buf_to_witness_stack(witness_data); + + return { constraint_systems, witness_stack }; +} + } // namespace acir_format From 2c0b89ceb3087257998f4608575b19df1de60504 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 20 May 2024 17:46:38 +0000 Subject: [PATCH 04/24] integration test for program stack --- .../dsl/acir_format/acir_format.hpp | 14 ++-- .../dsl/acir_format/acir_integration.test.cpp | 82 ++++++++++++------- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 9e5cbe5e138b..75071318ab0b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -104,6 +104,11 @@ struct AcirFormat { using WitnessVector = std::vector>; using WitnessVectorStack = std::vector>; +struct AcirProgram { + AcirFormat constraints; + WitnessVector witness; +}; + /** * @brief Storage for constaint_systems/witnesses for a stack of acir programs * @details In general the number of items in the witness stack will be equal or greater than the number of constraint @@ -114,13 +119,12 @@ struct AcirProgramStack { std::vector constraint_systems; WitnessVectorStack witness_stack; - struct AcirProgram { - AcirFormat constraints; - WitnessVector witness; - }; + // WORKTODO: cant use the seriailzation bc of circular dependency. Resolve? or just leave as is? + // AcirProgramStack(std::string const& bytecode_path, std::string const& witness_path) + // : constraint_systems(program_buf_to_acir_format(bytecode_path)) + // , witness_stack(witness_buf_to_witness_stack(witness_path)){}; size_t size() const { return witness_stack.size(); } - bool empty() const { return witness_stack.empty(); } AcirProgram back() diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 32081e7710aa..3e0a9a84c9b9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -30,59 +30,79 @@ class AcirIntegrationTests : public ::testing::Test { return file.good(); } - struct AcirProgram { - acir_format::AcirFormat constraints; - acir_format::WitnessVector witness; - }; - - AcirProgram get_test_program_data(std::string test_program_name) + acir_format::AcirProgramStack get_program_stack_data_from_test_file(const std::string& test_program_name) { std::string base_path = "../../acir_tests/acir_tests/" + test_program_name + "/target"; std::string bytecode_path = base_path + "/program.json"; std::string witness_path = base_path + "/witness.gz"; - EXPECT_TRUE(file_exists(bytecode_path)); - EXPECT_TRUE(file_exists(witness_path)); + return acir_format::get_acir_program_stack(bytecode_path, witness_path); + } - auto acir_buf = get_bytecode(bytecode_path); - acir_format::AcirFormat constraint_system = acir_format::circuit_buf_to_acir_format(acir_buf); + acir_format::AcirProgram get_program_data_from_test_file(const std::string& test_program_name) + { + auto program_stack = get_program_stack_data_from_test_file(test_program_name); + ASSERT(program_stack.size() == 1); // Otherwise this method will not return full stack data - auto witness_buf = get_bytecode(witness_path); - acir_format::WitnessVector witness = acir_format::witness_buf_to_witness_data(witness_buf); + return program_stack.back(); + } - return { constraint_system, witness }; + template bool prove_and_verify_honk(Flavor::CircuitBuilder& builder) + { + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = Flavor::VerificationKey; + + Prover prover{ builder }; + builder.blocks.summarize(); + info("num gates = ", builder.get_num_gates()); + info("circuit size = ", prover.instance->proving_key.circuit_size); + info("circuit size = ", prover.instance->proving_key.circuit_size); + auto proof = prover.construct_proof(); + + // Verify Honk proof + auto verification_key = std::make_shared(prover.instance->proving_key); + Verifier verifier{ verification_key }; + + return verifier.verify_proof(proof); } protected: static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); } }; -TEST_F(AcirIntegrationTests, Basic) + +TEST_F(AcirIntegrationTests, ProveAndVerifyProgram) { using Flavor = GoblinUltraFlavor; using Builder = Flavor::CircuitBuilder; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using VerificationKey = Flavor::VerificationKey; std::string test_name = "6_array"; - auto acir_data = get_test_program_data(test_name); + auto acir_program = get_program_data_from_test_file(test_name); // Construct a bberg circuit from the acir representation - auto builder = acir_format::create_circuit(acir_data.constraints, 0, acir_data.witness); + auto builder = acir_format::create_circuit(acir_program.constraints, 0, acir_program.witness); + + // Construct and verify Honk proof + EXPECT_TRUE(prove_and_verify_honk(builder)); +} - // Construct Honk proof - Prover prover{ builder }; - builder.blocks.summarize(); - info("num gates = ", builder.get_num_gates()); - info("circuit size = ", prover.instance->proving_key.circuit_size); - info("circuit size = ", prover.instance->proving_key.circuit_size); - auto proof = prover.construct_proof(); +TEST_F(AcirIntegrationTests, ProveAndVerifyProgramStack) +{ + using Flavor = GoblinUltraFlavor; + using Builder = Flavor::CircuitBuilder; - // Verify Honk proof - auto verification_key = std::make_shared(prover.instance->proving_key); - Verifier verifier{ verification_key }; + std::string test_name = "fold_basic"; + auto program_stack = get_program_stack_data_from_test_file(test_name); - EXPECT_TRUE(verifier.verify_proof(proof)); + while (!program_stack.empty()) { + auto program = program_stack.back(); - EXPECT_EQ(1, 1); + // Construct a bberg circuit from the acir representation + auto builder = acir_format::create_circuit(program.constraints, 0, program.witness); + + // Construct and verify Honk proof for the individidual circuit + EXPECT_TRUE(prove_and_verify_honk(builder)); + + program_stack.pop_back(); + } } From e328d2c6058c32c743d2db1f4d133954d2ee908e Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 20 May 2024 22:06:25 +0000 Subject: [PATCH 05/24] client ivc prove and verify method --- .../cpp/src/barretenberg/client_ivc/client_ivc.cpp | 14 ++++++++++++++ .../cpp/src/barretenberg/client_ivc/client_ivc.hpp | 2 ++ 2 files changed, 16 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 2cddb31731b1..04f77a7eeb5c 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -124,4 +124,18 @@ std::vector> ClientIVC::precompute_f return vkeys; } +/** + * @brief Construct and verify a proof for the IVC + * @details This is intended to be a development/testing only method since in general the prover and verifier will be + * different entities. + * + */ +bool ClientIVC::prove_and_verify() +{ + auto proof = prove(); + + auto verifier_inst = std::make_shared(this->instance_vk); + return verify(proof, { this->verifier_accumulator, verifier_inst }); +} + } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp index d44b02f6740d..e85b008cfc6b 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -87,6 +87,8 @@ class ClientIVC { bool verify(Proof& proof, const std::vector>& verifier_instances); + bool prove_and_verify(); + HonkProof decider_prove() const; std::vector> precompute_folding_verification_keys(std::vector); From aaf1550c7be94cb0430451c1bd677d2549314703 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 20 May 2024 22:07:33 +0000 Subject: [PATCH 06/24] updates to inegration tests, client ivc test failing --- .../cpp/src/barretenberg/dsl/CMakeLists.txt | 1 + .../dsl/acir_format/acir_integration.test.cpp | 74 +++++++++++++++++-- .../protogalaxy/protogalaxy_prover.cpp | 4 + 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt index e385ee6b05ad..c5822d80b4ca 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt @@ -2,6 +2,7 @@ barretenberg_module( dsl plonk ultra_honk + client_ivc stdlib_sha256 stdlib_aes128 stdlib_keccak diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 3e0a9a84c9b9..330232196958 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -4,6 +4,7 @@ #include "acir_format.hpp" #include "barretenberg/bb/exec_pipe.hpp" +#include "barretenberg/client_ivc/client_ivc.hpp" #include "barretenberg/common/streams.hpp" #include "barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp" @@ -47,7 +48,7 @@ class AcirIntegrationTests : public ::testing::Test { return program_stack.back(); } - template bool prove_and_verify_honk(Flavor::CircuitBuilder& builder) + template bool prove_and_verify_honk(Flavor::CircuitBuilder builder) { using Prover = UltraProver_; using Verifier = UltraVerifier_; @@ -67,8 +68,28 @@ class AcirIntegrationTests : public ::testing::Test { return verifier.verify_proof(proof); } + template bool prove_and_verify_honk(std::shared_ptr> prover_instance) + { + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = Flavor::VerificationKey; + + Prover prover{ prover_instance }; + auto proof = prover.construct_proof(); + + // Verify Honk proof + auto verification_key = std::make_shared(prover.instance->proving_key); + Verifier verifier{ verification_key }; + + return verifier.verify_proof(proof); + } + protected: - static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); } + static void SetUpTestSuite() + { + srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } }; TEST_F(AcirIntegrationTests, ProveAndVerifyProgram) @@ -80,10 +101,10 @@ TEST_F(AcirIntegrationTests, ProveAndVerifyProgram) auto acir_program = get_program_data_from_test_file(test_name); // Construct a bberg circuit from the acir representation - auto builder = acir_format::create_circuit(acir_program.constraints, 0, acir_program.witness); + auto circuit = acir_format::create_circuit(acir_program.constraints, 0, acir_program.witness); // Construct and verify Honk proof - EXPECT_TRUE(prove_and_verify_honk(builder)); + EXPECT_TRUE(prove_and_verify_honk(circuit)); } TEST_F(AcirIntegrationTests, ProveAndVerifyProgramStack) @@ -98,11 +119,52 @@ TEST_F(AcirIntegrationTests, ProveAndVerifyProgramStack) auto program = program_stack.back(); // Construct a bberg circuit from the acir representation - auto builder = acir_format::create_circuit(program.constraints, 0, program.witness); + auto circuit = acir_format::create_circuit(program.constraints, 0, program.witness); // Construct and verify Honk proof for the individidual circuit - EXPECT_TRUE(prove_and_verify_honk(builder)); + EXPECT_TRUE(prove_and_verify_honk(circuit)); + + program_stack.pop_back(); + } +} + +TEST_F(AcirIntegrationTests, FoldAndVerifyProgramStack) +{ + using Flavor = GoblinUltraFlavor; + using Builder = Flavor::CircuitBuilder; + + std::string test_name = "fold_basic"; + auto program_stack = get_program_stack_data_from_test_file(test_name); + + ClientIVC ivc; + ivc.structured_flag = true; + + while (!program_stack.empty()) { + info("Program:"); + auto program = program_stack.back(); + + // Construct a bberg circuit from the acir representation + auto circuit = + acir_format::create_circuit(program.constraints, 0, program.witness, false, ivc.goblin.op_queue); + + ivc.accumulate(circuit); + + info("Check"); + CircuitChecker::check(circuit); + + info("P & V"); + EXPECT_TRUE(prove_and_verify_honk(ivc.prover_instance)); + + info("num gates = ", circuit.get_num_gates()); + info("circuit size = ", ivc.prover_instance->proving_key.circuit_size); program_stack.pop_back(); } + + // EXPECT_TRUE(ivc.prove_and_verify()); + + // auto proof = ivc.prove(); + + // auto verifier_inst = std::make_shared(ivc.instance_vk); + // return ivc.verify(proof, { ivc.verifier_accumulator, verifier_inst }); } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index e003418a5245..4f5ee5327d13 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -200,6 +200,10 @@ template FoldingResult ProtoGalaxyProver_::fold_instances() { BB_OP_COUNT_TIME_NAME("ProtogalaxyProver::fold_instances"); + // Ensure instances are all of the same size + for (size_t idx = 0; idx < ProverInstances::NUM - 1; ++idx) { + ASSERT(instances[idx]->proving_key.circuit_size == instances[idx + 1]->proving_key.circuit_size); + } preparation_round(); perturbator_round(); combiner_quotient_round(); From 436f7514d039424ad277454ec769292250dd8552 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 20 May 2024 23:38:41 +0000 Subject: [PATCH 07/24] minimal test showing issue with adding RAM post --- .../dsl/acir_format/acir_integration.test.cpp | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 330232196958..f48314180df2 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -84,6 +84,35 @@ class AcirIntegrationTests : public ::testing::Test { return verifier.verify_proof(proof); } + void add_some_simple_RAM_gates(auto& circuit) + { + std::array ram_values{ circuit.add_variable(5), + circuit.add_variable(10), + circuit.add_variable(20) }; + + size_t ram_id = circuit.create_RAM_array(3); + + for (size_t i = 0; i < 3; ++i) { + circuit.init_RAM_element(ram_id, i, ram_values[i]); + } + + auto val_idx_1 = circuit.read_RAM_array(ram_id, circuit.add_variable(1)); + auto val_idx_2 = circuit.read_RAM_array(ram_id, circuit.add_variable(2)); + auto val_idx_3 = circuit.read_RAM_array(ram_id, circuit.add_variable(0)); + + circuit.create_big_add_gate({ + val_idx_1, + val_idx_2, + val_idx_3, + circuit.zero_idx, + 1, + 1, + 1, + 0, + -35, + }); + } + protected: static void SetUpTestSuite() { @@ -168,3 +197,45 @@ TEST_F(AcirIntegrationTests, FoldAndVerifyProgramStack) // auto verifier_inst = std::make_shared(ivc.instance_vk); // return ivc.verify(proof, { ivc.verifier_accumulator, verifier_inst }); } + +TEST_F(AcirIntegrationTests, UpdateAcirCircuit) +{ + using Flavor = GoblinUltraFlavor; + using Builder = Flavor::CircuitBuilder; + // using FF = Flavor::FF; + + std::string test_name = "6_array"; + auto acir_program = get_program_data_from_test_file(test_name); + + // Construct a bberg circuit from the acir representation + auto circuit = acir_format::create_circuit(acir_program.constraints, 0, acir_program.witness); + + EXPECT_TRUE(CircuitChecker::check(circuit)); + + // Manually append some RAM gates + add_some_simple_RAM_gates(circuit); + + EXPECT_TRUE(CircuitChecker::check(circuit)); + + // Construct and verify Honk proof + EXPECT_TRUE(prove_and_verify_honk(circuit)); +} + +TEST_F(AcirIntegrationTests, SimpleCircuit) +{ + using Flavor = GoblinUltraFlavor; + using Builder = Flavor::CircuitBuilder; + + // Construct a bberg circuit from the acir representation + Builder circuit; + + add_some_simple_RAM_gates(circuit); + add_some_simple_RAM_gates(circuit); + add_some_simple_RAM_gates(circuit); + circuit.blocks.summarize(); + + EXPECT_TRUE(CircuitChecker::check(circuit)); + + // Construct and verify Honk proof + EXPECT_TRUE(prove_and_verify_honk(circuit)); +} From 5e9072fc5a8b33537804a86e1e9657cfaec89d5c Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 22 May 2024 15:33:57 +0000 Subject: [PATCH 08/24] test cleanup --- .../dsl/acir_format/acir_format.cpp | 4 --- .../dsl/acir_format/acir_integration.test.cpp | 32 ++++++------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 3861c325618f..90da7a09a31a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -350,8 +350,6 @@ UltraCircuitBuilder create_circuit(const AcirFormat& constraint_system, bool has_valid_witness_assignments = !witness.empty(); build_constraints(builder, constraint_system, has_valid_witness_assignments, honk_recursion); - builder.finalize_circuit(); - return builder; }; @@ -379,8 +377,6 @@ GoblinUltraCircuitBuilder create_circuit(const AcirFormat& constraint_system, bool has_valid_witness_assignments = !witness.empty(); acir_format::build_constraints(builder, constraint_system, has_valid_witness_assignments, honk_recursion); - builder.finalize_circuit(); - return builder; }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index f48314180df2..89fe07646a06 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -202,7 +202,6 @@ TEST_F(AcirIntegrationTests, UpdateAcirCircuit) { using Flavor = GoblinUltraFlavor; using Builder = Flavor::CircuitBuilder; - // using FF = Flavor::FF; std::string test_name = "6_array"; auto acir_program = get_program_data_from_test_file(test_name); @@ -212,30 +211,19 @@ TEST_F(AcirIntegrationTests, UpdateAcirCircuit) EXPECT_TRUE(CircuitChecker::check(circuit)); - // Manually append some RAM gates - add_some_simple_RAM_gates(circuit); - - EXPECT_TRUE(CircuitChecker::check(circuit)); - - // Construct and verify Honk proof - EXPECT_TRUE(prove_and_verify_honk(circuit)); -} - -TEST_F(AcirIntegrationTests, SimpleCircuit) -{ - using Flavor = GoblinUltraFlavor; - using Builder = Flavor::CircuitBuilder; - - // Construct a bberg circuit from the acir representation - Builder circuit; + // Now we'll append some addition gates onto the circuit generated from acir and confirm that its still valid. + // First, check that the simple circuit is valid in isolation + { + Builder simple_circuit; + add_some_simple_RAM_gates(circuit); + EXPECT_TRUE(CircuitChecker::check(simple_circuit)); + EXPECT_TRUE(prove_and_verify_honk(simple_circuit)); + } + // Now manually append the simple RAM circuit to the circuit generated from acir add_some_simple_RAM_gates(circuit); - add_some_simple_RAM_gates(circuit); - add_some_simple_RAM_gates(circuit); - circuit.blocks.summarize(); + // Confirm that the result is still valid EXPECT_TRUE(CircuitChecker::check(circuit)); - - // Construct and verify Honk proof EXPECT_TRUE(prove_and_verify_honk(circuit)); } From 492b2ed5ebe511ba54096d4aae8afea3a3a07c11 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 22 May 2024 19:15:54 +0000 Subject: [PATCH 09/24] client ivc test passes --- .../barretenberg/client_ivc/client_ivc.cpp | 7 ------- .../dsl/acir_format/acir_integration.test.cpp | 21 +++++++------------ .../barretenberg/ultra_honk/merge_prover.cpp | 1 + 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 04f77a7eeb5c..117a2bf52f7e 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -25,13 +25,6 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr(circuit, structured_flag); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 89fe07646a06..76b141fc6a42 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -176,26 +176,21 @@ TEST_F(AcirIntegrationTests, FoldAndVerifyProgramStack) auto circuit = acir_format::create_circuit(program.constraints, 0, program.witness, false, ivc.goblin.op_queue); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): On the first call to accumulate, the input + // circuit generated from acir has no goblin ecc ops prior to the call to merge(), so the commitment to the new + // contribution (C_t_shift) will be the point at infinity. (Some ops are added in 'add_gates_to_ensure...' but + // not until instance construction which comes later). + MockCircuits::construct_goblin_ecc_op_circuit(circuit); // Add some arbitrary goblin ECC ops + ivc.accumulate(circuit); - info("Check"); CircuitChecker::check(circuit); - - info("P & V"); - EXPECT_TRUE(prove_and_verify_honk(ivc.prover_instance)); - - info("num gates = ", circuit.get_num_gates()); - info("circuit size = ", ivc.prover_instance->proving_key.circuit_size); + // EXPECT_TRUE(prove_and_verify_honk(ivc.prover_instance)); program_stack.pop_back(); } - // EXPECT_TRUE(ivc.prove_and_verify()); - - // auto proof = ivc.prove(); - - // auto verifier_inst = std::make_shared(ivc.instance_vk); - // return ivc.verify(proof, { ivc.verifier_accumulator, verifier_inst }); + EXPECT_TRUE(ivc.prove_and_verify()); } TEST_F(AcirIntegrationTests, UpdateAcirCircuit) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index de151cbb393a..6914b86d5ec3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -43,6 +43,7 @@ template HonkProof MergeProver_::construct_proof() auto T_prev = op_queue->get_previous_aggregate_transcript(); // TODO(#723): Cannot currently support an empty T_{i-1}. Need to be able to properly handle zero commitment. ASSERT(T_prev[0].size() > 0); + ASSERT(T_current[0].size() > T_prev[0].size()); // Must have some new ops to accumulate otherwise C_t_shift = 0 // Construct t_i^{shift} as T_i - T_{i-1} std::array t_shift; From 6e7162f1a7f5da07da9113684929d2ebf278c627 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 22 May 2024 20:35:07 +0000 Subject: [PATCH 10/24] move adding of mock ops into client ivc --- .../client_ivc/client_ivc.test.cpp | 41 ------------------- .../dsl/acir_format/acir_integration.test.cpp | 6 --- .../cpp/src/barretenberg/goblin/goblin.hpp | 8 ++++ 3 files changed, 8 insertions(+), 47 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index c470f15a6adb..c09f2aa46ae2 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -54,12 +54,6 @@ class ClientIVCTests : public ::testing::Test { Builder circuit{ ivc.goblin.op_queue }; MockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the - // function circuit because we cannot support zero commtiments. While the builder handles this at - // finalisation stage via the add_gates_to_ensure_all_polys_are_non_zero function for other UGH - // circuits (where we don't explicitly need to add goblin ops), in ClientIVC merge proving happens prior to - // folding where the absense of goblin ecc ops will result in zero commitments. - MockCircuits::construct_goblin_ecc_op_circuit(circuit); return circuit; } }; @@ -74,38 +68,15 @@ TEST_F(ClientIVCTests, Basic) using Flavor = GoblinUltraFlavor; // This is the only option using Builder = Flavor::CircuitBuilder; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using VerificationKey = Flavor::VerificationKey; // Initialize the IVC with an arbitrary circuit Builder circuit_0 = create_mock_circuit(ivc); ivc.accumulate(circuit_0); - Prover prover{ ivc.prover_instance }; - info("gates = ", circuit_0.get_num_gates()); - info("circuit size = ", prover.instance->proving_key.circuit_size); - auto proof = prover.construct_proof(); - - auto verification_key = std::make_shared(prover.instance->proving_key); - Verifier verifier{ verification_key }; - - EXPECT_TRUE(verifier.verify_proof(proof)); - // Create another circuit and accumulate Builder circuit_1 = create_mock_circuit(ivc); ivc.accumulate(circuit_1); - Prover prover2{ ivc.prover_instance }; - info("gates = ", circuit_1.get_num_gates()); - info("circuit size = ", prover.instance->proving_key.circuit_size); - auto proof2 = prover2.construct_proof(); - - auto verification_key2 = std::make_shared(prover2.instance->proving_key); - Verifier verifier2{ verification_key2 }; - - EXPECT_TRUE(verifier2.verify_proof(proof2)); - EXPECT_TRUE(prove_and_verify(ivc)); }; @@ -151,9 +122,6 @@ TEST_F(ClientIVCTests, DISABLED_BasicLarge) using Flavor = GoblinUltraFlavor; // This is the only option using Builder = Flavor::CircuitBuilder; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using VerificationKey = Flavor::VerificationKey; // Construct a set of arbitrary circuits size_t NUM_CIRCUITS = 5; @@ -165,15 +133,6 @@ TEST_F(ClientIVCTests, DISABLED_BasicLarge) // Accumulate each circuit for (auto& circuit : circuits) { ivc.accumulate(circuit); - - info("HERE"); - Prover prover{ ivc.prover_instance }; - info("gates = ", circuit.get_num_gates()); - info("circuit size = ", prover.instance->proving_key.circuit_size); - auto proof = prover.construct_proof(); - auto verification_key = std::make_shared(prover.instance->proving_key); - Verifier verifier{ verification_key }; - EXPECT_TRUE(verifier.verify_proof(proof)); } // EXPECT_TRUE(prove_and_verify(ivc)); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 76b141fc6a42..d1cf19557578 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -176,12 +176,6 @@ TEST_F(AcirIntegrationTests, FoldAndVerifyProgramStack) auto circuit = acir_format::create_circuit(program.constraints, 0, program.witness, false, ivc.goblin.op_queue); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): On the first call to accumulate, the input - // circuit generated from acir has no goblin ecc ops prior to the call to merge(), so the commitment to the new - // contribution (C_t_shift) will be the point at infinity. (Some ops are added in 'add_gates_to_ensure...' but - // not until instance construction which comes later). - MockCircuits::construct_goblin_ecc_op_circuit(circuit); // Add some arbitrary goblin ECC ops - ivc.accumulate(circuit); CircuitChecker::check(circuit); diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 7cfc5406801b..0a9107e7e28c 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -147,6 +147,14 @@ class Goblin { [[maybe_unused]] auto pairing_points = merge_verifier.verify_proof(merge_proof); } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/993): On the first call to accumulate, the input + // circuit generated from acir has no goblin ecc ops prior to the call to merge(), so the commitment to the new + // contribution (C_t_shift) will be the point at infinity. (Some ops are added in 'add_gates_to_ensure...' but + // not until instance construction which comes later). + if (circuit_builder.blocks.ecc_op.size() == 0) { + MockCircuits::construct_goblin_ecc_op_circuit(circuit_builder); // Add some arbitrary goblin ECC ops + } + // Construct and store the merge proof to be recursively verified on the next call to accumulate MergeProver merge_prover{ circuit_builder.op_queue }; merge_proof = merge_prover.construct_proof(); From f3a91e083f1424262b1438c18e872fba5aaf9dd4 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 22 May 2024 21:33:22 +0000 Subject: [PATCH 11/24] fold and verify flow passes --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 60 +++++-------------- .../client_ivc/client_ivc.test.cpp | 8 +-- 2 files changed, 17 insertions(+), 51 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 843bb58894b2..47c82004d226 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -227,62 +227,34 @@ bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& wi { using Flavor = GoblinUltraFlavor; // This is the only option using Builder = Flavor::CircuitBuilder; - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using VerificationKey = Flavor::VerificationKey; - init_bn254_crs(1 << 17); - init_grumpkin_crs(1 << 10); + init_bn254_crs(1 << 18); + init_grumpkin_crs(1 << 14); ClientIVC ivc; - // ivc.structured_flag = true; - auto op_queue = ivc.goblin.op_queue; + ivc.structured_flag = true; - auto constraint_systems = get_constraint_systems(bytecodePath); - auto witness_stack = get_witness_stack(witnessPath); - - info("stack depth = ", witness_stack.size()); - - while (!witness_stack.empty()) { - auto witness_stack_item = witness_stack.back(); - auto witness = witness_stack_item.second; - auto constraint_system = constraint_systems[witness_stack_item.first]; + auto program_stack = acir_format::get_acir_program_stack(bytecodePath, witnessPath); - bool verified = true; + while (!program_stack.empty()) { + auto stack_item = program_stack.back(); { // Construct a bberg circuit from the acir representation - auto builder = acir_format::create_circuit(constraint_system, 0, witness, false, op_queue); + auto builder = acir_format::create_circuit( + stack_item.constraints, 0, stack_item.witness, false, ivc.goblin.op_queue); ivc.accumulate(builder); - builder.blocks.summarize(); - - // Construct Honk proof - Prover prover{ ivc.prover_instance }; - // Prover prover{ builder }; - info("gates = ", builder.get_num_gates()); - info("circuit size = ", prover.instance->proving_key.circuit_size); - auto proof = prover.construct_proof(); - - // Verify Honk proof - auto verification_key = std::make_shared(prover.instance->proving_key); - // for (auto [val, val_vk] : zip_view(ivc.instance_vk->get_all(), verification_key->get_all())) { - // if (val == val_vk) { - // info("equal."); - // } else { - // info("NOT equal."); - // } - // } - Verifier verifier{ verification_key }; - - verified = verifier.verify_proof(proof); - } - if (!verified) { - return false; + // builder.blocks.summarize(); + + // // Construct Honk proof + // info("gates = ", builder.get_num_gates()); + // info("circuit size = ", ivc.prover_instance->proving_key.circuit_size); + + program_stack.pop_back(); } - witness_stack.pop_back(); } - return true; + return ivc.prove_and_verify(); } /** diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index c09f2aa46ae2..eab54163aef6 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -66,9 +66,6 @@ TEST_F(ClientIVCTests, Basic) { ClientIVC ivc; - using Flavor = GoblinUltraFlavor; // This is the only option - using Builder = Flavor::CircuitBuilder; - // Initialize the IVC with an arbitrary circuit Builder circuit_0 = create_mock_circuit(ivc); ivc.accumulate(circuit_0); @@ -120,9 +117,6 @@ TEST_F(ClientIVCTests, DISABLED_BasicLarge) { ClientIVC ivc; - using Flavor = GoblinUltraFlavor; // This is the only option - using Builder = Flavor::CircuitBuilder; - // Construct a set of arbitrary circuits size_t NUM_CIRCUITS = 5; std::vector circuits; @@ -135,7 +129,7 @@ TEST_F(ClientIVCTests, DISABLED_BasicLarge) ivc.accumulate(circuit); } - // EXPECT_TRUE(prove_and_verify(ivc)); + EXPECT_TRUE(prove_and_verify(ivc)); }; /** From deb96582783d8d06e4f5bf02e0460001a4080c05 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 22 May 2024 22:52:56 +0000 Subject: [PATCH 12/24] add cbinds for fold and verify --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 21 ++- .../dsl/acir_format/acir_format.hpp | 5 + .../barretenberg/dsl/acir_proofs/c_bind.cpp | 28 ++++ .../barretenberg/dsl/acir_proofs/c_bind.hpp | 8 ++ barretenberg/exports.json | 40 ++++++ barretenberg/ts/src/barretenberg_api/index.ts | 128 ++++-------------- 6 files changed, 119 insertions(+), 111 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 47c82004d226..1f7286b1cb7c 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -238,21 +238,20 @@ bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& wi while (!program_stack.empty()) { auto stack_item = program_stack.back(); - { - // Construct a bberg circuit from the acir representation - auto builder = acir_format::create_circuit( - stack_item.constraints, 0, stack_item.witness, false, ivc.goblin.op_queue); - ivc.accumulate(builder); + // Construct a bberg circuit from the acir representation + auto builder = acir_format::create_circuit( + stack_item.constraints, 0, stack_item.witness, false, ivc.goblin.op_queue); - // builder.blocks.summarize(); + ivc.accumulate(builder); - // // Construct Honk proof - // info("gates = ", builder.get_num_gates()); - // info("circuit size = ", ivc.prover_instance->proving_key.circuit_size); + // builder.blocks.summarize(); - program_stack.pop_back(); - } + // // Construct Honk proof + // info("gates = ", builder.get_num_gates()); + // info("circuit size = ", ivc.prover_instance->proving_key.circuit_size); + + program_stack.pop_back(); } return ivc.prove_and_verify(); } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 75071318ab0b..7317224446f7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -119,6 +119,11 @@ struct AcirProgramStack { std::vector constraint_systems; WitnessVectorStack witness_stack; + AcirProgramStack(std::vector& constraint_systems_in, WitnessVectorStack& witness_stack_in) + : constraint_systems(constraint_systems_in) + , witness_stack(witness_stack_in) + {} + // WORKTODO: cant use the seriailzation bc of circular dependency. Resolve? or just leave as is? // AcirProgramStack(std::string const& bytecode_path, std::string const& witness_path) // : constraint_systems(program_buf_to_acir_format(bytecode_path)) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index defc038a4d83..1d6a70404906 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -1,6 +1,7 @@ #include "c_bind.hpp" #include "../acir_format/acir_to_constraint_buf.hpp" #include "acir_composer.hpp" +#include "barretenberg/client_ivc/client_ivc.hpp" #include "barretenberg/common/mem.hpp" #include "barretenberg/common/net.hpp" #include "barretenberg/common/serialize.hpp" @@ -78,6 +79,33 @@ WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* acir_vec, uint8 *result = verifier.verify_proof(proof); } +WASM_EXPORT void acir_fold_and_verify_program_stack(uint8_t const* acir_vec, uint8_t const* witness_vec, bool* result) +{ + using ProgramStack = acir_format::AcirProgramStack; + using Builder = GoblinUltraCircuitBuilder; + + auto constraint_systems = acir_format::program_buf_to_acir_format(from_buffer>(acir_vec)); + auto witness_stack = acir_format::witness_buf_to_witness_stack(from_buffer>(witness_vec)); + + ProgramStack program_stack{ constraint_systems, witness_stack }; + + ClientIVC ivc; + ivc.structured_flag = true; + + while (!program_stack.empty()) { + auto stack_item = program_stack.back(); + + // Construct a bberg circuit from the acir representation + auto builder = acir_format::create_circuit( + stack_item.constraints, 0, stack_item.witness, false, ivc.goblin.op_queue); + + ivc.accumulate(builder); + + program_stack.pop_back(); + } + *result = ivc.prove_and_verify(); +} + WASM_EXPORT void acir_prove_and_verify_goblin_ultra_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, bool* result) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp index 8d1f060a74e3..038e85e27ff1 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp @@ -49,6 +49,14 @@ WASM_EXPORT void acir_prove_and_verify_goblin_ultra_honk(uint8_t const* constrai uint8_t const* witness_buf, bool* result); +/** + * @brief Fold and verify a set of circuits using ClientIvc + * + */ +WASM_EXPORT void acir_fold_and_verify_program_stack(uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + bool* result); + /** * @brief Construct a full goblin proof * @details Makes a call to accumulate to a final circuit before constructing a Goblin proof diff --git a/barretenberg/exports.json b/barretenberg/exports.json index b0ed6310fb37..00f5b3bda76f 100644 --- a/barretenberg/exports.json +++ b/barretenberg/exports.json @@ -654,6 +654,26 @@ ], "isAsync": false }, + { + "functionName": "acir_fold_and_verify_program_stack", + "inArgs": [ + { + "name": "constraint_system_buf", + "type": "const uint8_t *" + }, + { + "name": "witness_buf", + "type": "const uint8_t *" + } + ], + "outArgs": [ + { + "name": "result", + "type": "bool *" + } + ], + "isAsync": false + }, { "functionName": "acir_goblin_prove", "inArgs": [ @@ -839,5 +859,25 @@ } ], "isAsync": false + }, + { + "functionName": "acir_prove_ultra_honk", + "inArgs": [ + { + "name": "acir_vec", + "type": "const uint8_t *" + }, + { + "name": "witness_vec", + "type": "const uint8_t *" + } + ], + "outArgs": [ + { + "name": "out", + "type": "uint8_t **" + } + ], + "isAsync": false } ] diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index c7972d388693..29d575452dc0 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -440,6 +440,18 @@ export class BarretenbergApi { return out[0]; } + async acirFoldAndVerifyProgramStack(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Promise { + const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; + const result = await this.wasm.callWasmExport( + 'acir_fold_and_verify_program_stack', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + async acirGoblinProve( acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array, @@ -568,8 +580,8 @@ export class BarretenbergApi { return out as any; } - async acirProveUltraHonk(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Promise { - const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + async acirProveUltraHonk(acirVec: Uint8Array, witnessVec: Uint8Array): Promise { + const inArgs = [acirVec, witnessVec].map(serializeBufferable); const outTypes: OutputType[] = [BufferDeserializer()]; const result = await this.wasm.callWasmExport( 'acir_prove_ultra_honk', @@ -579,54 +591,6 @@ export class BarretenbergApi { const out = result.map((r, i) => outTypes[i].fromBuffer(r)); return out[0]; } - - async acirVerifyUltraHonk(proofBuf: Uint8Array, vkBuf: Uint8Array): Promise { - const inArgs = [proofBuf, vkBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BoolDeserializer()]; - const result = await this.wasm.callWasmExport( - 'acir_verify_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - - async acirWriteVkUltraHonk(constraintSystemBuf: Uint8Array): Promise { - const inArgs = [constraintSystemBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BufferDeserializer()]; - const result = await this.wasm.callWasmExport( - 'acir_write_vk_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - - async acirProofAsFieldsUltraHonk(proofBuf: Uint8Array): Promise { - const inArgs = [proofBuf].map(serializeBufferable); - const outTypes: OutputType[] = [VectorDeserializer(Fr)]; - const result = await this.wasm.callWasmExport( - 'acir_proof_as_fields_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - - async acirVkAsFieldsUltraHonk(vkBuf: Uint8Array): Promise { - const inArgs = [vkBuf].map(serializeBufferable); - const outTypes: OutputType[] = [VectorDeserializer(Fr)]; - const result = await this.wasm.callWasmExport( - 'acir_vk_as_fields_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out as any; - } } export class BarretenbergApiSync { constructor(protected wasm: BarretenbergWasm) {} @@ -1052,6 +1016,18 @@ export class BarretenbergApiSync { return out[0]; } + acirFoldAndVerifyProgramStack(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): boolean { + const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; + const result = this.wasm.callWasmExport( + 'acir_fold_and_verify_program_stack', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + acirGoblinProve(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Uint8Array { const inArgs = [acirComposerPtr, constraintSystemBuf, witnessBuf].map(serializeBufferable); const outTypes: OutputType[] = [BufferDeserializer()]; @@ -1172,8 +1148,8 @@ export class BarretenbergApiSync { return out as any; } - acirUltraHonkProve(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Uint8Array { - const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + acirProveUltraHonk(acirVec: Uint8Array, witnessVec: Uint8Array): Uint8Array { + const inArgs = [acirVec, witnessVec].map(serializeBufferable); const outTypes: OutputType[] = [BufferDeserializer()]; const result = this.wasm.callWasmExport( 'acir_prove_ultra_honk', @@ -1183,52 +1159,4 @@ export class BarretenbergApiSync { const out = result.map((r, i) => outTypes[i].fromBuffer(r)); return out[0]; } - - acirVerifyUltraHonk(proofBuf: Uint8Array, vkBuf: Uint8Array): boolean { - const inArgs = [proofBuf, vkBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BoolDeserializer()]; - const result = this.wasm.callWasmExport( - 'acir_verify_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - - acirWriteVkUltraHonk(constraintSystemBuf: Uint8Array): Uint8Array { - const inArgs = [constraintSystemBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BufferDeserializer()]; - const result = this.wasm.callWasmExport( - 'acir_write_vk_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - - acirProofAsFieldsUltraHonk(proofBuf: Uint8Array): Fr[] { - const inArgs = [proofBuf].map(serializeBufferable); - const outTypes: OutputType[] = [VectorDeserializer(Fr)]; - const result = this.wasm.callWasmExport( - 'acir_proof_as_fields_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - - acirVkAsFieldsUltraHonk(vkBuf: Uint8Array): Fr[] { - const inArgs = [vkBuf].map(serializeBufferable); - const outTypes: OutputType[] = [VectorDeserializer(Fr)]; - const result = this.wasm.callWasmExport( - 'acir_vk_as_fields_ultra_honk', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out as any; - } } From 5adc97a5bbe18fbd4955f06f94e944c737eff413 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 23 May 2024 13:46:52 +0000 Subject: [PATCH 13/24] add fold tests to CI for bb and bbjs --- barretenberg/Earthfile | 2 ++ barretenberg/acir_tests/Dockerfile.bb.js | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/barretenberg/Earthfile b/barretenberg/Earthfile index 739dfc9e1aef..d2f287513ef1 100644 --- a/barretenberg/Earthfile +++ b/barretenberg/Earthfile @@ -38,6 +38,8 @@ barretenberg-acir-tests-bb: RUN FLOW=prove_and_verify_goblin_ultra_honk ./run_acir_tests.sh 6_array # Construct and verify a UltraHonk proof for all ACIR programs using the new witness stack workflow RUN FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh + # Fold and verify an ACIR program stack using ClientIvc + RUN FLOW=fold_and_verify_program ./run_acir_tests.sh # This is a "full" Goblin flow. It constructs and verifies four proofs: GoblinUltraHonk, ECCVM, Translator, and merge RUN FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through native bb build, all_cmds flow, to test all cli args. diff --git a/barretenberg/acir_tests/Dockerfile.bb.js b/barretenberg/acir_tests/Dockerfile.bb.js index ebafd7da88cb..8ea436cf9170 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -23,6 +23,10 @@ RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify ./run_acir_tests.sh poseid RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk ./run_acir_tests.sh closures_mut_ref # Run a single arbitrary test for separate prove and verify for UltraHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin_ultra_honk ./run_acir_tests.sh 6_array +# Construct and verify a UltraHonk proof for a stack of ACIR programs +RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh fold_basic +# Fold and verify an ACIR program stack +RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # Run a single arbitrary test not involving recursion through bb.js for full Goblin RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through bb.js build, all_cmds flow, to test all cli args. From 5e5784c154e3c65e56610174b2a20ad63c705f6a Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 23 May 2024 15:04:53 +0000 Subject: [PATCH 14/24] update integration tests after merge --- .../dsl/acir_format/acir_integration.test.cpp | 150 +++++++++--------- .../acir_format/acir_to_constraint_buf.hpp | 2 +- 2 files changed, 74 insertions(+), 78 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index c9d113620885..4e886b0bee09 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -1,3 +1,4 @@ +#include "barretenberg/client_ivc/client_ivc.hpp" #ifndef __wasm__ #include "barretenberg/bb/exec_pipe.hpp" #include "barretenberg/common/streams.hpp" @@ -53,11 +54,6 @@ class AcirIntegrationTest : public ::testing::Test { using VerificationKey = Flavor::VerificationKey; Prover prover{ builder }; - // builder.blocks.summarize(); - // info("num gates = ", builder.get_num_gates()); - // info("total circuit size = ", builder.get_total_circuit_size()); - // info("circuit size = ", prover.instance->proving_key.circuit_size); - // info("log circuit size = ", prover.instance->proving_key.log_circuit_size); auto proof = prover.construct_proof(); // Verify Honk proof @@ -111,16 +107,20 @@ class AcirIntegrationTest : public ::testing::Test { -35, }); } -}; -class AcirIntegrationSingleTest : public AcirIntegrationTest, public testing::WithParamInterface { protected: static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); } }; +class AcirIntegrationSingleTest : public AcirIntegrationTest, public testing::WithParamInterface {}; + class AcirIntegrationFoldingTest : public AcirIntegrationTest, public testing::WithParamInterface { protected: - static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); } + static void SetUpTestSuite() + { + srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } }; TEST_P(AcirIntegrationSingleTest, ProveAndVerifyProgram) @@ -367,76 +367,72 @@ TEST_P(AcirIntegrationFoldingTest, ProveAndVerifyProgramStack) } } +TEST_P(AcirIntegrationFoldingTest, FoldAndVerifyProgramStack) +{ + using Flavor = GoblinUltraFlavor; + using Builder = Flavor::CircuitBuilder; + + std::string test_name = GetParam(); + auto program_stack = get_program_stack_data_from_test_file(test_name); + + ClientIVC ivc; + ivc.structured_flag = true; + + while (!program_stack.empty()) { + auto program = program_stack.back(); + + // Construct a bberg circuit from the acir representation + auto circuit = + acir_format::create_circuit(program.constraints, 0, program.witness, false, ivc.goblin.op_queue); + + ivc.accumulate(circuit); + + CircuitChecker::check(circuit); + // EXPECT_TRUE(prove_and_verify_honk(ivc.prover_instance)); + + program_stack.pop_back(); + } + + EXPECT_TRUE(ivc.prove_and_verify()); +} + INSTANTIATE_TEST_SUITE_P(AcirTests, AcirIntegrationFoldingTest, - testing::Values("fold_after_inlined_calls", - "fold_basic", - "fold_basic_nested_call", - "fold_call_witness_condition", - "fold_complex_outputs", - "fold_distinct_return", - "fold_fibonacci", - "fold_numeric_generic_poseidon")); - -// TEST_F(AcirIntegrationTests, FoldAndVerifyProgramStack) -// { -// using Flavor = GoblinUltraFlavor; -// using Builder = Flavor::CircuitBuilder; - -// std::string test_name = "fold_basic"; -// auto program_stack = get_program_stack_data_from_test_file(test_name); - -// ClientIVC ivc; -// ivc.structured_flag = true; - -// while (!program_stack.empty()) { -// info("Program:"); -// auto program = program_stack.back(); - -// // Construct a bberg circuit from the acir representation -// auto circuit = -// acir_format::create_circuit(program.constraints, 0, program.witness, false, -// ivc.goblin.op_queue); - -// ivc.accumulate(circuit); - -// CircuitChecker::check(circuit); -// // EXPECT_TRUE(prove_and_verify_honk(ivc.prover_instance)); - -// program_stack.pop_back(); -// } - -// EXPECT_TRUE(ivc.prove_and_verify()); -// } - -// TEST_F(AcirIntegrationTests, UpdateAcirCircuit) -// { -// using Flavor = GoblinUltraFlavor; -// using Builder = Flavor::CircuitBuilder; - -// std::string test_name = "6_array"; -// auto acir_program = get_program_data_from_test_file(test_name); - -// // Construct a bberg circuit from the acir representation -// auto circuit = acir_format::create_circuit(acir_program.constraints, 0, acir_program.witness); - -// EXPECT_TRUE(CircuitChecker::check(circuit)); - -// // Now we'll append some addition gates onto the circuit generated from acir and confirm that its still valid. -// // First, check that the simple circuit is valid in isolation -// { -// Builder simple_circuit; -// add_some_simple_RAM_gates(circuit); -// EXPECT_TRUE(CircuitChecker::check(simple_circuit)); -// EXPECT_TRUE(prove_and_verify_honk(simple_circuit)); -// } - -// // Now manually append the simple RAM circuit to the circuit generated from acir -// add_some_simple_RAM_gates(circuit); - -// // Confirm that the result is still valid -// EXPECT_TRUE(CircuitChecker::check(circuit)); -// EXPECT_TRUE(prove_and_verify_honk(circuit)); -// } + testing::Values("fold_basic", "fold_basic_nested_call")); + +/** + * @brief Ensure that adding gates post-facto to a circuit generated from acir still results in a valid circuit + * @details This is a pattern required by e.g. ClientIvc which appends recursive verifiers to acir-generated circuits + * + */ +TEST_F(AcirIntegrationTest, UpdateAcirCircuit) +{ + using Flavor = GoblinUltraFlavor; + using Builder = Flavor::CircuitBuilder; + + std::string test_name = "6_array"; // arbitrary program with RAM gates + auto acir_program = get_program_data_from_test_file(test_name); + + // Construct a bberg circuit from the acir representation + auto circuit = acir_format::create_circuit(acir_program.constraints, 0, acir_program.witness); + + EXPECT_TRUE(CircuitChecker::check(circuit)); + + // Now we'll append some addition gates onto the circuit generated from acir and confirm that its still valid. + // First, check that the simple circuit is valid in isolation + { + Builder simple_circuit; + add_some_simple_RAM_gates(circuit); + EXPECT_TRUE(CircuitChecker::check(simple_circuit)); + EXPECT_TRUE(prove_and_verify_honk(simple_circuit)); + } + + // Now manually append the simple RAM circuit to the circuit generated from acir + add_some_simple_RAM_gates(circuit); + + // Confirm that the result is still valid + EXPECT_TRUE(CircuitChecker::check(circuit)); + EXPECT_TRUE(prove_and_verify_honk(circuit)); +} #endif diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index 493baa2f515a..eebb97dfc208 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -10,7 +10,7 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf); * @brief Converts from the ACIR-native `WitnessMap` format to Barretenberg's internal `WitnessVector` format. * * @param buf Serialized representation of a `WitnessMap`. - * @return A `WitnessVector` equivalent to the passed `WitnessMap`.xo + * @return A `WitnessVector` equivalent to the passed `WitnessMap`. * @note This transformation results in all unassigned witnesses within the `WitnessMap` being assigned the value 0. * Converting the `WitnessVector` back to a `WitnessMap` is unlikely to return the exact same `WitnessMap`. */ From adcbe99ee0695d39603fb28941a5f50fef0c4980 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 23 May 2024 15:28:03 +0000 Subject: [PATCH 15/24] fix binding --- barretenberg/exports.json | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/barretenberg/exports.json b/barretenberg/exports.json index fbd55c714b34..72c41343b8e3 100644 --- a/barretenberg/exports.json +++ b/barretenberg/exports.json @@ -880,26 +880,6 @@ ], "isAsync": false }, - { - "functionName": "acir_prove_ultra_honk", - "inArgs": [ - { - "name": "acir_vec", - "type": "const uint8_t *" - }, - { - "name": "witness_vec", - "type": "const uint8_t *" - } - ], - "outArgs": [ - { - "name": "out", - "type": "uint8_t **" - } - ], - "isAsync": false - }, { "functionName": "acir_verify_ultra_honk", "inArgs": [ From 0cacb521b2bebe0e5f7c0df5a7d40481f7cff2a7 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 23 May 2024 16:33:15 +0000 Subject: [PATCH 16/24] fix CI setup --- barretenberg/Earthfile | 2 +- barretenberg/acir_tests/Dockerfile.bb.js | 4 ++-- barretenberg/acir_tests/run_acir_tests.sh | 4 ++-- barretenberg/ts/src/main.ts | 26 +++++++++++++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/barretenberg/Earthfile b/barretenberg/Earthfile index d2f287513ef1..09e3c0b1bb68 100644 --- a/barretenberg/Earthfile +++ b/barretenberg/Earthfile @@ -39,7 +39,7 @@ barretenberg-acir-tests-bb: # Construct and verify a UltraHonk proof for all ACIR programs using the new witness stack workflow RUN FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh # Fold and verify an ACIR program stack using ClientIvc - RUN FLOW=fold_and_verify_program ./run_acir_tests.sh + RUN FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # This is a "full" Goblin flow. It constructs and verifies four proofs: GoblinUltraHonk, ECCVM, Translator, and merge RUN FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through native bb build, all_cmds flow, to test all cli args. diff --git a/barretenberg/acir_tests/Dockerfile.bb.js b/barretenberg/acir_tests/Dockerfile.bb.js index 8ea436cf9170..8a07e0ef5baf 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -23,8 +23,8 @@ RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify ./run_acir_tests.sh poseid RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk ./run_acir_tests.sh closures_mut_ref # Run a single arbitrary test for separate prove and verify for UltraHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin_ultra_honk ./run_acir_tests.sh 6_array -# Construct and verify a UltraHonk proof for a stack of ACIR programs -RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh fold_basic +# # Construct and verify a UltraHonk proof for a stack of ACIR programs +# RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh fold_basic # Fold and verify an ACIR program stack RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # Run a single arbitrary test not involving recursion through bb.js for full Goblin diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 677c86fe01d9..b66970bbcc1f 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -11,10 +11,10 @@ source ./bash_helpers/catch.sh trap handle_sigchild SIGCHLD BIN=${BIN:-../cpp/build/bin/bb} -# FLOW=${FLOW:-prove_and_verify} +FLOW=${FLOW:-prove_and_verify} # FLOW=${FLOW:-prove_and_verify_ultra_honk_program} # FLOW=${FLOW:-prove_and_verify_goblin_ultra_honk_program} -FLOW=${FLOW:-fold_and_verify_program} +# FLOW=${FLOW:-fold_and_verify_program} CRS_PATH=~/.bb-crs BRANCH=master VERBOSE=${VERBOSE:-} diff --git a/barretenberg/ts/src/main.ts b/barretenberg/ts/src/main.ts index 8e07dceb8c02..4de6ab44341e 100755 --- a/barretenberg/ts/src/main.ts +++ b/barretenberg/ts/src/main.ts @@ -166,6 +166,21 @@ export async function proveAndVerifyGoblinUltraHonk(bytecodePath: string, witnes /* eslint-enable camelcase */ } +export async function foldAndVerifyProgram(bytecodePath: string, witnessPath: string, crsPath: string) { + /* eslint-disable camelcase */ + const { api } = await init(bytecodePath, crsPath); + try { + const bytecode = getBytecode(bytecodePath); + const witness = getWitness(witnessPath); + + const verified = await api.acirFoldAndVerifyProgramStack(bytecode, witness); + return verified; + } finally { + await api.destroy(); + } + /* eslint-enable camelcase */ +} + export async function proveAndVerifyGoblin(bytecodePath: string, witnessPath: string, crsPath: string) { /* eslint-disable camelcase */ const acir_test = path.basename(process.cwd()); @@ -492,6 +507,17 @@ program process.exit(result ? 0 : 1); }); +program + .command('fold_and_verify_program') + .description('Generate a GUH proof and verify it. Process exits with success or failure code.') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') + .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') + .action(async ({ bytecodePath, witnessPath, crsPath }) => { + handleGlobalOptions(); + const result = await foldAndVerifyProgram(bytecodePath, witnessPath, crsPath); + process.exit(result ? 0 : 1); + }); + program .command('prove_and_verify_goblin') .description('Generate a Goblin proof and verify it. Process exits with success or failure code.') From bea3d67fb637d7273ed2618a47c6d56d86dde5af Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 23 May 2024 17:22:50 +0000 Subject: [PATCH 17/24] clean up --- barretenberg/acir_tests/Dockerfile.bb.js | 2 -- barretenberg/acir_tests/run_acir_tests.sh | 3 --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 13 ++----------- .../src/barretenberg/client_ivc/client_ivc.cpp | 4 ++-- .../barretenberg/client_ivc/client_ivc.test.cpp | 2 +- .../dsl/acir_format/acir_integration.test.cpp | 16 ---------------- .../cpp/src/barretenberg/goblin/goblin.hpp | 9 +++++---- 7 files changed, 10 insertions(+), 39 deletions(-) diff --git a/barretenberg/acir_tests/Dockerfile.bb.js b/barretenberg/acir_tests/Dockerfile.bb.js index 8a07e0ef5baf..aa07f2df7e58 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -23,8 +23,6 @@ RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify ./run_acir_tests.sh poseid RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk ./run_acir_tests.sh closures_mut_ref # Run a single arbitrary test for separate prove and verify for UltraHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin_ultra_honk ./run_acir_tests.sh 6_array -# # Construct and verify a UltraHonk proof for a stack of ACIR programs -# RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh fold_basic # Fold and verify an ACIR program stack RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # Run a single arbitrary test not involving recursion through bb.js for full Goblin diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index b66970bbcc1f..0e360a895514 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -12,9 +12,6 @@ trap handle_sigchild SIGCHLD BIN=${BIN:-../cpp/build/bin/bb} FLOW=${FLOW:-prove_and_verify} -# FLOW=${FLOW:-prove_and_verify_ultra_honk_program} -# FLOW=${FLOW:-prove_and_verify_goblin_ultra_honk_program} -# FLOW=${FLOW:-fold_and_verify_program} CRS_PATH=~/.bb-crs BRANCH=master VERBOSE=${VERBOSE:-} diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 1f7286b1cb7c..66730eae4771 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -171,9 +171,6 @@ bool proveAndVerifyHonkAcirFormat(acir_format::AcirFormat constraint_system, aci // Construct Honk proof Prover prover{ builder }; - builder.blocks.summarize(); - info("num gates = ", builder.get_num_gates()); - info("circuit size = ", prover.instance->proving_key.circuit_size); auto proof = prover.construct_proof(); // Verify Honk proof @@ -240,16 +237,10 @@ bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& wi auto stack_item = program_stack.back(); // Construct a bberg circuit from the acir representation - auto builder = acir_format::create_circuit( + auto circuit = acir_format::create_circuit( stack_item.constraints, 0, stack_item.witness, false, ivc.goblin.op_queue); - ivc.accumulate(builder); - - // builder.blocks.summarize(); - - // // Construct Honk proof - // info("gates = ", builder.get_num_gates()); - // info("circuit size = ", ivc.prover_instance->proving_key.circuit_size); + ivc.accumulate(circuit); program_stack.pop_back(); } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 117a2bf52f7e..5c63d127f993 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -119,8 +119,8 @@ std::vector> ClientIVC::precompute_f /** * @brief Construct and verify a proof for the IVC - * @details This is intended to be a development/testing only method since in general the prover and verifier will be - * different entities. + * @note Use of this method only makes sense when the prover and verifier are the same entity, e.g. in + * development/testsing. * */ bool ClientIVC::prove_and_verify() diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index eab54163aef6..a2c68a10fd92 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -121,7 +121,7 @@ TEST_F(ClientIVCTests, DISABLED_BasicLarge) size_t NUM_CIRCUITS = 5; std::vector circuits; for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { - circuits.emplace_back(create_mock_circuit(ivc, 4)); + circuits.emplace_back(create_mock_circuit(ivc)); } // Accumulate each circuit diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 4e886b0bee09..3486d9f92a0a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -63,22 +63,6 @@ class AcirIntegrationTest : public ::testing::Test { return verifier.verify_proof(proof); } - template bool prove_and_verify_honk(std::shared_ptr> prover_instance) - { - using Prover = UltraProver_; - using Verifier = UltraVerifier_; - using VerificationKey = Flavor::VerificationKey; - - Prover prover{ prover_instance }; - auto proof = prover.construct_proof(); - - // Verify Honk proof - auto verification_key = std::make_shared(prover.instance->proving_key); - Verifier verifier{ verification_key }; - - return verifier.verify_proof(proof); - } - void add_some_simple_RAM_gates(auto& circuit) { std::array ram_values{ circuit.add_variable(5), diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 0a9107e7e28c..dcea95e5d24a 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -147,10 +147,11 @@ class Goblin { [[maybe_unused]] auto pairing_points = merge_verifier.verify_proof(merge_proof); } - // TODO(https://github.com/AztecProtocol/barretenberg/issues/993): On the first call to accumulate, the input - // circuit generated from acir has no goblin ecc ops prior to the call to merge(), so the commitment to the new - // contribution (C_t_shift) will be the point at infinity. (Some ops are added in 'add_gates_to_ensure...' but - // not until instance construction which comes later). + // TODO(https://github.com/AztecProtocol/barretenberg/issues/993): Some circuits (particularly on the first call + // to accumulate) may not have any goblin ecc ops prior to the call to merge(), so the commitment to the new + // contribution (C_t_shift) in the merge prover will be the point at infinity. (Note: Some dummy ops are added + // in 'add_gates_to_ensure...' but not until instance construction which comes later). See issue for ideas about + // how to resolve. if (circuit_builder.blocks.ecc_op.size() == 0) { MockCircuits::construct_goblin_ecc_op_circuit(circuit_builder); // Add some arbitrary goblin ECC ops } From bba7d2da04237fabaa121ec0a67674d99c6a1b76 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 24 May 2024 14:49:01 +0000 Subject: [PATCH 18/24] clean up --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 1 + .../cpp/src/barretenberg/client_ivc/client_ivc.cpp | 2 +- .../dsl/acir_format/acir_integration.test.cpp | 10 +++++----- barretenberg/ts/src/main.ts | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 66730eae4771..a792167f7c58 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -233,6 +233,7 @@ bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& wi auto program_stack = acir_format::get_acir_program_stack(bytecodePath, witnessPath); + // Accumulate the entire program stack into the IVC while (!program_stack.empty()) { auto stack_item = program_stack.back(); diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 5c63d127f993..af9f0c2e4e8c 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -120,7 +120,7 @@ std::vector> ClientIVC::precompute_f /** * @brief Construct and verify a proof for the IVC * @note Use of this method only makes sense when the prover and verifier are the same entity, e.g. in - * development/testsing. + * development/testing. * */ bool ClientIVC::prove_and_verify() diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 3486d9f92a0a..a72d75c91d82 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -402,13 +402,13 @@ TEST_F(AcirIntegrationTest, UpdateAcirCircuit) EXPECT_TRUE(CircuitChecker::check(circuit)); - // Now we'll append some addition gates onto the circuit generated from acir and confirm that its still valid. - // First, check that the simple circuit is valid in isolation + // Now append some RAM gates onto the circuit generated from acir and confirm that its still valid. (First, check + // that the RAM operations constitute a valid independent circuit). { - Builder simple_circuit; + Builder circuit; add_some_simple_RAM_gates(circuit); - EXPECT_TRUE(CircuitChecker::check(simple_circuit)); - EXPECT_TRUE(prove_and_verify_honk(simple_circuit)); + EXPECT_TRUE(CircuitChecker::check(circuit)); + EXPECT_TRUE(prove_and_verify_honk(circuit)); } // Now manually append the simple RAM circuit to the circuit generated from acir diff --git a/barretenberg/ts/src/main.ts b/barretenberg/ts/src/main.ts index 4de6ab44341e..f2bfa81cbda6 100755 --- a/barretenberg/ts/src/main.ts +++ b/barretenberg/ts/src/main.ts @@ -509,7 +509,7 @@ program program .command('fold_and_verify_program') - .description('Generate a GUH proof and verify it. Process exits with success or failure code.') + .description('Accumulate a set of circuits using ClientIvc then verify. Process exits with success or failure code.') .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .action(async ({ bytecodePath, witnessPath, crsPath }) => { From 233ff93d7c199a76ebd5beb3263062b2790a2745 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 24 May 2024 20:24:13 +0000 Subject: [PATCH 19/24] mega name fix --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 4 ++-- .../barretenberg/dsl/acir_format/acir_integration.test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 722cb1b01d7d..8e83874769a4 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -222,7 +222,7 @@ bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::strin bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& witnessPath) { - using Flavor = GoblinUltraFlavor; // This is the only option + using Flavor = MegaFlavor; // This is the only option using Builder = Flavor::CircuitBuilder; init_bn254_crs(1 << 18); @@ -862,7 +862,7 @@ int main(int argc, char* argv[]) return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; } if (command == "prove_and_verify_goblin_ultra_honk_program") { - return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; + return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; } if (command == "fold_and_verify_program") { return foldAndVerifyProgram(bytecode_path, witness_path) ? 0 : 1; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index decb997cc49c..936c35cc44cc 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -353,7 +353,7 @@ TEST_P(AcirIntegrationFoldingTest, ProveAndVerifyProgramStack) TEST_P(AcirIntegrationFoldingTest, FoldAndVerifyProgramStack) { - using Flavor = GoblinUltraFlavor; + using Flavor = MegaFlavor; using Builder = Flavor::CircuitBuilder; std::string test_name = GetParam(); @@ -391,7 +391,7 @@ INSTANTIATE_TEST_SUITE_P(AcirTests, */ TEST_F(AcirIntegrationTest, UpdateAcirCircuit) { - using Flavor = GoblinUltraFlavor; + using Flavor = MegaFlavor; using Builder = Flavor::CircuitBuilder; std::string test_name = "6_array"; // arbitrary program with RAM gates From 7d035077cdb57a91bba9039df394134ccbaef13c Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 24 May 2024 21:10:03 +0000 Subject: [PATCH 20/24] disable tests at risk for intermittent failure --- barretenberg/Earthfile | 3 ++- barretenberg/acir_tests/Dockerfile.bb.js | 3 ++- .../src/barretenberg/dsl/acir_format/acir_integration.test.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/barretenberg/Earthfile b/barretenberg/Earthfile index 724bd6f4bd55..e5190da35136 100644 --- a/barretenberg/Earthfile +++ b/barretenberg/Earthfile @@ -39,7 +39,8 @@ barretenberg-acir-tests-bb: # Construct and verify a UltraHonk proof for all ACIR programs using the new witness stack workflow RUN FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh # Fold and verify an ACIR program stack using ClientIvc - RUN FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic + # TODO(https://github.com/AztecProtocol/barretenberg/issues/1003): reinstate when ClientIvc fixed. + # RUN FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # This is a "full" Goblin flow. It constructs and verifies four proofs: MegaHonk, ECCVM, Translator, and merge RUN FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through native bb build, all_cmds flow, to test all cli args. diff --git a/barretenberg/acir_tests/Dockerfile.bb.js b/barretenberg/acir_tests/Dockerfile.bb.js index 573ed5efd877..54b79226ad91 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -24,7 +24,8 @@ RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk ./run_acir_test # Run a single arbitrary test for separate prove and verify for MegaHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_mega_honk ./run_acir_tests.sh 6_array # Fold and verify an ACIR program stack -RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic +# TODO(https://github.com/AztecProtocol/barretenberg/issues/1003): reinstate when ClientIvc is fixed. +# RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # Run a single arbitrary test not involving recursion through bb.js for full Goblin RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through bb.js build, all_cmds flow, to test all cli args. diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 936c35cc44cc..957fe3abc3fd 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -351,7 +351,8 @@ TEST_P(AcirIntegrationFoldingTest, ProveAndVerifyProgramStack) } } -TEST_P(AcirIntegrationFoldingTest, FoldAndVerifyProgramStack) +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1003): Reinstate when ClientIvc is fixed. +TEST_P(AcirIntegrationFoldingTest, DISABLED_FoldAndVerifyProgramStack) { using Flavor = MegaFlavor; using Builder = Flavor::CircuitBuilder; From a41fe29238052a0c616e1632d5c134346e82a1a7 Mon Sep 17 00:00:00 2001 From: codygunton Date: Mon, 27 May 2024 15:58:16 +0000 Subject: [PATCH 21/24] Address issue 1003 --- barretenberg/Earthfile | 3 +-- barretenberg/acir_tests/Dockerfile.bb.js | 3 +-- .../src/barretenberg/dsl/acir_format/acir_integration.test.cpp | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/barretenberg/Earthfile b/barretenberg/Earthfile index e5190da35136..724bd6f4bd55 100644 --- a/barretenberg/Earthfile +++ b/barretenberg/Earthfile @@ -39,8 +39,7 @@ barretenberg-acir-tests-bb: # Construct and verify a UltraHonk proof for all ACIR programs using the new witness stack workflow RUN FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh # Fold and verify an ACIR program stack using ClientIvc - # TODO(https://github.com/AztecProtocol/barretenberg/issues/1003): reinstate when ClientIvc fixed. - # RUN FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic + RUN FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # This is a "full" Goblin flow. It constructs and verifies four proofs: MegaHonk, ECCVM, Translator, and merge RUN FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through native bb build, all_cmds flow, to test all cli args. diff --git a/barretenberg/acir_tests/Dockerfile.bb.js b/barretenberg/acir_tests/Dockerfile.bb.js index 54b79226ad91..573ed5efd877 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -24,8 +24,7 @@ RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk ./run_acir_test # Run a single arbitrary test for separate prove and verify for MegaHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_mega_honk ./run_acir_tests.sh 6_array # Fold and verify an ACIR program stack -# TODO(https://github.com/AztecProtocol/barretenberg/issues/1003): reinstate when ClientIvc is fixed. -# RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic +RUN BIN=../ts/dest/node/main.js FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic # Run a single arbitrary test not involving recursion through bb.js for full Goblin RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through bb.js build, all_cmds flow, to test all cli args. diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 957fe3abc3fd..89fe265f5ded 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -351,7 +351,6 @@ TEST_P(AcirIntegrationFoldingTest, ProveAndVerifyProgramStack) } } -// TODO(https://github.com/AztecProtocol/barretenberg/issues/1003): Reinstate when ClientIvc is fixed. TEST_P(AcirIntegrationFoldingTest, DISABLED_FoldAndVerifyProgramStack) { using Flavor = MegaFlavor; From e7ace4a8bf53fe2000397b43f2281f472bf197ba Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 28 May 2024 14:46:19 +0000 Subject: [PATCH 22/24] update mega naming --- .../flows/prove_and_verify_goblin_ultra_honk_program.sh | 6 ------ .../acir_tests/flows/prove_and_verify_mega_honk_program.sh | 6 ++++++ barretenberg/cpp/src/barretenberg/bb/main.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100755 barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh create mode 100755 barretenberg/acir_tests/flows/prove_and_verify_mega_honk_program.sh diff --git a/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh b/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh deleted file mode 100755 index c34d2e545298..000000000000 --- a/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk_program.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -eu - -VFLAG=${VERBOSE:+-v} - -$BIN prove_and_verify_goblin_ultra_honk_program $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/acir_tests/flows/prove_and_verify_mega_honk_program.sh b/barretenberg/acir_tests/flows/prove_and_verify_mega_honk_program.sh new file mode 100755 index 000000000000..21e15fbf7c53 --- /dev/null +++ b/barretenberg/acir_tests/flows/prove_and_verify_mega_honk_program.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +VFLAG=${VERBOSE:+-v} + +$BIN prove_and_verify_mega_honk_program $VFLAG -c $CRS_PATH -b ./target/program.json diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 8e83874769a4..091c87ad0cb1 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -861,7 +861,7 @@ int main(int argc, char* argv[]) if (command == "prove_and_verify_ultra_honk_program") { return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; } - if (command == "prove_and_verify_goblin_ultra_honk_program") { + if (command == "prove_and_verify_mega_honk_program") { return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; } if (command == "fold_and_verify_program") { From 922d83ec873213c84efb0753a947f45ef8a66861 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 28 May 2024 15:42:44 +0000 Subject: [PATCH 23/24] update name --- barretenberg/acir_tests/Dockerfile.bb.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/acir_tests/Dockerfile.bb.js b/barretenberg/acir_tests/Dockerfile.bb.js index 59c4e5d2cd03..dd5269e69026 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -21,7 +21,7 @@ RUN BIN=../ts/dest/node/main.js FLOW=prove_then_verify ./run_acir_tests.sh ecdsa RUN BIN=../ts/dest/node/main.js FLOW=prove_then_verify_ultra_honk ./run_acir_tests.sh nested_array_dynamic # Run a single arbitrary test not involving recursion through bb.js for Plonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify ./run_acir_tests.sh poseidon_bn254_hash -# Run a single arbitrary test not involving recursion through bb.js for MegaHonk +# Run a single arbitrary test not involving recursion through bb.js for UltraHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_ultra_honk ./run_acir_tests.sh closures_mut_ref # Run a single arbitrary test for separate prove and verify for MegaHonk RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_mega_honk ./run_acir_tests.sh 6_array From ffc362270a89084d92c9a56a7a6c5a3f0059bf29 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 28 May 2024 16:39:36 +0000 Subject: [PATCH 24/24] disable last integration test --- .../src/barretenberg/dsl/acir_format/acir_integration.test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 468691e4293b..33045c675cd7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -422,7 +422,7 @@ INSTANTIATE_TEST_SUITE_P(AcirTests, * @details This is a pattern required by e.g. ClientIvc which appends recursive verifiers to acir-generated circuits * */ -TEST_F(AcirIntegrationTest, UpdateAcirCircuit) +TEST_F(AcirIntegrationTest, DISABLED_UpdateAcirCircuit) { using Flavor = MegaFlavor; using Builder = Flavor::CircuitBuilder;