Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Goblin acir composer #4112

Merged
merged 25 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a485b04
split honk acir composer from original
ledwards2225 Jan 17, 2024
44259ee
use accumulate framework for basic GUH
ledwards2225 Jan 17, 2024
735fd29
use accumulate nomenclature
ledwards2225 Jan 17, 2024
ebbc8f7
update to use accumulate nomenclature everywhere
ledwards2225 Jan 18, 2024
f95a12a
update docker files to use accumulate
ledwards2225 Jan 18, 2024
22bfac8
debug prints
ledwards2225 Jan 18, 2024
934e38a
full goblin verifies
ledwards2225 Jan 18, 2024
1402ef7
cleanup and commenting
ledwards2225 Jan 18, 2024
851d430
Add goblin flow to docker
ledwards2225 Jan 18, 2024
f370400
name change honk to goblin
ledwards2225 Jan 18, 2024
8c7ef97
Merge branch 'master' into lde/honk_acir_composer
ledwards2225 Jan 18, 2024
8fc65a4
fix wasm: create goblin acir composer
ledwards2225 Jan 18, 2024
d9f5b67
fix index ts formatting
ledwards2225 Jan 18, 2024
a05e3b4
removed grumpkin from the wrong flow
ledwards2225 Jan 18, 2024
d415de2
js flow for full goblin prove and verify
ledwards2225 Jan 19, 2024
4a14cdc
debug
ledwards2225 Jan 19, 2024
8b71f47
test faking it with accum methods
ledwards2225 Jan 19, 2024
a49026b
Merge branch 'master' into lde/honk_acir_composer
ledwards2225 Jan 19, 2024
52c52a2
WiP debug
ledwards2225 Jan 19, 2024
3c91cdc
Merge branch 'master' into lde/honk_acir_composer
ledwards2225 Jan 19, 2024
28c085c
bring it all together
ledwards2225 Jan 19, 2024
cad7ac7
Merge branch 'master' into lde/honk_acir_composer
ledwards2225 Jan 22, 2024
91fc81e
fix bberg and acir
ledwards2225 Jan 22, 2024
57af750
additional comments
ledwards2225 Jan 22, 2024
f8efa12
Merge branch 'master' into lde/honk_acir_composer
ledwards2225 Jan 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions barretenberg/acir_tests/Dockerfile.bb
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ COPY --from=0 /usr/src/barretenberg/cpp/build /usr/src/barretenberg/cpp/build
COPY --from=noir-acir-tests /usr/src/noir/test_programs /usr/src/noir/test_programs
WORKDIR /usr/src/barretenberg/acir_tests
COPY . .
# Run every acir test through native bb build prove_then_verify flow.
# 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
# TODO(https://github.com/AztecProtocol/barretenberg/issues/811) make this able to run the default test
RUN FLOW=prove_and_verify_goblin ./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
# 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.
RUN VERBOSE=1 FLOW=all_cmds ./run_acir_tests.sh 1_mul
5 changes: 4 additions & 1 deletion barretenberg/acir_tests/Dockerfile.bb.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,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 BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin ./run_acir_tests.sh double_verify_proof
# 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 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.
RUN BIN=../ts/dest/node/main.js FLOW=all_cmds ./run_acir_tests.sh 1_mul
# Run double_verify_proof through bb.js on chrome testing multi-threaded browser support.
Expand Down
6 changes: 6 additions & 0 deletions barretenberg/acir_tests/flows/accumulate_and_verify_goblin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
set -eu

VFLAG=${VERBOSE:+-v}

$BIN accumulate_and_verify_goblin $VFLAG -c $CRS_PATH -b ./target/acir.gz
1 change: 1 addition & 0 deletions barretenberg/acir_tests/run_acir_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ fi

export BIN CRS_PATH VERBOSE BRANCH

# copy the gzipped acir test data from noir/test_programs to barretenberg/acir_tests
./clone_test_vectors.sh

cd acir_tests
Expand Down
51 changes: 46 additions & 5 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <barretenberg/common/timer.hpp>
#include <barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp>
#include <barretenberg/dsl/acir_proofs/acir_composer.hpp>
#include <barretenberg/dsl/acir_proofs/goblin_acir_composer.hpp>
#include <barretenberg/srs/global_crs.hpp>
#include <iostream>
#include <stdexcept>
Expand Down Expand Up @@ -115,6 +116,41 @@ bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessP
return verified;
}

/**
* @brief Constructs and verifies a Honk proof for an ACIR circuit via the Goblin accumulate mechanism
*
* 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
*/
bool accumulateAndVerifyGoblin(const std::string& bytecodePath, const std::string& witnessPath)
{
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);

acir_proofs::GoblinAcirComposer acir_composer;
acir_composer.create_circuit(constraint_system, witness);

// 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 << 18;
init_bn254_crs(hardcoded_bn254_dyadic_size_hack);
size_t hardcoded_grumpkin_dyadic_size_hack = 1 << 10;
init_grumpkin_crs(hardcoded_grumpkin_dyadic_size_hack);

// Call accumulate to generate a GoblinUltraHonk proof
auto proof = acir_composer.accumulate();

// Verify the GoblinUltraHonk proof
auto verified = acir_composer.verify_accumulator(proof);

return verified;
}

/**
* @brief Proves and Verifies an ACIR circuit
*
Expand All @@ -135,19 +171,21 @@ bool proveAndVerifyGoblin(const std::string& bytecodePath,
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);

acir_proofs::AcirComposer acir_composer;
acir_composer.create_goblin_circuit(constraint_system, witness);
acir_proofs::GoblinAcirComposer acir_composer;
acir_composer.create_circuit(constraint_system, witness);

// 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 << 18;
init_bn254_crs(hardcoded_bn254_dyadic_size_hack);
size_t hardcoded_grumpkin_dyadic_size_hack = 1 << 10; // For eccvm only
size_t hardcoded_grumpkin_dyadic_size_hack = 1 << 10;
init_grumpkin_crs(hardcoded_grumpkin_dyadic_size_hack);

auto proof = acir_composer.create_goblin_proof();
// Generate a GoblinUltraHonk proof and a full Goblin proof
auto proof = acir_composer.accumulate_and_prove();

auto verified = acir_composer.verify_goblin_proof(proof);
// Verify the GoblinUltraHonk proof and the full Goblin proof
auto verified = acir_composer.verify(proof);

return verified;
}
Expand Down Expand Up @@ -458,6 +496,9 @@ int main(int argc, char* argv[])
if (command == "prove_and_verify") {
return proveAndVerify(bytecode_path, witness_path, recursive) ? 0 : 1;
}
if (command == "accumulate_and_verify_goblin") {
return accumulateAndVerifyGoblin(bytecode_path, witness_path) ? 0 : 1;
}
if (command == "prove_and_verify_goblin") {
return proveAndVerifyGoblin(bytecode_path, witness_path, recursive) ? 0 : 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "barretenberg/common/throw_or_abort.hpp"
#include "barretenberg/dsl/acir_format/acir_format.hpp"
#include "barretenberg/dsl/types.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"
#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp"
#include "barretenberg/plonk/proof_system/verification_key/sol_gen.hpp"
#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp"
Expand Down Expand Up @@ -61,27 +60,6 @@ std::vector<uint8_t> AcirComposer::create_proof(bool is_recursive)
return proof;
}

void AcirComposer::create_goblin_circuit(acir_format::acir_format& constraint_system,
acir_format::WitnessVector& witness)
{
// Construct a builder using the witness and public input data from acir
goblin_builder_ = acir_format::GoblinBuilder{
goblin.op_queue, witness, constraint_system.public_inputs, constraint_system.varnum
};

// Populate constraints in the builder via the data in constraint_system
acir_format::build_constraints(goblin_builder_, constraint_system, true);

// 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.
GoblinMockCircuits::construct_goblin_ecc_op_circuit(goblin_builder_);
}

std::vector<uint8_t> AcirComposer::create_goblin_proof()
{
return goblin.construct_proof(goblin_builder_);
}

std::shared_ptr<bb::plonk::verification_key> AcirComposer::init_verification_key()
{
if (!proving_key_) {
Expand Down Expand Up @@ -132,11 +110,6 @@ bool AcirComposer::verify_proof(std::vector<uint8_t> const& proof, bool is_recur
}
}

bool AcirComposer::verify_goblin_proof(std::vector<uint8_t> const& proof)
{
return goblin.verify_proof({ proof });
}

std::string AcirComposer::get_solidity_verifier()
{
std::ostringstream stream;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once
#include <barretenberg/dsl/acir_format/acir_format.hpp>
#include <barretenberg/goblin/goblin.hpp>

namespace acir_proofs {

Expand Down Expand Up @@ -38,15 +37,8 @@ class AcirComposer {

std::vector<bb::fr> serialize_verification_key_into_fields();

// Goblin specific methods
void create_goblin_circuit(acir_format::acir_format& constraint_system, acir_format::WitnessVector& witness);
std::vector<uint8_t> create_goblin_proof();
bool verify_goblin_proof(std::vector<uint8_t> const& proof);

private:
acir_format::Builder builder_;
acir_format::GoblinBuilder goblin_builder_;
Goblin goblin;
size_t size_hint_;
std::shared_ptr<bb::plonk::proving_key> proving_key_;
std::shared_ptr<bb::plonk::verification_key> verification_key_;
Expand Down
47 changes: 37 additions & 10 deletions barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "barretenberg/common/serialize.hpp"
#include "barretenberg/common/slab_allocator.hpp"
#include "barretenberg/dsl/acir_format/acir_format.hpp"
#include "barretenberg/dsl/acir_proofs/goblin_acir_composer.hpp"
#include "barretenberg/plonk/proof_system/proving_key/serialize.hpp"
#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp"
#include "barretenberg/srs/global_crs.hpp"
Expand All @@ -26,6 +27,11 @@ WASM_EXPORT void acir_new_acir_composer(uint32_t const* size_hint, out_ptr out)
*out = new acir_proofs::AcirComposer(ntohl(*size_hint));
}

WASM_EXPORT void acir_new_goblin_acir_composer(out_ptr out)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You love to see it.

{
*out = new acir_proofs::GoblinAcirComposer();
}

WASM_EXPORT void acir_delete_acir_composer(in_ptr acir_composer_ptr)
{
delete reinterpret_cast<acir_proofs::AcirComposer*>(*acir_composer_ptr);
Expand Down Expand Up @@ -57,17 +63,31 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr,
*out = to_heap_buffer(proof_data);
}

WASM_EXPORT void acir_create_goblin_proof(in_ptr acir_composer_ptr,
uint8_t const* acir_vec,
uint8_t const* witness_vec,
uint8_t** out)
WASM_EXPORT void acir_goblin_accumulate(in_ptr acir_composer_ptr,
uint8_t const* acir_vec,
uint8_t const* witness_vec,
uint8_t** out)
{
auto acir_composer = reinterpret_cast<acir_proofs::AcirComposer*>(*acir_composer_ptr);
auto acir_composer = reinterpret_cast<acir_proofs::GoblinAcirComposer*>(*acir_composer_ptr);
auto constraint_system = acir_format::circuit_buf_to_acir_format(from_buffer<std::vector<uint8_t>>(acir_vec));
auto witness = acir_format::witness_buf_to_witness_data(from_buffer<std::vector<uint8_t>>(witness_vec));

acir_composer->create_goblin_circuit(constraint_system, witness);
auto proof_data = acir_composer->create_goblin_proof();
acir_composer->create_circuit(constraint_system, witness);
auto proof_data = acir_composer->accumulate();
*out = to_heap_buffer(proof_data);
}

WASM_EXPORT void acir_goblin_prove(in_ptr acir_composer_ptr,
uint8_t const* acir_vec,
uint8_t const* witness_vec,
uint8_t** out)
{
auto acir_composer = reinterpret_cast<acir_proofs::GoblinAcirComposer*>(*acir_composer_ptr);
auto constraint_system = acir_format::circuit_buf_to_acir_format(from_buffer<std::vector<uint8_t>>(acir_vec));
auto witness = acir_format::witness_buf_to_witness_data(from_buffer<std::vector<uint8_t>>(witness_vec));

acir_composer->create_circuit(constraint_system, witness);
auto proof_data = acir_composer->accumulate_and_prove();
*out = to_heap_buffer(proof_data);
}

Expand Down Expand Up @@ -102,11 +122,18 @@ 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_verify_goblin_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result)
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_proofs::AcirComposer*>(*acir_composer_ptr);
auto acir_composer = reinterpret_cast<acir_proofs::GoblinAcirComposer*>(*acir_composer_ptr);
auto proof = from_buffer<std::vector<uint8_t>>(proof_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_proofs::GoblinAcirComposer*>(*acir_composer_ptr);
auto proof = from_buffer<std::vector<uint8_t>>(proof_buf);
*result = acir_composer->verify_goblin_proof(proof);
*result = acir_composer->verify(proof);
}

WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr,
Expand Down
19 changes: 14 additions & 5 deletions barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ WASM_EXPORT void acir_get_circuit_sizes(uint8_t const* constraint_system_buf,

WASM_EXPORT void acir_new_acir_composer(uint32_t const* size_hint, out_ptr out);

WASM_EXPORT void acir_new_goblin_acir_composer(out_ptr out);

WASM_EXPORT void acir_delete_acir_composer(in_ptr acir_composer_ptr);

WASM_EXPORT void acir_create_circuit(in_ptr acir_composer_ptr,
Expand All @@ -32,10 +34,15 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr,
bool const* is_recursive,
uint8_t** out);

WASM_EXPORT void acir_create_goblin_proof(in_ptr acir_composer_ptr,
uint8_t const* constraint_system_buf,
uint8_t const* witness_buf,
uint8_t** out);
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_goblin_prove(in_ptr acir_composer_ptr,
uint8_t const* constraint_system_buf,
uint8_t const* witness_buf,
uint8_t** out);

WASM_EXPORT void acir_load_verification_key(in_ptr acir_composer_ptr, uint8_t const* vk_buf);

Expand All @@ -50,7 +57,9 @@ WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr,
bool const* is_recursive,
bool* result);

WASM_EXPORT void acir_verify_goblin_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result);
WASM_EXPORT void acir_goblin_verify_accumulator(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result);

WASM_EXPORT void acir_goblin_verify(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result);

WASM_EXPORT void acir_get_solidity_verifier(in_ptr acir_composer_ptr, out_str_buf out);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "goblin_acir_composer.hpp"
#include "barretenberg/common/throw_or_abort.hpp"
#include "barretenberg/dsl/acir_format/acir_format.hpp"
#include "barretenberg/dsl/types.hpp"
#include "barretenberg/goblin/mock_circuits.hpp"

namespace acir_proofs {

GoblinAcirComposer::GoblinAcirComposer() {}

void GoblinAcirComposer::create_circuit(acir_format::acir_format& constraint_system,
acir_format::WitnessVector& witness)
{
// Construct a builder using the witness and public input data from acir and with the goblin-owned op_queue
builder_ = acir_format::GoblinBuilder{
goblin.op_queue, witness, constraint_system.public_inputs, constraint_system.varnum
};

// Populate constraints in the builder via the data in constraint_system
acir_format::build_constraints(builder_, constraint_system, true);

// 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.
GoblinMockCircuits::construct_goblin_ecc_op_circuit(builder_);
}

std::vector<uint8_t> 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<uint8_t> 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<uint8_t> const& proof)
{
return goblin.verify_accumulator_for_acir(proof);
}

std::vector<uint8_t> GoblinAcirComposer::accumulate_and_prove()
{
// Construct one final GUH proof via the accumulate mechanism
std::vector<uint8_t> 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(std::vector<uint8_t> const& proof)
{
// Verify the final GUH proof
bool ultra_verified = goblin.verify_accumulator_for_acir(proof);

// Verify the Goblin proof (ECCVM, Translator, Merge)
bool goblin_verified = goblin.verify_for_acir();

return ultra_verified && goblin_verified;
}

} // namespace acir_proofs
Loading