From a2d138fa8c0ecf90bea843d38d2d693d6a38b2cc Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Thu, 21 Mar 2024 13:52:30 -0700 Subject: [PATCH] feat: simplified bb Honk interface (#5319) Purpose of this PR is to clarify and simplify the bb interface for constructing and verifying Honk proofs (both UltraHonk and GoblinUltraHonk). A similar flow was previously achieved somewhat indirectly through the `goblin` class via `goblin.accumulate`. This was simply done for convenience a while back and is not the right thing long term. The new Honk flows are simplified and do not make use of anything like the `AcirComposer` used for Plonk. I have only added flows of the prove-AND-verify variety, i.e. more logic will be needed in order to separate out the proving and verifying (a la the prove-THEN-verify flows for Plonk). This includes serialization of proving and verification keys. --- barretenberg/acir_tests/Dockerfile.bb | 7 +- barretenberg/acir_tests/Dockerfile.bb.js | 4 +- .../flows/accumulate_and_verify_goblin.sh | 6 -- .../prove_and_verify_goblin_ultra_honk.sh | 6 ++ .../flows/prove_and_verify_ultra_honk.sh | 6 ++ barretenberg/cpp/src/barretenberg/bb/main.cpp | 54 ++++++++------- .../dsl/acir_format/acir_format.cpp | 42 ++++++++++-- .../barretenberg/dsl/acir_proofs/c_bind.cpp | 47 +++++++------ .../barretenberg/dsl/acir_proofs/c_bind.hpp | 24 +++---- .../dsl/acir_proofs/goblin_acir_composer.cpp | 19 ------ .../dsl/acir_proofs/goblin_acir_composer.hpp | 16 ----- .../goblin_ultra_circuit_builder.hpp | 2 +- barretenberg/exports.json | 46 ++++++------- barretenberg/ts/src/barretenberg_api/index.ts | 68 +++++++++---------- barretenberg/ts/src/main.ts | 46 ++++++++----- 15 files changed, 206 insertions(+), 187 deletions(-) delete mode 100755 barretenberg/acir_tests/flows/accumulate_and_verify_goblin.sh create mode 100755 barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh create mode 100755 barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh diff --git a/barretenberg/acir_tests/Dockerfile.bb b/barretenberg/acir_tests/Dockerfile.bb index f7123707612..60144b8a707 100644 --- a/barretenberg/acir_tests/Dockerfile.bb +++ b/barretenberg/acir_tests/Dockerfile.bb @@ -10,9 +10,10 @@ COPY . . # Run every acir test through native bb build prove_then_verify flow for UltraPlonk. # This ensures we test independent pk construction through real/garbage witness data paths. RUN FLOW=prove_then_verify ./run_acir_tests.sh -# This flow is essentially the GoblinUltraHonk equivalent to the UltraPlonk "prove and verify". (This functionality is -# accessed via the goblin "accumulate" mechanism). -RUN FLOW=accumulate_and_verify_goblin ./run_acir_tests.sh +# Construct and verify a UltraHonk proof for all acir programs +RUN FLOW=prove_and_verify_ultra_honk ./run_acir_tests.sh +# Construct and verify a Goblin UltraHonk (GUH) proof for a single arbitrary program +RUN FLOW=prove_and_verify_goblin_ultra_honk ./run_acir_tests.sh 6_array # 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 d797fe8bed9..e0838949964 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -15,8 +15,10 @@ COPY . . ENV VERBOSE=1 # Run double_verify_proof through bb.js on node to check 512k support. RUN BIN=../ts/dest/node/main.js FLOW=prove_then_verify ./run_acir_tests.sh double_verify_proof +# 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 6_array # Run a single arbitrary test not involving recursion through bb.js for GoblinUltraHonk -RUN BIN=../ts/dest/node/main.js FLOW=accumulate_and_verify_goblin ./run_acir_tests.sh 6_array +RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin_ultra_honk ./run_acir_tests.sh 6_array # 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/acir_tests/flows/accumulate_and_verify_goblin.sh b/barretenberg/acir_tests/flows/accumulate_and_verify_goblin.sh deleted file mode 100755 index a89e1a1dba1..00000000000 --- a/barretenberg/acir_tests/flows/accumulate_and_verify_goblin.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -eu - -VFLAG=${VERBOSE:+-v} - -$BIN accumulate_and_verify_goblin $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file diff --git a/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh new file mode 100755 index 00000000000..a8a72924898 --- /dev/null +++ b/barretenberg/acir_tests/flows/prove_and_verify_goblin_ultra_honk.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +VFLAG=${VERBOSE:+-v} + +$BIN prove_and_verify_goblin_ultra_honk $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file diff --git a/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh new file mode 100755 index 00000000000..7b6f0384796 --- /dev/null +++ b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +VFLAG=${VERBOSE:+-v} + +$BIN prove_and_verify_ultra_honk $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 17c465945f1..34e4ef0fe4c 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -128,40 +128,41 @@ bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessP } /** - * @brief Constructs and verifies a Honk proof for an ACIR circuit via the Goblin accumulate mechanism + * @brief Constructs and verifies a Honk proof for an acir-generated circuit * - * Communication: - * - proc_exit: A boolean value is returned indicating whether the proof is valid. - * an exit code of 0 will be returned for success and 1 for failure. - * - * @param bytecodePath Path to the file containing the serialized acir constraint system - * @param witnessPath Path to the file containing the serialized witness - * @return verified + * @tparam Flavor + * @param bytecodePath Path to serialized acir circuit data + * @param witnessPath Path to serialized acir witness data */ -bool accumulateAndVerifyGoblin(const std::string& bytecodePath, const std::string& witnessPath) +template bool proveAndVerifyHonk(const std::string& bytecodePath, const std::string& witnessPath) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): Don't hardcode dyadic circuit size. Currently set - // to max circuit size present in acir tests suite. - size_t hardcoded_bn254_dyadic_size_hack = 1 << 19; - init_bn254_crs(hardcoded_bn254_dyadic_size_hack); - size_t hardcoded_grumpkin_dyadic_size_hack = 1 << 10; // For eccvm only - init_grumpkin_crs(hardcoded_grumpkin_dyadic_size_hack); + using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = Flavor::VerificationKey; // Populate the acir constraint system and witness from gzipped data auto constraint_system = get_constraint_system(bytecodePath); auto witness = get_witness(witnessPath); - // Instantiate a Goblin acir composer and construct a bberg circuit from the acir representation - acir_proofs::GoblinAcirComposer acir_composer; - acir_composer.create_circuit(constraint_system, witness); + // Construct a bberg circuit from the acir representation + auto builder = acir_format::create_circuit(constraint_system, 0, witness); - // Call accumulate to generate a GoblinUltraHonk proof - auto proof = acir_composer.accumulate(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): Add a buffer to the expected circuit size to + // account for the addition of "gates to ensure nonzero polynomials" (in Honk only). + const size_t additional_gates_buffer = 15; // conservatively large to be safe + size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + additional_gates_buffer); + init_bn254_crs(srs_size); - // Verify the GoblinUltraHonk proof - auto verified = acir_composer.verify_accumulator(proof); + // Construct Honk proof + Prover prover{ builder }; + auto proof = prover.construct_proof(); - return verified; + // Verify Honk proof + auto verification_key = std::make_shared(prover.instance->proving_key); + Verifier verifier{ verification_key }; + + return verifier.verify_proof(proof); } /** @@ -569,8 +570,11 @@ int main(int argc, char* argv[]) if (command == "prove_and_verify") { return proveAndVerify(bytecode_path, witness_path) ? 0 : 1; } - if (command == "accumulate_and_verify_goblin") { - return accumulateAndVerifyGoblin(bytecode_path, witness_path) ? 0 : 1; + if (command == "prove_and_verify_ultra_honk") { + return proveAndVerifyHonk(bytecode_path, witness_path) ? 0 : 1; + } + if (command == "prove_and_verify_goblin_ultra_honk") { + return proveAndVerifyHonk(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/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index f37d1f0bdfc..d8b1e2fdeb7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -1,5 +1,6 @@ #include "acir_format.hpp" #include "barretenberg/common/log.hpp" +#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include @@ -202,7 +203,7 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo } /** - * @brief Create a circuit from acir constraints and optionally a witness + * @brief Specialization for creating Ultra circuit from acir constraints and optionally a witness * * @tparam Builder * @param constraint_system @@ -210,8 +211,8 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo * @param witness * @return Builder */ -template -Builder create_circuit(const AcirFormat& constraint_system, size_t size_hint, WitnessVector const& witness) +template <> +UltraCircuitBuilder create_circuit(const AcirFormat& constraint_system, size_t size_hint, WitnessVector const& witness) { Builder builder{ size_hint, witness, constraint_system.public_inputs, constraint_system.varnum, constraint_system.recursive @@ -221,11 +222,38 @@ Builder create_circuit(const AcirFormat& constraint_system, size_t size_hint, Wi build_constraints(builder, constraint_system, has_valid_witness_assignments); return builder; -} +}; + +/** + * @brief Specialization for creating GoblinUltra circuit from acir constraints and optionally a witness + * + * @tparam Builder + * @param constraint_system + * @param size_hint + * @param witness + * @return Builder + */ +template <> +GoblinUltraCircuitBuilder create_circuit(const AcirFormat& constraint_system, + [[maybe_unused]] size_t size_hint, + WitnessVector const& witness) +{ + // 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 }; + + // Populate constraints in the builder via the data in constraint_system + bool has_valid_witness_assignments = !witness.empty(); + acir_format::build_constraints(builder, constraint_system, has_valid_witness_assignments); + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/817): Add some arbitrary op gates to ensure the + // associated polynomials are non-zero and to give ECCVM and Translator some ECC ops to process. + MockCircuits::construct_goblin_ecc_op_circuit(builder); + + return builder; +}; -template UltraCircuitBuilder create_circuit(const AcirFormat& constraint_system, - size_t size_hint, - WitnessVector const& witness); template void build_constraints(GoblinUltraCircuitBuilder&, AcirFormat const&, bool); } // namespace acir_format 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 7fc9eff28f3..c867bd24847 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -62,21 +62,38 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr, *out = to_heap_buffer(proof_data); } -WASM_EXPORT void acir_goblin_accumulate(in_ptr acir_composer_ptr, - uint8_t const* acir_vec, - uint8_t const* witness_vec, - uint8_t** out) +WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, bool* result) { - auto acir_composer = reinterpret_cast(*acir_composer_ptr); auto constraint_system = acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec)); auto witness = acir_format::witness_buf_to_witness_data(from_buffer>(witness_vec)); - acir_composer->create_circuit(constraint_system, witness); - auto proof = acir_composer->accumulate(); - auto proof_data_buf = to_buffer( - proof); // template parameter needs to be set so that vector deserialization from - // buffer, which reads the size at the beginning can be done properly - *out = to_heap_buffer(proof_data_buf); + auto builder = acir_format::create_circuit(constraint_system, 0, witness); + + UltraProver prover{ builder }; + auto proof = prover.construct_proof(); + + auto verification_key = std::make_shared(prover.instance->proving_key); + UltraVerifier verifier{ verification_key }; + + *result = verifier.verify_proof(proof); +} + +WASM_EXPORT void acir_prove_and_verify_goblin_ultra_honk(uint8_t const* acir_vec, + uint8_t const* witness_vec, + bool* result) +{ + auto constraint_system = acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec)); + auto witness = acir_format::witness_buf_to_witness_data(from_buffer>(witness_vec)); + + auto builder = acir_format::create_circuit(constraint_system, 0, witness); + + GoblinUltraProver prover{ builder }; + auto proof = prover.construct_proof(); + + auto verification_key = std::make_shared(prover.instance->proving_key); + GoblinUltraVerifier verifier{ verification_key }; + + *result = verifier.verify_proof(proof); } WASM_EXPORT void acir_goblin_prove(in_ptr acir_composer_ptr, @@ -127,14 +144,6 @@ WASM_EXPORT void acir_get_proving_key(in_ptr acir_composer_ptr, uint8_t const* a *out = to_heap_buffer(to_buffer(*pk)); } -WASM_EXPORT void acir_goblin_verify_accumulator(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result) -{ - auto acir_composer = reinterpret_cast(*acir_composer_ptr); - auto proof_data_buf = from_buffer>(proof_buf); - auto proof = from_buffer>(proof_data_buf); - *result = acir_composer->verify_accumulator(proof); -} - WASM_EXPORT void acir_goblin_verify(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result) { auto acir_composer = reinterpret_cast(*acir_composer_ptr); 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 4dfc3259947..1c624c96ef3 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp @@ -34,14 +34,20 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr, uint8_t** out); /** - * @brief Perform the goblin accumulate operation - * @details Constructs a GUH proof and possibly handles transcript merge logic + * @brief Construct and verify an UltraHonk proof * */ -WASM_EXPORT void acir_goblin_accumulate(in_ptr acir_composer_ptr, - uint8_t const* constraint_system_buf, - uint8_t const* witness_buf, - uint8_t** out); +WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + bool* result); + +/** + * @brief Construct and verify a GoblinUltraHonk proof + * + */ +WASM_EXPORT void acir_prove_and_verify_goblin_ultra_honk(uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + bool* result); /** * @brief Construct a full goblin proof @@ -63,12 +69,6 @@ WASM_EXPORT void acir_get_proving_key(in_ptr acir_composer_ptr, uint8_t const* a WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result); -/** - * @brief Verifies a GUH proof produced during goblin accumulation - * - */ -WASM_EXPORT void acir_goblin_verify_accumulator(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result); - /** * @brief Verifies a full goblin proof (and the GUH proof produced by accumulation) * diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.cpp index a757d2661f9..5d754a168a7 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.cpp @@ -21,25 +21,6 @@ void GoblinAcirComposer::create_circuit(acir_format::AcirFormat& constraint_syst MockCircuits::construct_goblin_ecc_op_circuit(builder_); } -std::vector GoblinAcirComposer::accumulate() -{ - // // Construct a GUH proof for the circuit via the accumulate mechanism - // return goblin.accumulate_for_acir(builder_); - - // Construct one final GUH proof via the accumulate mechanism - std::vector ultra_proof = goblin.accumulate_for_acir(builder_); - - // Construct a Goblin proof (ECCVM, Translator, Merge); result stored internally - goblin.prove_for_acir(); - - return ultra_proof; -} - -bool GoblinAcirComposer::verify_accumulator(std::vector const& proof) -{ - return goblin.verify_accumulator_for_acir(proof); -} - std::vector GoblinAcirComposer::accumulate_and_prove() { // Construct one final GUH proof via the accumulate mechanism diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.hpp index a533cba1830..534df5d6e44 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/goblin_acir_composer.hpp @@ -24,22 +24,6 @@ class GoblinAcirComposer { */ void create_circuit(acir_format::AcirFormat& constraint_system, acir_format::WitnessVector& witness); - /** - * @brief Accumulate a circuit via Goblin - * @details For the present circuit, construct a GUH proof and the vkey needed to verify it - * - * @return std::vector The GUH proof bytes - */ - std::vector accumulate(); - - /** - * @brief Verify the Goblin accumulator (the GUH proof) using the vkey internal to Goblin - * - * @param proof - * @return bool Whether or not the proof was verified - */ - bool verify_accumulator(std::vector const& proof); - /** * @brief Accumulate a final circuit and construct a full Goblin proof * @details Accumulation means constructing a GUH proof of a single (final) circuit. A full Goblin proof consists of diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index 31f824216f2..28bda7e6f6e 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -72,7 +72,7 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui */ GoblinUltraCircuitBuilder_(std::shared_ptr op_queue_in, auto& witness_values, - std::vector& public_inputs, + const std::vector& public_inputs, size_t varnum) : UltraCircuitBuilder_>(/*size_hint=*/0, witness_values, public_inputs, varnum) , op_queue(op_queue_in) diff --git a/barretenberg/exports.json b/barretenberg/exports.json index 13425b898cd..cffe8b8fd08 100644 --- a/barretenberg/exports.json +++ b/barretenberg/exports.json @@ -599,12 +599,28 @@ "isAsync": false }, { - "functionName": "acir_goblin_accumulate", + "functionName": "acir_prove_and_verify_ultra_honk", "inArgs": [ { - "name": "acir_composer_ptr", - "type": "in_ptr" + "name": "constraint_system_buf", + "type": "const uint8_t *" }, + { + "name": "witness_buf", + "type": "const uint8_t *" + } + ], + "outArgs": [ + { + "name": "result", + "type": "bool *" + } + ], + "isAsync": false + }, + { + "functionName": "acir_prove_and_verify_goblin_ultra_honk", + "inArgs": [ { "name": "constraint_system_buf", "type": "const uint8_t *" @@ -616,8 +632,8 @@ ], "outArgs": [ { - "name": "out", - "type": "uint8_t **" + "name": "result", + "type": "bool *" } ], "isAsync": false @@ -728,26 +744,6 @@ ], "isAsync": false }, - { - "functionName": "acir_goblin_verify_accumulator", - "inArgs": [ - { - "name": "acir_composer_ptr", - "type": "in_ptr" - }, - { - "name": "proof_buf", - "type": "const uint8_t *" - } - ], - "outArgs": [ - { - "name": "result", - "type": "bool *" - } - ], - "isAsync": false - }, { "functionName": "acir_goblin_verify", "inArgs": [ diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index f74134d5467..05d6568cdb7 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -404,15 +404,23 @@ export class BarretenbergApi { return out[0]; } - async acirGoblinAccumulate( - acirComposerPtr: Ptr, - constraintSystemBuf: Uint8Array, - witnessBuf: Uint8Array, - ): Promise { - const inArgs = [acirComposerPtr, constraintSystemBuf, witnessBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BufferDeserializer()]; + async acirProveAndVerifyUltraHonk(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Promise { + const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; + const result = await this.wasm.callWasmExport( + 'acir_prove_and_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 acirProveAndVerifyGoblinUltraHonk(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Promise { + const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; const result = await this.wasm.callWasmExport( - 'acir_goblin_accumulate', + 'acir_prove_and_verify_goblin_ultra_honk', inArgs, outTypes.map(t => t.SIZE_IN_BYTES), ); @@ -496,18 +504,6 @@ export class BarretenbergApi { return out[0]; } - async acirGoblinVerifyAccumulator(acirComposerPtr: Ptr, proofBuf: Uint8Array): Promise { - const inArgs = [acirComposerPtr, proofBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BoolDeserializer()]; - const result = await this.wasm.callWasmExport( - 'acir_goblin_verify_accumulator', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - async acirGoblinVerify(acirComposerPtr: Ptr, proofBuf: Uint8Array): Promise { const inArgs = [acirComposerPtr, proofBuf].map(serializeBufferable); const outTypes: OutputType[] = [BoolDeserializer()]; @@ -948,11 +944,23 @@ export class BarretenbergApiSync { return out[0]; } - acirGoblinAccumulate(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Uint8Array { - const inArgs = [acirComposerPtr, constraintSystemBuf, witnessBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BufferDeserializer()]; + acirProveAndVerifyUltraHonk(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): boolean { + const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; + const result = this.wasm.callWasmExport( + 'acir_prove_and_verify_ultra_honk', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + + acirProveAndVerifyGoblinUltraHonk(constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): boolean { + const inArgs = [constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; const result = this.wasm.callWasmExport( - 'acir_goblin_accumulate', + 'acir_prove_and_verify_goblin_ultra_honk', inArgs, outTypes.map(t => t.SIZE_IN_BYTES), ); @@ -1032,18 +1040,6 @@ export class BarretenbergApiSync { return out[0]; } - acirGoblinVerifyAccumulator(acirComposerPtr: Ptr, proofBuf: Uint8Array): boolean { - const inArgs = [acirComposerPtr, proofBuf].map(serializeBufferable); - const outTypes: OutputType[] = [BoolDeserializer()]; - const result = this.wasm.callWasmExport( - 'acir_goblin_verify_accumulator', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return out[0]; - } - acirGoblinVerify(acirComposerPtr: Ptr, proofBuf: Uint8Array): boolean { const inArgs = [acirComposerPtr, proofBuf].map(serializeBufferable); const outTypes: OutputType[] = [BoolDeserializer()]; diff --git a/barretenberg/ts/src/main.ts b/barretenberg/ts/src/main.ts index ec974fd1c35..6a7d7922f52 100755 --- a/barretenberg/ts/src/main.ts +++ b/barretenberg/ts/src/main.ts @@ -129,28 +129,29 @@ export async function proveAndVerify(bytecodePath: string, witnessPath: string, /* eslint-enable camelcase */ } -export async function accumulateAndVerifyGoblin(bytecodePath: string, witnessPath: string, crsPath: string) { +export async function proveAndVerifyUltraHonk(bytecodePath: string, witnessPath: string, crsPath: string) { /* eslint-disable camelcase */ - const acir_test = path.basename(process.cwd()); - - const { api, acirComposer, circuitSize, subgroupSize } = await initGoblin(bytecodePath, crsPath); + const { api } = await init(bytecodePath, crsPath); try { - debug(`In accumulateAndVerifyGoblin:`); const bytecode = getBytecode(bytecodePath); const witness = getWitness(witnessPath); - writeBenchmark('gate_count', circuitSize, { acir_test, threads }); - writeBenchmark('subgroup_size', subgroupSize, { acir_test, threads }); + const verified = await api.acirProveAndVerifyUltraHonk(bytecode, witness); + return verified; + } finally { + await api.destroy(); + } + /* eslint-enable camelcase */ +} - debug(`acirGoblinAccumulate()`); - const proofTimer = new Timer(); - const proof = await api.acirGoblinAccumulate(acirComposer, bytecode, witness); - writeBenchmark('proof_construction_time', proofTimer.ms(), { acir_test, threads }); +export async function proveAndVerifyGoblinUltraHonk(bytecodePath: string, witnessPath: string, crsPath: string) { + /* eslint-disable camelcase */ + const { api } = await init(bytecodePath, crsPath); + try { + const bytecode = getBytecode(bytecodePath); + const witness = getWitness(witnessPath); - debug(`acirVerifyGoblinProof()`); - const verified = await api.acirGoblinVerifyAccumulator(acirComposer, proof); - debug(`verified: ${verified}`); - console.log({ verified }); + const verified = await api.acirProveAndVerifyGoblinUltraHonk(bytecode, witness); return verified; } finally { await api.destroy(); @@ -380,13 +381,24 @@ program }); program - .command('accumulate_and_verify_goblin') + .command('prove_and_verify_ultra_honk') + .description('Generate an UltraHonk proof and verify it. Process exits with success or failure code.') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') + .action(async ({ bytecodePath, witnessPath, crsPath }) => { + handleGlobalOptions(); + const result = await proveAndVerifyUltraHonk(bytecodePath, witnessPath, crsPath); + process.exit(result ? 0 : 1); + }); + +program + .command('prove_and_verify_goblin_ultra_honk') .description('Generate a GUH proof and verify it. Process exits with success or failure code.') .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .action(async ({ bytecodePath, witnessPath, crsPath }) => { handleGlobalOptions(); - const result = await accumulateAndVerifyGoblin(bytecodePath, witnessPath, crsPath); + const result = await proveAndVerifyGoblinUltraHonk(bytecodePath, witnessPath, crsPath); process.exit(result ? 0 : 1); });