Skip to content

Commit

Permalink
feat: Constant Honk proof sizes (#6954)
Browse files Browse the repository at this point in the history
Introduces logic in the Honk provers/verifiers to 1) produce a proof of
fixed size regardless of the size of the circuit, and 2) produce a
recursive verifier circuit that is independent of the size of the
circuit whose proof it is verifying. This was done largely for
convenience so that no additional logic is needed downstream of bberg to
handle the fact that Honk proofs and recursive verifier circuits are in
general dependent on the size of the inner circuit (unlike for Plonk).

---------

Co-authored-by: lucasxia01 <lucasxia01@gmail.com>
Co-authored-by: ledwards2225 <l.edwards.d@gmail.com>
  • Loading branch information
3 people committed Jun 28, 2024
1 parent 77c304e commit 17c8d3a
Show file tree
Hide file tree
Showing 55 changed files with 738 additions and 503 deletions.
2 changes: 1 addition & 1 deletion barretenberg/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ barretenberg-acir-tests-bb:
RUN FLOW=prove_and_verify_mega_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
# Fold and verify an ACIR program stack using ClientIvc, recursively verify as part of the Tube circuit and produce and verify a Honk proof
# Fold and verify an ACIR program stack using ClientIvc, recursively verify as part of the Tube circuit and produce and verify a Honk proof
RUN FLOW=prove_then_verify_tube ./run_acir_tests.sh fold_basic
# Construct and separately verify a UltraHonk proof for a single program that recursively verifies a Honk proof
RUN FLOW=prove_then_verify_ultra_honk ./run_acir_tests.sh verify_honk_proof
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/sh
set -eu
set -eux

VFLAG=${VERBOSE:+-v}
BFLAG="-b ./target/program.json"
Expand Down
1 change: 1 addition & 0 deletions barretenberg/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ add_subdirectory(barretenberg/bb)
add_subdirectory(barretenberg/circuit_checker)
add_subdirectory(barretenberg/client_ivc)
add_subdirectory(barretenberg/commitment_schemes)
add_subdirectory(barretenberg/commitment_schemes_recursion)
add_subdirectory(barretenberg/common)
add_subdirectory(barretenberg/crypto)
add_subdirectory(barretenberg/dsl)
Expand Down
68 changes: 39 additions & 29 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,18 +741,15 @@ bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::
#endif

/**
* @brief Creates a proof for an ACIR circuit
*
* Communication:
* - stdout: The proof is written to stdout as a byte array
* - Filesystem: The proof is written to the path specified by outputPath
* @brief Create a Honk a prover from program bytecode and an optional witness
*
* @param bytecodePath Path to the file containing the serialized circuit
* @param witnessPath Path to the file containing the serialized witness
* @param outputPath Path to write the proof to
* @tparam Flavor
* @param bytecodePath
* @param witnessPath
* @return UltraProver_<Flavor>
*/
template <IsUltraFlavor Flavor>
void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, const std::string& outputPath)
template <typename Flavor>
UltraProver_<Flavor> compute_valid_prover(const std::string& bytecodePath, const std::string& witnessPath)
{
using Builder = Flavor::CircuitBuilder;
using Prover = UltraProver_<Flavor>;
Expand All @@ -762,16 +759,40 @@ void prove_honk(const std::string& bytecodePath, const std::string& witnessPath,
honk_recursion = true;
}
auto constraint_system = get_constraint_system(bytecodePath, honk_recursion);
auto witness = get_witness(witnessPath);
acir_format::WitnessVector witness = {};
if (!witnessPath.empty()) {
witness = get_witness(witnessPath);
}

auto builder = acir_format::create_circuit<Builder>(constraint_system, 0, witness, honk_recursion);

auto num_extra_gates = builder.get_num_gates_added_to_ensure_nonzero_polynomials();
size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + num_extra_gates);
init_bn254_crs(srs_size);

// Construct Honk proof
Prover prover{ builder };
return prover;
}

/**
* @brief Creates a proof for an ACIR circuit
*
* Communication:
* - stdout: The proof is written to stdout as a byte array
* - Filesystem: The proof is written to the path specified by outputPath
*
* @param bytecodePath Path to the file containing the serialized circuit
* @param witnessPath Path to the file containing the serialized witness
* @param outputPath Path to write the proof to
*/
template <IsUltraFlavor Flavor>
void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, const std::string& outputPath)
{
// using Builder = Flavor::CircuitBuilder;
using Prover = UltraProver_<Flavor>;

// Construct Honk proof
Prover prover = compute_valid_prover<Flavor>(bytecodePath, witnessPath);
auto proof = prover.construct_proof();

if (outputPath == "-") {
Expand Down Expand Up @@ -807,10 +828,9 @@ template <IsUltraFlavor Flavor> bool verify_honk(const std::string& proof_path,
auto g2_data = get_bn254_g2_data(CRS_PATH);
srs::init_crs_factory({}, g2_data);
auto proof = from_buffer<std::vector<bb::fr>>(read_file(proof_path));
auto verification_key = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(read_file(vk_path)));
verification_key->pcs_verification_key = std::make_shared<VerifierCommitmentKey>();

Verifier verifier{ verification_key };
auto vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(read_file(vk_path)));
vk->pcs_verification_key = std::make_shared<VerifierCommitmentKey>();
Verifier verifier{ vk };

bool verified = verifier.verify_proof(proof);

Expand All @@ -830,22 +850,12 @@ template <IsUltraFlavor Flavor> bool verify_honk(const std::string& proof_path,
*/
template <IsUltraFlavor Flavor> void write_vk_honk(const std::string& bytecodePath, const std::string& outputPath)
{
using Builder = Flavor::CircuitBuilder;
using Prover = UltraProver_<Flavor>;
using ProverInstance = ProverInstance_<Flavor>;
using VerificationKey = Flavor::VerificationKey;

bool honk_recursion = false;
if constexpr (IsAnyOf<Flavor, UltraFlavor>) {
honk_recursion = true;
}
auto constraint_system = get_constraint_system(bytecodePath, honk_recursion);
auto builder = acir_format::create_circuit<Builder>(constraint_system, 0, {}, honk_recursion);

auto num_extra_gates = builder.get_num_gates_added_to_ensure_nonzero_polynomials();
size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + num_extra_gates);
init_bn254_crs(srs_size);

ProverInstance prover_inst(builder);
Prover prover = compute_valid_prover<Flavor>(bytecodePath, "");
ProverInstance& prover_inst = *prover.instance;
VerificationKey vk(
prover_inst.proving_key); // uses a partial form of the proving key which only has precomputed entities

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ template <class Curve> class VerifierCommitmentKey;
* @tparam curve::BN254
*/
template <> class VerifierCommitmentKey<curve::BN254> {
public:
using Curve = curve::BN254;
using GroupElement = typename Curve::Element;
using Commitment = typename Curve::AffineElement;

public:
VerifierCommitmentKey()
{
srs::init_crs_factory("../srs_db/ignition");
Expand Down Expand Up @@ -69,11 +69,11 @@ template <> class VerifierCommitmentKey<curve::BN254> {
* @tparam curve::Grumpkin
*/
template <> class VerifierCommitmentKey<curve::Grumpkin> {
public:
using Curve = curve::Grumpkin;
using GroupElement = typename Curve::Element;
using Commitment = typename Curve::AffineElement;

public:
/**
* @brief Construct a new IPA Verification Key object from existing SRS
*
Expand Down
Loading

0 comments on commit 17c8d3a

Please sign in to comment.