Skip to content

Commit

Permalink
chore: clean up proof lengths and IPA (#11020)
Browse files Browse the repository at this point in the history
Closes AztecProtocol/barretenberg#1184.
Closes AztecProtocol/barretenberg#1168.

Cleans up some ugliness by deduplication and refactoring. Also adds new
UltraRollupHonk tests and a new test for checking proof lengths.
  • Loading branch information
lucasxia01 authored Jan 6, 2025
1 parent bf10a5c commit 800c834
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 117 deletions.
24 changes: 11 additions & 13 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,10 @@ void prove_tube(const std::string& output_path)
// circuit
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1048): INSECURE - make this tube proof actually use
// these public inputs by turning proof into witnesses and calling set_public on each witness
auto num_public_inputs = static_cast<uint32_t>(static_cast<uint256_t>(proof.mega_proof[1]));
num_public_inputs -= bb::PAIRING_POINT_ACCUMULATOR_SIZE; // don't add the agg object
auto num_inner_public_inputs = static_cast<uint32_t>(static_cast<uint256_t>(proof.mega_proof[1]));
num_inner_public_inputs -= bb::PAIRING_POINT_ACCUMULATOR_SIZE; // don't add the agg object

for (size_t i = 0; i < num_public_inputs; i++) {
for (size_t i = 0; i < num_inner_public_inputs; i++) {
auto offset = bb::HONK_PROOF_PUBLIC_INPUT_OFFSET;
builder->add_public_variable(proof.mega_proof[i + offset]);
}
Expand Down Expand Up @@ -278,13 +278,13 @@ void prove_tube(const std::string& output_path)
Verifier tube_verifier(tube_verification_key, ipa_verification_key);

// Break up the tube proof into the honk portion and the ipa portion
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor
const size_t HONK_PROOF_LENGTH = 469;
const size_t HONK_PROOF_LENGTH_WITHOUT_INNER_PUB_INPUTS =
UltraRollupFlavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS + PAIRING_POINT_ACCUMULATOR_SIZE + IPA_CLAIM_SIZE;
// The extra calculation is for the IPA proof length.
ASSERT(tube_proof.size() == HONK_PROOF_LENGTH + 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2 + num_public_inputs);
ASSERT(tube_proof.size() == HONK_PROOF_LENGTH_WITHOUT_INNER_PUB_INPUTS + num_inner_public_inputs);
// split out the ipa proof
const std::ptrdiff_t honk_proof_with_pub_inputs_length =
static_cast<std::ptrdiff_t>(HONK_PROOF_LENGTH + num_public_inputs);
const std::ptrdiff_t honk_proof_with_pub_inputs_length = static_cast<std::ptrdiff_t>(
HONK_PROOF_LENGTH_WITHOUT_INNER_PUB_INPUTS - IPA_PROOF_LENGTH + num_inner_public_inputs);
auto ipa_proof = HonkProof(tube_proof.begin() + honk_proof_with_pub_inputs_length, tube_proof.end());
auto tube_honk_proof = HonkProof(tube_proof.begin(), tube_proof.end() + honk_proof_with_pub_inputs_length);
bool verified = tube_verifier.verify_proof(tube_honk_proof, ipa_proof);
Expand Down Expand Up @@ -895,15 +895,13 @@ template <IsUltraFlavor Flavor> bool verify_honk(const std::string& proof_path,
bool verified;
if constexpr (HasIPAAccumulator<Flavor>) {
// Break up the tube proof into the honk portion and the ipa portion
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor
const size_t HONK_PROOF_LENGTH = 469;
const size_t num_public_inputs =
static_cast<size_t>(uint64_t(proof[1])) - PAIRING_POINT_ACCUMULATOR_SIZE - IPA_CLAIM_SIZE;
const size_t HONK_PROOF_LENGTH = Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS - IPA_PROOF_LENGTH;
const size_t num_public_inputs = static_cast<size_t>(uint64_t(proof[1]));
// The extra calculation is for the IPA proof length.
debug("proof size: ", proof.size());
debug("num public inputs: ", num_public_inputs);
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1182): Move to ProofSurgeon.
ASSERT(proof.size() == HONK_PROOF_LENGTH + 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2 + num_public_inputs);
ASSERT(proof.size() == HONK_PROOF_LENGTH + IPA_PROOF_LENGTH + num_public_inputs);
// split out the ipa proof
const std::ptrdiff_t honk_proof_with_pub_inputs_length =
static_cast<std::ptrdiff_t>(HONK_PROOF_LENGTH + num_public_inputs);
Expand Down
30 changes: 30 additions & 0 deletions barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
#include "barretenberg/common/container.hpp"
#include "barretenberg/common/thread.hpp"
#include "barretenberg/common/throw_or_abort.hpp"
#include "barretenberg/constants.hpp"
#include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp"
#include "barretenberg/stdlib/hash/poseidon2/poseidon2.hpp"
#include "barretenberg/stdlib/honk_verifier/ipa_accumulator.hpp"
#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp"
#include "barretenberg/stdlib/transcript/transcript.hpp"
#include "barretenberg/transcript/transcript.hpp"
#include <cstddef>
Expand All @@ -20,6 +22,8 @@
namespace bb {
// clang-format off

constexpr size_t IPA_PROOF_LENGTH = 1 + 4 * CONST_ECCVM_LOG_N + 2 + 2;

/**
* @brief IPA (inner product argument) commitment scheme class.
*
Expand Down Expand Up @@ -949,6 +953,32 @@ template <typename Curve_> class IPA {
output_claim.opening_pair.evaluation.self_reduce();
return {output_claim, prover_transcript->proof_data};
}

static std::pair<OpeningClaim<Curve>, HonkProof> create_fake_ipa_claim_and_proof(UltraCircuitBuilder& builder)
requires Curve::is_stdlib_type {
using NativeCurve = curve::Grumpkin;
using Builder = typename Curve::Builder;
using Curve = stdlib::grumpkin<Builder>;
auto ipa_transcript = std::make_shared<NativeTranscript>();
auto ipa_commitment_key = std::make_shared<CommitmentKey<NativeCurve>>(1 << CONST_ECCVM_LOG_N);
size_t n = 4;
auto poly = Polynomial<fq>(n);
for (size_t i = 0; i < n; i++) {
poly.at(i) = fq::random_element();
}
fq x = fq::random_element();
fq eval = poly.evaluate(x);
auto commitment = ipa_commitment_key->commit(poly);
const OpeningPair<NativeCurve> opening_pair = { x, eval };
IPA<NativeCurve>::compute_opening_proof(ipa_commitment_key, { poly, opening_pair }, ipa_transcript);

auto stdlib_comm = Curve::Group::from_witness(&builder, commitment);
auto stdlib_x = Curve::ScalarField::from_witness(&builder, x);
auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval);
OpeningClaim<Curve> stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm };

return {stdlib_opening_claim, ipa_transcript->export_proof()};
}
};

} // namespace bb
26 changes: 4 additions & 22 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,31 +439,13 @@ HonkRecursionConstraintsOutput<Builder> process_honk_recursion_constraints(
} else if (nested_ipa_claims.size() > 2) {
throw_or_abort("Too many nested IPA claims to accumulate");
} else {
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1184): Move to IPA class.
if (honk_recursion == 2) {
info("Proving with UltraRollupHonk but no IPA claims exist.");
// just create some fake IPA claim and proof
using NativeCurve = curve::Grumpkin;
using Curve = stdlib::grumpkin<Builder>;
auto ipa_transcript = std::make_shared<NativeTranscript>();
auto ipa_commitment_key = std::make_shared<CommitmentKey<NativeCurve>>(1 << CONST_ECCVM_LOG_N);
size_t n = 4;
auto poly = Polynomial<fq>(n);
for (size_t i = 0; i < n; i++) {
poly.at(i) = fq::random_element();
}
fq x = fq::random_element();
fq eval = poly.evaluate(x);
auto commitment = ipa_commitment_key->commit(poly);
const OpeningPair<NativeCurve> opening_pair = { x, eval };
IPA<NativeCurve>::compute_opening_proof(ipa_commitment_key, { poly, opening_pair }, ipa_transcript);

auto stdlib_comm = Curve::Group::from_witness(&builder, commitment);
auto stdlib_x = Curve::ScalarField::from_witness(&builder, x);
auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval);
OpeningClaim<Curve> stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm };
auto [stdlib_opening_claim, ipa_proof] =
IPA<stdlib::grumpkin<Builder>>::create_fake_ipa_claim_and_proof(builder);

output.ipa_claim = stdlib_opening_claim;
output.ipa_proof = ipa_transcript->export_proof();
output.ipa_proof = ipa_proof;
}
}
output.agg_obj_indices = current_aggregation_object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,9 @@ void create_dummy_vkey_and_proof(Builder& builder,
const std::vector<field_ct>& proof_fields)
{
// Set vkey->circuit_size correctly based on the proof size
size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs<typename Flavor::Commitment>();
size_t num_frs_fr = bb::field_conversion::calc_num_bn254_frs<typename Flavor::FF>();
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor
assert((proof_size - bb::HONK_PROOF_PUBLIC_INPUT_OFFSET - Flavor::NUM_WITNESS_ENTITIES * num_frs_comm -
Flavor::NUM_ALL_ENTITIES * num_frs_fr - num_frs_comm) %
(num_frs_comm + num_frs_fr * (Flavor::BATCHED_RELATION_PARTIAL_LENGTH + 1)) ==
0);
ASSERT(proof_size == Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS);
// Note: this computation should always result in log_circuit_size = CONST_PROOF_SIZE_LOG_N
auto log_circuit_size =
(proof_size - bb::HONK_PROOF_PUBLIC_INPUT_OFFSET - Flavor::NUM_WITNESS_ENTITIES * num_frs_comm -
Flavor::NUM_ALL_ENTITIES * num_frs_fr - num_frs_comm) /
(num_frs_comm + num_frs_fr * (Flavor::BATCHED_RELATION_PARTIAL_LENGTH + 1));
auto log_circuit_size = CONST_PROOF_SIZE_LOG_N;
// First key field is circuit size
builder.assert_equal(builder.add_variable(1 << log_circuit_size), key_fields[0].witness_index);
// Second key field is number of public inputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,14 @@ UltraRecursiveVerifier_<Flavor>::Output UltraRecursiveVerifier_<Flavor>::verify_
Output output;
StdlibProof<Builder> honk_proof;
if constexpr (HasIPAAccumulator<Flavor>) {
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1168): Add formula to flavor
const size_t HONK_PROOF_LENGTH = 469;
const size_t HONK_PROOF_LENGTH = Flavor::NativeFlavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS - IPA_PROOF_LENGTH;
const size_t num_public_inputs = static_cast<uint32_t>(proof[1].get_value());
// The extra calculation is for the IPA proof length.
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1182): Handle in ProofSurgeon.
ASSERT(proof.size() == HONK_PROOF_LENGTH + (1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2) + num_public_inputs -
(PAIRING_POINT_ACCUMULATOR_SIZE + IPA_CLAIM_SIZE));
ASSERT(proof.size() == HONK_PROOF_LENGTH + IPA_PROOF_LENGTH + num_public_inputs);
// split out the ipa proof
const std::ptrdiff_t honk_proof_with_pub_inputs_length = static_cast<std::ptrdiff_t>(
HONK_PROOF_LENGTH + num_public_inputs - (PAIRING_POINT_ACCUMULATOR_SIZE + IPA_CLAIM_SIZE));
const std::ptrdiff_t honk_proof_with_pub_inputs_length =
static_cast<std::ptrdiff_t>(HONK_PROOF_LENGTH + num_public_inputs);
output.ipa_proof = StdlibProof<Builder>(proof.begin() + honk_proof_with_pub_inputs_length, proof.end());
honk_proof = StdlibProof<Builder>(proof.begin(), proof.end() + honk_proof_with_pub_inputs_length);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,29 +77,11 @@ template <typename RecursiveFlavor> class RecursiveVerifierTest : public testing
PairingPointAccumulatorIndices agg_obj_indices = stdlib::recursion::init_default_agg_obj_indices(builder);
builder.add_pairing_point_accumulator(agg_obj_indices);

// TODO(https://github.com/AztecProtocol/barretenberg/issues/1184): Move to IPA class.
if constexpr (HasIPAAccumulator<RecursiveFlavor>) {
using NativeCurve = curve::Grumpkin;
using Curve = stdlib::grumpkin<InnerBuilder>;
auto ipa_transcript = std::make_shared<NativeTranscript>();
auto ipa_commitment_key = std::make_shared<CommitmentKey<NativeCurve>>(1 << CONST_ECCVM_LOG_N);
size_t n = 4;
auto poly = Polynomial<fq>(n);
for (size_t i = 0; i < n; i++) {
poly.at(i) = fq::random_element();
}
fq x = fq::random_element();
fq eval = poly.evaluate(x);
auto commitment = ipa_commitment_key->commit(poly);
const OpeningPair<NativeCurve> opening_pair = { x, eval };
IPA<NativeCurve>::compute_opening_proof(ipa_commitment_key, { poly, opening_pair }, ipa_transcript);

auto stdlib_comm = Curve::Group::from_witness(&builder, commitment);
auto stdlib_x = Curve::ScalarField::from_witness(&builder, x);
auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval);
OpeningClaim<Curve> stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm };
auto [stdlib_opening_claim, ipa_proof] =
IPA<grumpkin<InnerBuilder>>::create_fake_ipa_claim_and_proof(builder);
builder.add_ipa_claim(stdlib_opening_claim.get_witness_indices());
builder.ipa_proof = ipa_transcript->export_proof();
builder.ipa_proof = ipa_proof;
}
return builder;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ class UltraFlavor {
// Note: made generic for use in MegaRecursive.
template <typename FF>

// List of relations reflecting the Ultra arithmetisation. WARNING: As UltraKeccak flavor inherits from Ultra flavor
// any change of ordering in this tuple needs to be reflected in the smart contract, otherwise relation accumulation
// will not match.
// List of relations reflecting the Ultra arithmetisation. WARNING: As UltraKeccak flavor inherits from
// Ultra flavor any change of ordering in this tuple needs to be reflected in the smart contract, otherwise
// relation accumulation will not match.
using Relations_ = std::tuple<bb::UltraArithmeticRelation<FF>,
bb::UltraPermutationRelation<FF>,
bb::LogDerivLookupRelation<FF>,
Expand Down Expand Up @@ -97,6 +97,22 @@ class UltraFlavor {
static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1;
static constexpr size_t NUM_RELATIONS = std::tuple_size_v<Relations>;

// Proof length formula:
// 1. HONK_PROOF_PUBLIC_INPUT_OFFSET are the circuit_size, num_public_inputs, pub_inputs_offset
// 2. PAIRING_POINT_ACCUMULATOR_SIZE public inputs for pairing point accumulator
// 3. NUM_WITNESS_ENTITIES commitments
// 4. CONST_PROOF_SIZE_LOG_N sumcheck univariates
// 5. NUM_ALL_ENTITIES sumcheck evaluations
// 6. CONST_PROOF_SIZE_LOG_N Gemini Fold commitments
// 7. CONST_PROOF_SIZE_LOG_N Gemini a evaluations
// 8. KZG W commitment
static constexpr size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs<Commitment>();
static constexpr size_t num_frs_fr = bb::field_conversion::calc_num_bn254_frs<FF>();
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS =
HONK_PROOF_PUBLIC_INPUT_OFFSET + NUM_WITNESS_ENTITIES * num_frs_comm +
CONST_PROOF_SIZE_LOG_N * BATCHED_RELATION_PARTIAL_LENGTH * num_frs_fr + NUM_ALL_ENTITIES * num_frs_fr +
CONST_PROOF_SIZE_LOG_N * num_frs_comm + CONST_PROOF_SIZE_LOG_N * num_frs_fr + num_frs_comm;

template <size_t NUM_KEYS>
using ProtogalaxyTupleOfTuplesOfUnivariatesNoOptimisticSkipping =
decltype(create_protogalaxy_tuple_of_tuples_of_univariates<Relations, NUM_KEYS>());
Expand Down Expand Up @@ -537,7 +553,6 @@ class UltraFlavor {
* @brief A container for storing the partially evaluated multivariates produced by sumcheck.
*/
class PartiallyEvaluatedMultivariates : public AllEntities<Polynomial> {

public:
PartiallyEvaluatedMultivariates() = default;
PartiallyEvaluatedMultivariates(const size_t circuit_size)
Expand Down Expand Up @@ -675,7 +690,7 @@ class UltraFlavor {
this->z_perm = commitments.z_perm;
}
}
};
}; // namespace bb
// Specialize for Ultra (general case used in UltraRecursive).
using VerifierCommitments = VerifierCommitments_<Commitment, VerificationKey>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
#pragma once
#include "barretenberg/commitment_schemes/ipa/ipa.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp"

namespace bb {

class UltraRollupFlavor : public bb::UltraFlavor {
public:
// Proof length formula:
// 1. HONK_PROOF_PUBLIC_INPUT_OFFSET are the circuit_size, num_public_inputs, pub_inputs_offset
// 2. PAIRING_POINT_ACCUMULATOR_SIZE public inputs for pairing point accumulator
// 3. IPA_CLAIM_SIZE public inputs for IPA claim
// 4. NUM_WITNESS_ENTITIES commitments
// 5. CONST_PROOF_SIZE_LOG_N sumcheck univariates
// 6. NUM_ALL_ENTITIES sumcheck evaluations
// 7. CONST_PROOF_SIZE_LOG_N Gemini Fold commitments
// 8. CONST_PROOF_SIZE_LOG_N Gemini a evaluations
// 9. KZG W commitment
static constexpr size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs<Commitment>();
static constexpr size_t num_frs_fr = bb::field_conversion::calc_num_bn254_frs<FF>();
static constexpr size_t PROOF_LENGTH_WITHOUT_PUB_INPUTS =
UltraFlavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS + IPA_PROOF_LENGTH;

using UltraFlavor::UltraFlavor;
class ProvingKey : public UltraFlavor::ProvingKey {
public:
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
barretenberg_module(ultra_honk sumcheck)
barretenberg_module(ultra_honk sumcheck stdlib_primitives)
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ template <IsUltraFlavor Flavor> HonkProof UltraProver_<Flavor>::export_proof()
// Add the IPA proof
if constexpr (HasIPAAccumulator<Flavor>) {
// The extra calculation is for the IPA proof length.
ASSERT(proving_key->proving_key.ipa_proof.size() == 1 + 4 * (CONST_ECCVM_LOG_N) + 2 + 2);
ASSERT(proving_key->proving_key.ipa_proof.size() == IPA_PROOF_LENGTH);
proof.insert(proof.end(), proving_key->proving_key.ipa_proof.begin(), proving_key->proving_key.ipa_proof.end());
}
return proof;
Expand Down
Loading

0 comments on commit 800c834

Please sign in to comment.