Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/api/prove_tube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void prove_tube(const std::string& output_path, const std::string& vk_path)
AggregationObject::add_default_pairing_points_to_public_inputs(*builder);

// The tube only calls an IPA recursive verifier once, so we can just add this IPA claim and proof
builder->add_ipa_claim(client_ivc_rec_verifier_output.opening_claim.get_witness_indices());
client_ivc_rec_verifier_output.opening_claim.set_public();
builder->ipa_proof = convert_stdlib_proof_to_native(client_ivc_rec_verifier_output.ipa_transcript->proof_data);
ASSERT(builder->ipa_proof.size() && "IPA proof should not be empty");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ template <typename RecursiveFlavor> class BoomerangRecursiveVerifierTest : publi
if constexpr (HasIPAAccumulator<RecursiveFlavor>) {
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());
stdlib_opening_claim.set_public();
builder.ipa_proof = ipa_proof;
}
return builder;
Expand Down Expand Up @@ -125,7 +125,7 @@ template <typename RecursiveFlavor> class BoomerangRecursiveVerifierTest : publi
pairing_points.P1.x.fix_witness();
pairing_points.P1.y.fix_witness();
if constexpr (HasIPAAccumulator<OuterFlavor>) {
outer_circuit.add_ipa_claim(output.ipa_opening_claim.get_witness_indices());
output.ipa_opening_claim.set_public();
outer_circuit.ipa_proof = convert_stdlib_proof_to_native(output.ipa_proof);
}
info("Recursive Verifier: num gates = ", outer_circuit.get_estimated_num_finalized_gates());
Expand Down Expand Up @@ -153,4 +153,4 @@ HEAVY_TYPED_TEST(BoomerangRecursiveVerifierTest, SingleRecursiveVerification)
TestFixture::test_recursive_verification();
};

} // namespace bb::stdlib::recursion::honk
} // namespace bb::stdlib::recursion::honk
60 changes: 49 additions & 11 deletions barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,24 +51,62 @@ template <typename Curve> class OpeningClaim {
using Fr = typename Curve::ScalarField;

public:
using Builder =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

does this fail to compile if we try to use it with a non grumpkin curve?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well it fails to compile with a non stdlib Curve type (this class is shared with native code). I made it explicitly Grumpkin because that's all we currently need it for and all we currently test

std::conditional_t<std::is_same_v<Curve, stdlib::grumpkin<UltraCircuitBuilder>>, UltraCircuitBuilder, void>;
// (challenge r, evaluation v = p(r))
OpeningPair<Curve> opening_pair;
// commitment to univariate polynomial p(X)
Commitment commitment;

IPAClaimIndices get_witness_indices() const
// Size of public inputs representation of an opening claim over Grumpkin
static constexpr size_t PUBLIC_INPUTS_SIZE = IPA_CLAIM_SIZE;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe this can be written as a sum now, and IPA_CLAIM_SIZE can be based off of this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is a good idea but it spirals in the linker bc agg types has to include some stdlib types which in turn wreaks havoc in all the places agg types is included. leaving it for another day


/**
* @brief Set the witness indices for the opening claim to public
* @note Implemented only for an opening claim over Grumpkin for use with IPA.
*
*/
uint32_t set_public()
requires(std::is_same_v<Curve, stdlib::grumpkin<UltraCircuitBuilder>>)
{
uint32_t start_idx = opening_pair.challenge.set_public();
opening_pair.evaluation.set_public();
commitment.set_public();

Builder* ctx = commitment.get_context();
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1325): Eventually the builder/PK/VK will store
// public input key which should be set here and ipa_claim_public_input_indices should go away.
uint32_t pub_idx = start_idx;
for (uint32_t& idx : ctx->ipa_claim_public_input_indices) {
idx = pub_idx++;
}
ctx->contains_ipa_claim = true;

return start_idx;
}

/**
* @brief Reconstruct an opening claim from limbs stored on the public inputs.
* @note Implemented only for an opening claim over Grumpkin for use with IPA.
*
*/
static OpeningClaim<Curve> reconstruct_from_public(
const std::span<const stdlib::field_t<Builder>, PUBLIC_INPUTS_SIZE>& limbs)
requires(std::is_same_v<Curve, stdlib::grumpkin<UltraCircuitBuilder>>)
{
return { opening_pair.challenge.binary_basis_limbs[0].element.normalize().witness_index,
opening_pair.challenge.binary_basis_limbs[1].element.normalize().witness_index,
opening_pair.challenge.binary_basis_limbs[2].element.normalize().witness_index,
opening_pair.challenge.binary_basis_limbs[3].element.normalize().witness_index,
opening_pair.evaluation.binary_basis_limbs[0].element.normalize().witness_index,
opening_pair.evaluation.binary_basis_limbs[1].element.normalize().witness_index,
opening_pair.evaluation.binary_basis_limbs[2].element.normalize().witness_index,
opening_pair.evaluation.binary_basis_limbs[3].element.normalize().witness_index,
commitment.x.normalize().witness_index, // no idea if we need these normalize() calls...
commitment.y.normalize().witness_index };
ASSERT(2 * Fr::PUBLIC_INPUTS_SIZE + Commitment::PUBLIC_INPUTS_SIZE == PUBLIC_INPUTS_SIZE);

const size_t FIELD_SIZE = Fr::PUBLIC_INPUTS_SIZE;
const size_t COMMITMENT_SIZE = Commitment::PUBLIC_INPUTS_SIZE;
std::span<const stdlib::field_t<Builder>, FIELD_SIZE> challenge_limbs{ limbs.data(), FIELD_SIZE };
std::span<const stdlib::field_t<Builder>, FIELD_SIZE> evaluation_limbs{ limbs.data() + FIELD_SIZE, FIELD_SIZE };
std::span<const stdlib::field_t<Builder>, COMMITMENT_SIZE> commitment_limbs{ limbs.data() + 2 * FIELD_SIZE,
COMMITMENT_SIZE };
auto challenge = Fr::reconstruct_from_public(challenge_limbs);
auto evaluation = Fr::reconstruct_from_public(evaluation_limbs);
auto commitment = Commitment::reconstruct_from_public(commitment_limbs);

return OpeningClaim<Curve>{ { challenge, evaluation }, commitment };
}

auto get_native_opening_claim() const
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class IPARecursiveTests : public CommitmentTest<NativeCurve> {
// polynomial.
auto [output_claim, ipa_proof] =
RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2);
builder.add_ipa_claim(output_claim.get_witness_indices());
output_claim.set_public();
builder.ipa_proof = ipa_proof;
builder.finalize_circuit(/*ensure_nonzero=*/false);
info("Circuit with 2 IPA Recursive Verifiers and IPA Accumulation num finalized gates = ",
Expand Down Expand Up @@ -266,7 +266,7 @@ TEST_F(IPARecursiveTests, AccumulationAndFullRecursiveVerifier)
// Creates two IPA accumulators and accumulators from the two claims. Also constructs the accumulated h
// polynomial.
auto [output_claim, ipa_proof] = RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2);
builder.add_ipa_claim(output_claim.get_witness_indices());
output_claim.set_public();
builder.ipa_proof = ipa_proof;
builder.finalize_circuit(/*ensure_nonzero=*/false);
info("Circuit with 2 IPA Recursive Verifiers and IPA Accumulation num finalized gates = ",
Expand Down Expand Up @@ -314,7 +314,7 @@ TEST_F(IPARecursiveTests, AccumulationWithDifferentSizes)
// Creates two IPA accumulators and accumulators from the two claims. Also constructs the accumulated h
// polynomial.
auto [output_claim, ipa_proof] = RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2);
builder.add_ipa_claim(output_claim.get_witness_indices());
output_claim.set_public();
builder.ipa_proof = ipa_proof;
builder.finalize_circuit(/*ensure_nonzero=*/false);
info("Circuit with 2 IPA Recursive Verifiers and IPA Accumulation num finalized gates = ",
Expand All @@ -332,4 +332,4 @@ TEST_F(IPARecursiveTests, AccumulationWithDifferentSizes)

auto result = NativeIPA::reduce_verify(this->vk(), opening_claim, verifier_transcript);
EXPECT_TRUE(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ void build_constraints(Builder& builder, AcirProgram& program, const ProgramMeta
// If we are proving with UltraRollupFlavor, the IPA proof should have nonzero size.
ASSERT((metadata.honk_recursion == 2) == (output.ipa_proof.size() > 0));
if (metadata.honk_recursion == 2) {
builder.add_ipa_claim(output.ipa_claim.get_witness_indices());
output.ipa_claim.set_public();
builder.ipa_proof = output.ipa_proof;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ TEST_F(ClientIVCRecursionTests, ClientTubeBase)
// just using default.
AggregationObject::add_default_pairing_points_to_public_inputs(*tube_builder);
// The tube only calls an IPA recursive verifier once, so we can just add this IPA claim and proof
tube_builder->add_ipa_claim(client_ivc_rec_verifier_output.opening_claim.get_witness_indices());
client_ivc_rec_verifier_output.opening_claim.set_public();
tube_builder->ipa_proof = convert_stdlib_proof_to_native(client_ivc_rec_verifier_output.ipa_transcript->proof_data);

info("ClientIVC Recursive Verifier: num prefinalized gates = ", tube_builder->num_gates);
Expand Down Expand Up @@ -140,7 +140,7 @@ TEST_F(ClientIVCRecursionTests, ClientTubeBase)
base_verifier.verify_proof(base_tube_proof, AggregationObject::construct_default(base_builder));
info("Tube UH Recursive Verifier: num prefinalized gates = ", base_builder.num_gates);
output.agg_obj.set_public();
base_builder.add_ipa_claim(output.ipa_opening_claim.get_witness_indices());
output.ipa_opening_claim.set_public();
base_builder.ipa_proof = tube_prover.proving_key->proving_key.ipa_proof;
EXPECT_EQ(base_builder.failed(), false) << base_builder.err();
EXPECT_TRUE(CircuitChecker::check(base_builder));
Expand Down Expand Up @@ -172,7 +172,7 @@ TEST_F(ClientIVCRecursionTests, TubeVKIndependentOfInputCircuits)
// instead of just using default.
AggregationObject::add_default_pairing_points_to_public_inputs(*tube_builder);
// The tube only calls an IPA recursive verifier once, so we can just add this IPA claim and proof
tube_builder->add_ipa_claim(client_ivc_rec_verifier_output.opening_claim.get_witness_indices());
client_ivc_rec_verifier_output.opening_claim.set_public();
tube_builder->ipa_proof =
convert_stdlib_proof_to_native(client_ivc_rec_verifier_output.ipa_transcript->proof_data);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,36 +137,12 @@ UltraRecursiveVerifier_<Flavor>::Output UltraRecursiveVerifier_<Flavor>::verify_
// Extract the IPA claim from the public inputs
// Parse out the nested IPA claim using key->ipa_claim_public_input_indices and run the native IPA verifier.
if constexpr (HasIPAAccumulator<Flavor>) {
const auto recover_fq_from_public_inputs = [](std::array<FF, Curve::BaseField::NUM_LIMBS>& limbs) {
for (size_t k = 0; k < Curve::BaseField::NUM_LIMBS; k++) {
limbs[k].create_range_constraint(Curve::BaseField::NUM_LIMB_BITS, "limb_" + std::to_string(k));
}
return Curve::BaseField::unsafe_construct_from_limbs(limbs[0], limbs[1], limbs[2], limbs[3], false);
};
using PublicIpaClaim = PublicInputComponent<OpeningClaim<grumpkin<Builder>>>;

if (verification_key->verification_key->contains_ipa_claim) {
OpeningClaim<grumpkin<Builder>> ipa_claim;
std::array<FF, Curve::BaseField::NUM_LIMBS> challenge_bigfield_limbs;
for (size_t k = 0; k < Curve::BaseField::NUM_LIMBS; k++) {
challenge_bigfield_limbs[k] =
verification_key
->public_inputs[verification_key->verification_key->ipa_claim_public_input_indices[k]];
}
std::array<FF, Curve::BaseField::NUM_LIMBS> evaluation_bigfield_limbs;
for (size_t k = 0; k < Curve::BaseField::NUM_LIMBS; k++) {
evaluation_bigfield_limbs[k] =
verification_key
->public_inputs[verification_key->verification_key
->ipa_claim_public_input_indices[Curve::BaseField::NUM_LIMBS + k]];
}
ipa_claim.opening_pair.challenge = recover_fq_from_public_inputs(challenge_bigfield_limbs);
ipa_claim.opening_pair.evaluation = recover_fq_from_public_inputs(evaluation_bigfield_limbs);
ipa_claim.commitment = {
verification_key->public_inputs[verification_key->verification_key->ipa_claim_public_input_indices[8]],
verification_key->public_inputs[verification_key->verification_key->ipa_claim_public_input_indices[9]],
false
};
output.ipa_opening_claim = std::move(ipa_claim);
PublicComponentKey ipa_claim_key{ verification_key->verification_key->ipa_claim_public_input_indices[0],
true };
output.ipa_opening_claim = PublicIpaClaim::reconstruct(verification_key->public_inputs, ipa_claim_key);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ template <typename RecursiveFlavor> class RecursiveVerifierTest : public testing
if constexpr (HasIPAAccumulator<RecursiveFlavor>) {
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());
stdlib_opening_claim.set_public();
builder.ipa_proof = ipa_proof;
}
return builder;
Expand Down Expand Up @@ -165,7 +165,7 @@ template <typename RecursiveFlavor> class RecursiveVerifierTest : public testing
typename RecursiveVerifier::Output verifier_output =
verifier.verify_proof(inner_proof, AggState::construct_default(outer_circuit));
if constexpr (HasIPAAccumulator<OuterFlavor>) {
outer_circuit.add_ipa_claim(verifier_output.ipa_opening_claim.get_witness_indices());
verifier_output.ipa_opening_claim.set_public();
outer_circuit.ipa_proof = convert_stdlib_proof_to_native(verifier_output.ipa_proof);
}

Expand Down Expand Up @@ -206,7 +206,7 @@ template <typename RecursiveFlavor> class RecursiveVerifierTest : public testing
VerifierOutput output = verifier.verify_proof(inner_proof, agg_obj);
AggState pairing_points = output.agg_obj;
if constexpr (HasIPAAccumulator<OuterFlavor>) {
outer_circuit.add_ipa_claim(output.ipa_opening_claim.get_witness_indices());
output.ipa_opening_claim.set_public();
outer_circuit.ipa_proof = convert_stdlib_proof_to_native(output.ipa_proof);
}
info("Recursive Verifier: num gates = ", outer_circuit.get_estimated_num_finalized_gates());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,16 @@ template <typename Builder> class field_t {
void assert_is_not_zero(std::string const& msg = "field_t::assert_is_not_zero") const;
void assert_is_zero(std::string const& msg = "field_t::assert_is_zero") const;
bool is_constant() const { return witness_index == IS_CONSTANT; }
void set_public() const
uint32_t set_public() const
{
uint32_t public_input_index = 0;
if constexpr (IsSimulator<Builder>) {
auto value = normalize().get_value();
context->set_public_input(value);
public_input_index = context->set_public_input(value);
} else {
context->set_public_input(normalize().witness_index);
public_input_index = context->set_public_input(normalize().witness_index);
}
return public_input_index;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ template <typename Builder> class cycle_group {
static constexpr size_t NUM_ROUNDS = (NUM_BITS + TABLE_BITS - 1) / TABLE_BITS;
inline static constexpr std::string_view OFFSET_GENERATOR_DOMAIN_SEPARATOR = "cycle_group_offset_generator";

// Since the cycle_group base field is the circuit's native field, it can be stored using two public inputs.
static constexpr size_t PUBLIC_INPUTS_SIZE = 2;

private:
public:
/**
Expand Down Expand Up @@ -276,6 +279,31 @@ template <typename Builder> class cycle_group {
return OriginTag(x.get_origin_tag(), y.get_origin_tag(), _is_infinity.get_origin_tag());
}

/**
* @brief Set the witness indices representing the cycle_group to public
*
* @return uint32_t Index into the public inputs array at which the representation is stored
*/
uint32_t set_public()
{
uint32_t start_idx = x.set_public();
y.set_public();
return start_idx;
}

/**
* @brief Reconstruct a cycle_group from limbs (generally stored in the public inputs)
* @details The base field of the cycle_group curve is the same as the circuit's native field so each coordinate is
* represented by a single "limb".
*
* @param limbs The coordinates of the cycle_group element
* @return cycle_group
*/
static cycle_group reconstruct_from_public(const std::span<const field_t, 2>& limbs)
{
return cycle_group(limbs[0], limbs[1], false);
}

field_t x;
field_t y;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,12 @@ template <typename FF_> class CircuitBuilderBase {
virtual uint32_t add_public_variable(const FF& in);

/**
* Make a witness variable public.
* @brief Make a witness variable public.
*
* @param witness_index The index of the witness.
* */
virtual void set_public_input(uint32_t witness_index);
* @return uint32_t The index of the witness in the public inputs vector.
*/
virtual uint32_t set_public_input(uint32_t witness_index);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should modify the comment to say what it returns

virtual void assert_equal(uint32_t a_idx, uint32_t b_idx, std::string const& msg = "assert_equal");

// TODO(#216)(Adrian): This method should belong in the ComposerHelper, where the number of reserved gates can be
Expand Down Expand Up @@ -216,8 +217,6 @@ template <typename FF_> class CircuitBuilderBase {
void add_pairing_point_accumulator_for_plonk(
const PairingPointAccumulatorIndices& pairing_point_accum_witness_indices);

void add_ipa_claim(const IPAClaimIndices& ipa_claim_witness_indices);

bool failed() const;
const std::string& err() const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,17 +176,20 @@ template <typename FF_> uint32_t CircuitBuilderBase<FF_>::add_public_variable(co
return index;
}

template <typename FF_> void CircuitBuilderBase<FF_>::set_public_input(const uint32_t witness_index)
template <typename FF_> uint32_t CircuitBuilderBase<FF_>::set_public_input(const uint32_t witness_index)
{
for (const uint32_t public_input : public_inputs) {
if (public_input == witness_index) {
if (!failed()) {
failure("Attempted to set a public input that is already public!");
}
return;
return 0;
}
}
uint32_t public_input_index = static_cast<uint32_t>(public_inputs.size());
public_inputs.emplace_back(witness_index);

return public_input_index;
}

/**
Expand Down Expand Up @@ -255,22 +258,6 @@ void CircuitBuilderBase<FF_>::add_pairing_point_accumulator_for_plonk(
}
}

template <typename FF_> void CircuitBuilderBase<FF_>::add_ipa_claim(const IPAClaimIndices& ipa_claim_witness_indices)
{
if (contains_ipa_claim) {
failure("added IPA claim when one already exists");
ASSERT(0);
}
contains_ipa_claim = true;

size_t i = 0;
for (const auto& idx : ipa_claim_witness_indices) {
set_public_input(idx);
ipa_claim_public_input_indices[i] = static_cast<uint32_t>(public_inputs.size() - 1);
++i;
}
}

template <typename FF_> bool CircuitBuilderBase<FF_>::failed() const
{
return _failed;
Expand Down
Loading