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
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ TEST_F(BoomerangGoblinRecursiveVerifierTests, graph_description_basic)

GoblinRecursiveVerifier verifier{ &builder, verifier_input };
GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND);
output.points_accumulator.set_public();

stdlib::recursion::honk::DefaultIO<Builder> inputs;
inputs.pairing_inputs = output.points_accumulator;
inputs.set_public();

// Construct and verify a proof for the Goblin Recursive Verifier circuit
{
auto prover_instance = std::make_shared<OuterProverInstance>(builder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "barretenberg/stdlib/primitives/curves/bn254.hpp"
#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp"
#include "barretenberg/stdlib/primitives/padding_indicator_array/padding_indicator_array.hpp"
#include "barretenberg/stdlib/primitives/pairing_points.hpp"
#include "barretenberg/stdlib/proof/proof.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp"
#include <gtest/gtest.h>
Expand Down Expand Up @@ -136,11 +137,12 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle)
u_challenge_in_circuit,
Commitment::one(&builder),
stdlib_verifier_transcript);
auto pairing_points = KZG<Curve>::reduce_verify_batch_opening_claim(opening_claim, stdlib_verifier_transcript);
stdlib::recursion::PairingPoints<Builder> pairing_points(
KZG<Curve>::reduce_verify_batch_opening_claim(opening_claim, stdlib_verifier_transcript));
EXPECT_TRUE(CircuitChecker::check(builder));

VerifierCommitmentKey<NativeCurve> vk;
EXPECT_EQ(vk.pairing_check(pairing_points[0].get_value(), pairing_points[1].get_value()), true);
EXPECT_EQ(vk.pairing_check(pairing_points.P0.get_value(), pairing_points.P1.get_value()), true);

// Return finalized number of gates;
return builder.num_gates();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ HypernovaDeciderVerifier<Flavor>::PairingPoints HypernovaDeciderVerifier<Flavor>
const auto opening_claim = ShpleminiVerifier::compute_batch_opening_claim(
padding_indicator_array, claim_batcher, accumulator.challenge, generator, transcript);

auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript);

if constexpr (IsRecursiveFlavor<Flavor>) {
PairingPoints pairing_points(PCS::reduce_verify_batch_opening_claim(opening_claim, transcript));
return pairing_points;
} else {
auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript);
// Native pairing points contain affine elements
return { typename Curve::AffineElement(pairing_points[0]), typename Curve::AffineElement(pairing_points[1]) };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ class RecursiveCircuit {

StdlibProof stdlib_inner_proof(outer_circuit, inner_proof);
VerifierOutput output = verifier.template verify_proof<OuterIO>(stdlib_inner_proof);
output.points_accumulator.set_public();

stdlib::recursion::honk::DefaultIO<OuterBuilder> public_inputs;
public_inputs.pairing_inputs = output.points_accumulator;
public_inputs.set_public();

return outer_circuit;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ TEST_F(GoblinRecursiveVerifierTests, Basic)

GoblinRecursiveVerifier verifier{ &builder, verifier_input };
GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND);
output.points_accumulator.set_public();

stdlib::recursion::honk::DefaultIO<Builder> inputs;
inputs.pairing_inputs = output.points_accumulator;
inputs.set_public();

info("Recursive Verifier: num gates = ", builder.num_gates());

Expand Down Expand Up @@ -181,7 +184,10 @@ TEST_F(GoblinRecursiveVerifierTests, IndependentVKHash)
GoblinRecursiveVerifier verifier{ &builder, verifier_input };
GoblinRecursiveVerifierOutput output =
verifier.verify(proof, recursive_merge_commitments, MergeSettings::APPEND);
output.points_accumulator.set_public();

stdlib::recursion::honk::DefaultIO<Builder> inputs;
inputs.pairing_inputs = output.points_accumulator;
inputs.set_public();

info("Recursive Verifier: num gates = ", builder.num_gates());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ DeciderRecursiveVerifier_<Flavor>::PairingPoints DeciderRecursiveVerifier_<Flavo
transcript,
Flavor::REPEATED_COMMITMENTS,
Flavor::HasZK);
auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript);
PairingPoints pairing_points(PCS::reduce_verify_batch_opening_claim(opening_claim, transcript));

return { pairing_points[0], pairing_points[1] };
return pairing_points;
}

template class DeciderRecursiveVerifier_<bb::MegaRecursiveFlavor_<MegaCircuitBuilder>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ UltraRecursiveVerifier_<Flavor>::Output UltraRecursiveVerifier_<Flavor>::verify_
libra_commitments,
sumcheck_output.claimed_libra_evaluation);

auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript);
PairingPoints<typename Curve::Builder> pairing_points(
PCS::reduce_verify_batch_opening_claim(opening_claim, transcript));

// Reconstruct the public inputs
IO inputs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ MergeRecursiveVerifier_<CircuitBuilder>::verify_proof(const stdlib::Proof<Circui
auto batch_opening_claim = verifier.export_batch_opening_claim(Commitment::one(kappa.get_context()));

// KZG verifier
auto pairing_points = KZG::reduce_verify_batch_opening_claim(batch_opening_claim, transcript);
PairingPoints pairing_points(KZG::reduce_verify_batch_opening_claim(batch_opening_claim, transcript));

return { pairing_points, merged_table_commitments };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ template <typename Builder_> struct PairingPoints {
Group P1;

bool has_data = false;
uint32_t tag_index = 0; // Index of the tag for tracking pairing point aggregation

// Number of bb::fr field elements used to represent a goblin element in the public inputs
static constexpr size_t PUBLIC_INPUTS_SIZE = PAIRING_POINTS_SIZE;
Expand All @@ -50,7 +51,13 @@ template <typename Builder_> struct PairingPoints {
: P0(P0)
, P1(P1)
, has_data(true)
{}
{
// Get the builder from the group elements and assign a new tag
Builder* builder = P0.get_context();
if (builder != nullptr) {
tag_index = builder->pairing_points_tagging.create_pairing_point_tag();
}
}

PairingPoints(std::array<Group, 2> const& points)
: PairingPoints(points[0], points[1])
Expand Down Expand Up @@ -95,7 +102,17 @@ template <typename Builder_> struct PairingPoints {
auto P0 = Group::batch_mul(first_components, challenges);
auto P1 = Group::batch_mul(second_components, challenges);

return { P0, P1 };
PairingPoints aggregated_points(P0, P1);

// Merge tags
Builder* builder = P0.get_context();
if (builder != nullptr) {
for (const auto& points : pairing_points) {
builder->pairing_points_tagging.merge_pairing_point_tags(aggregated_points.tag_index, points.tag_index);
}
}

return aggregated_points;
}

/**
Expand Down Expand Up @@ -135,6 +152,12 @@ template <typename Builder_> struct PairingPoints {
point_to_aggregate = other.P1.scalar_mul(recursion_separator, 128);
P1 += point_to_aggregate;
}

// Merge the tags in the builder
Builder* builder = P0.get_context();
if (builder != nullptr) {
builder->pairing_points_tagging.merge_pairing_point_tags(this->tag_index, other.tag_index);
}
}

/**
Expand Down Expand Up @@ -229,29 +252,12 @@ template <typename Builder_> struct PairingPoints {
}
};

template <typename Builder> void read(uint8_t const*& it, PairingPoints<Builder>& as)
{
using serialize::read;

read(it, as.P0);
read(it, as.P1);
read(it, as.has_data);
};

template <typename Builder> void write(std::vector<uint8_t>& buf, PairingPoints<Builder> const& as)
{
using serialize::write;

write(buf, as.P0);
write(buf, as.P1);
write(buf, as.has_data);
};

template <typename NCT> std::ostream& operator<<(std::ostream& os, PairingPoints<NCT> const& as)
{
return os << "P0: " << as.P0 << "\n"
<< "P1: " << as.P1 << "\n"
<< "has_data: " << as.has_data << "\n";
<< "has_data: " << as.has_data << "\n"
<< "tag_index: " << as.tag_index << "\n";
}

} // namespace bb::stdlib::recursion
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "barretenberg/stdlib/primitives/pairing_points.hpp"
#include "barretenberg/commitment_schemes/pairing_points.hpp"
#include "barretenberg/srs/global_crs.hpp"
#include "barretenberg/ultra_honk/prover_instance.hpp"
#include <gtest/gtest.h>

namespace bb::stdlib::recursion {
Expand Down Expand Up @@ -48,4 +49,110 @@ TYPED_TEST(PairingPointsTests, TestDefault)
bb::PairingPoints native_pp(P0.get_value(), P1.get_value());
EXPECT_TRUE(native_pp.check()) << "Default PairingPoints are not valid pairing points.";
}

TYPED_TEST(PairingPointsTests, TaggingMechanismWorks)
{
using Builder = TypeParam;
using PairingPoints = PairingPoints<Builder>;
using Group = PairingPoints::Group;
using Fr = PairingPoints::Curve::ScalarField;
using NativeFr = PairingPoints::Curve::ScalarFieldNative;

Builder builder;

Fr scalar_one = Fr::from_witness(&builder, NativeFr::random_element());
Fr scalar_two = Fr::from_witness(&builder, NativeFr::random_element());
Group P0 = Group::batch_mul({ Group::one(&builder) }, { scalar_one });
Group P1 = Group::batch_mul({ Group::one(&builder) }, { scalar_two });

// Check that no pairing points exist
EXPECT_TRUE(builder.pairing_points_tagging.has_single_pairing_point_tag());

PairingPoints pp_one = { P0, P1 };
PairingPoints pp_two = { P0, P1 };

// Check the tags
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_one.tag_index), 0U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_two.tag_index), 1U);

// Check that there are two different pairing points in the builder
EXPECT_FALSE(builder.pairing_points_tagging.has_single_pairing_point_tag());

// Merge the tags
pp_one.aggregate(pp_two);

// Check that the tags have been merged
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_two.tag_index), 0U);
EXPECT_TRUE(builder.pairing_points_tagging.has_single_pairing_point_tag());

// Create two new pairing points and aggregate with aggregate_multiple
PairingPoints pp_three = { P0, P1 };
PairingPoints pp_four = { P0, P1 };

// Check the tags
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_three.tag_index), 2U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_four.tag_index), 3U);

// Check that there are two different pairing points in the builder
EXPECT_FALSE(builder.pairing_points_tagging.has_single_pairing_point_tag());

// Merge the tags
std::vector<PairingPoints> pp_to_be_aggregated = { pp_one, pp_three, pp_four };
PairingPoints aggregated_pp = PairingPoints::aggregate_multiple(pp_to_be_aggregated);

// Check that the tags have been merged
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_one.tag_index), 4U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_two.tag_index), 4U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_three.tag_index), 4U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_four.tag_index), 4U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(aggregated_pp.tag_index), 4U);
EXPECT_TRUE(builder.pairing_points_tagging.has_single_pairing_point_tag());
}

TYPED_TEST(PairingPointsTests, TaggingMechanismFails)
{
BB_DISABLE_ASSERTS();

using Builder = TypeParam;
using PairingPoints = PairingPoints<Builder>;
using Group = PairingPoints::Group;
using Fr = PairingPoints::Curve::ScalarField;
using NativeFr = PairingPoints::Curve::ScalarFieldNative;
using Flavor = std::conditional_t<IsMegaBuilder<Builder>, MegaFlavor, UltraFlavor>;
using ProverInstance = ProverInstance_<Flavor>;

Builder builder;

Fr scalar_one = Fr::from_witness(&builder, NativeFr::random_element());
Fr scalar_two = Fr::from_witness(&builder, NativeFr::random_element());
Group P0 = Group::batch_mul({ Group::one(&builder) }, { scalar_one });
Group P1 = Group::batch_mul({ Group::one(&builder) }, { scalar_two });

PairingPoints pp_one = { P0, P1 };
PairingPoints pp_two = { P0, P1 };
PairingPoints pp_three = { P0, P1 };

// Check the tags
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_one.tag_index), 0U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_two.tag_index), 1U);
BB_ASSERT_EQ(builder.pairing_points_tagging.get_tag(pp_three.tag_index), 2U);

// Check that there are different pairing points in the builder
EXPECT_FALSE(builder.pairing_points_tagging.has_single_pairing_point_tag());

// Merge the tags
pp_one.aggregate(pp_two);

// Check that the tags have not been merged
EXPECT_FALSE(builder.pairing_points_tagging.has_single_pairing_point_tag());

// Create a ProverInstance, expect failure
try {
ProverInstance prover_instance(builder);
} catch (std::exception& e) {
BB_ASSERT_EQ(e.what(),
"Pairing points must all be aggregated together. Either no pairing points should be created, or "
"all created pairing points must be aggregated into a single pairing point.");
}
}
} // namespace bb::stdlib::recursion
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class KernelIO {
}
output_hn_accum_hash.set_public();

// Record that pairing points have been set to public
builder->pairing_points_tagging.set_public_pairing_points();
Copy link
Contributor

Choose a reason for hiding this comment

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

Could PairingPoints::set_public() be responsible for making this call so the developer doesnt have to remember to do it? Not a big deal if not

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed and leaving as is to avoid the usage of set_public on the single pairing points (pairing points should be set to public using the public inputs classes we have). Added an issue about making set_public protected.

// Finalize the public inputs to ensure no more public inputs can be added hereafter.
builder->finalize_public_inputs();
}
Expand Down Expand Up @@ -180,6 +182,8 @@ template <typename Builder_> class DefaultIO {

pairing_inputs.set_public();

// Record that pairing points have been set to public
builder->pairing_points_tagging.set_public_pairing_points();
// Finalize the public inputs to ensure no more public inputs can be added hereafter.
builder->finalize_public_inputs();
}
Expand Down Expand Up @@ -239,11 +243,14 @@ template <typename Builder_> class GoblinAvmIO {
*/
void set_public()
{
Builder* builder = pairing_inputs.P0.get_context();

mega_hash.set_public();
pairing_inputs.set_public();

// Record that pairing points have been set to public
builder->pairing_points_tagging.set_public_pairing_points();
// Finalize the public inputs to ensure no more public inputs can be added hereafter.
Builder* builder = pairing_inputs.P0.get_context();
builder->finalize_public_inputs();
}
};
Expand Down Expand Up @@ -308,6 +315,8 @@ template <class Builder_> class HidingKernelIO {
commitment.set_public();
}

// Record that pairing points have been set to public
builder->pairing_points_tagging.set_public_pairing_points();
// Finalize the public inputs to ensure no more public inputs can be added hereafter.
builder->finalize_public_inputs();
}
Expand Down Expand Up @@ -380,6 +389,8 @@ class RollupIO {
}
ipa_claim.set_public();

// Record that pairing points have been set to public
builder->pairing_points_tagging.set_public_pairing_points();
// Finalize the public inputs to ensure no more public inputs can be added hereafter.
builder->finalize_public_inputs();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ TranslatorRecursiveVerifier::PairingPoints TranslatorRecursiveVerifier::verify_p
libra_commitments,
sumcheck_output.claimed_libra_evaluation);

auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript);
PairingPoints pairing_points(PCS::reduce_verify_batch_opening_claim(opening_claim, transcript));

return { pairing_points[0], pairing_points[1] };
return pairing_points;
}

void TranslatorRecursiveVerifier::verify_translation(const TranslationEvaluations_<BF>& translation_evaluations,
Expand Down
Loading
Loading