Skip to content

Commit 4129e27

Browse files
authored
feat: IPA accumulators setup for Rollup (#10040)
Creates a new flavor, UltraRollupFlavor, that handles IPA accumulators. Currently unused in the rollup, but will be used there. Adds IPA claim to builder, pk, vk, so that the verifier knows where to look to extract the IPA claim from. Modifies the UltraRecursiveVerifier to extract out the IPA claim from the public inputs and return it. Also modifies native verifier to check the IPA claim and proof.
1 parent 4ab46fe commit 4129e27

File tree

56 files changed

+492
-155
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+492
-155
lines changed

barretenberg/cpp/src/barretenberg/bb/main.cpp

+22-7
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ void prove_tube(const std::string& output_path)
590590
}
591591
ClientIVC verifier{ builder, input };
592592

593-
verifier.verify(proof);
593+
ClientIVC::Output client_ivc_rec_verifier_output = verifier.verify(proof);
594594

595595
PairingPointAccumulatorIndices current_aggregation_object =
596596
stdlib::recursion::init_default_agg_obj_indices<Builder>(*builder);
@@ -599,6 +599,12 @@ void prove_tube(const std::string& output_path)
599599
// This is currently just setting the aggregation object to the default one.
600600
builder->add_pairing_point_accumulator(current_aggregation_object);
601601

602+
// The tube only calls an IPA recursive verifier once, so we can just add this IPA claim and proof
603+
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1154): We shouldn't add these to the public inputs for
604+
// now since we don't handle them correctly. Uncomment when we start using UltraRollupHonk in the rollup.
605+
// builder->add_ipa_claim(client_ivc_rec_verifier_output.opening_claim.get_witness_indices());
606+
// builder->ipa_proof = convert_stdlib_proof_to_native(client_ivc_rec_verifier_output.ipa_transcript->proof_data);
607+
602608
using Prover = UltraProver_<UltraFlavor>;
603609
using Verifier = UltraVerifier_<UltraFlavor>;
604610
Prover tube_prover{ *builder };
@@ -622,8 +628,9 @@ void prove_tube(const std::string& output_path)
622628
write_file(tubeAsFieldsVkPath, { data.begin(), data.end() });
623629

624630
info("Native verification of the tube_proof");
625-
Verifier tube_verifier(tube_verification_key);
626-
bool verified = tube_verifier.verify_proof(tube_proof);
631+
auto ipa_verification_key = std::make_shared<VerifierCommitmentKey<curve::Grumpkin>>(1 << CONST_ECCVM_LOG_N);
632+
Verifier tube_verifier(tube_verification_key, ipa_verification_key);
633+
bool verified = tube_verifier.verify_proof(tube_proof, builder->ipa_proof);
627634
info("Tube proof verification: ", verified);
628635
}
629636

@@ -1066,7 +1073,7 @@ UltraProver_<Flavor> compute_valid_prover(const std::string& bytecodePath,
10661073
using Prover = UltraProver_<Flavor>;
10671074

10681075
bool honk_recursion = false;
1069-
if constexpr (IsAnyOf<Flavor, UltraFlavor, UltraKeccakFlavor>) {
1076+
if constexpr (IsAnyOf<Flavor, UltraFlavor, UltraKeccakFlavor, UltraRollupFlavor>) {
10701077
honk_recursion = true;
10711078
}
10721079
auto constraint_system = get_constraint_system(bytecodePath, honk_recursion);
@@ -1132,14 +1139,22 @@ template <IsUltraFlavor Flavor> bool verify_honk(const std::string& proof_path,
11321139
{
11331140
using VerificationKey = Flavor::VerificationKey;
11341141
using Verifier = UltraVerifier_<Flavor>;
1135-
using VerifierCommitmentKey = bb::VerifierCommitmentKey<curve::BN254>;
11361142

11371143
auto g2_data = get_bn254_g2_data(CRS_PATH);
11381144
srs::init_crs_factory({}, g2_data);
11391145
auto proof = from_buffer<std::vector<bb::fr>>(read_file(proof_path));
11401146
auto vk = std::make_shared<VerificationKey>(from_buffer<VerificationKey>(read_file(vk_path)));
1141-
vk->pcs_verification_key = std::make_shared<VerifierCommitmentKey>();
1142-
Verifier verifier{ vk };
1147+
vk->pcs_verification_key = std::make_shared<VerifierCommitmentKey<curve::BN254>>();
1148+
1149+
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1154): Remove this and pass in the IPA proof to the
1150+
// verifier.
1151+
std::shared_ptr<VerifierCommitmentKey<curve::Grumpkin>> ipa_verification_key = nullptr;
1152+
if constexpr (HasIPAAccumulatorFlavor<Flavor>) {
1153+
init_grumpkin_crs(1 << 16);
1154+
vk->contains_ipa_claim = false;
1155+
ipa_verification_key = std::make_shared<VerifierCommitmentKey<curve::Grumpkin>>(1 << CONST_ECCVM_LOG_N);
1156+
}
1157+
Verifier verifier{ vk, ipa_verification_key };
11431158

11441159
bool verified = verifier.verify_proof(proof);
11451160

barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ void ClientIVC::instantiate_stdlib_verification_queue(
2525
size_t key_idx = 0;
2626
for (auto& [proof, vkey, type] : verification_queue) {
2727
// Construct stdlib proof directly from the internal native queue data
28-
auto stdlib_proof = bb::convert_proof_to_witness(&circuit, proof);
28+
auto stdlib_proof = bb::convert_native_proof_to_stdlib(&circuit, proof);
2929

3030
// Use the provided stdlib vkey if present, otherwise construct one from the internal native queue
3131
auto stdlib_vkey =
@@ -261,7 +261,7 @@ HonkProof ClientIVC::construct_and_prove_hiding_circuit()
261261
auto stdlib_decider_vk =
262262
std::make_shared<RecursiveVerificationKey>(&builder, verification_queue[0].honk_verification_key);
263263

264-
auto stdlib_proof = bb::convert_proof_to_witness(&builder, fold_proof);
264+
auto stdlib_proof = bb::convert_native_proof_to_stdlib(&builder, fold_proof);
265265

266266
// Perform recursive folding verification of the last folding proof
267267
FoldingRecursiveVerifier folding_verifier{ &builder, stdlib_verifier_accumulator, { stdlib_decider_vk } };

barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp

+28
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#pragma once
22

33
#include "barretenberg/commitment_schemes/commitment_key.hpp"
4+
#include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp"
45
#include "barretenberg/polynomials/polynomial.hpp"
6+
#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp"
57

68
namespace bb {
79
/**
@@ -51,6 +53,32 @@ template <typename Curve> class OpeningClaim {
5153
// commitment to univariate polynomial p(X)
5254
Commitment commitment;
5355

56+
IPAClaimIndices get_witness_indices() const
57+
requires(std::is_same_v<Curve, stdlib::grumpkin<UltraCircuitBuilder>>)
58+
{
59+
return { opening_pair.challenge.binary_basis_limbs[0].element.normalize().witness_index,
60+
opening_pair.challenge.binary_basis_limbs[1].element.normalize().witness_index,
61+
opening_pair.challenge.binary_basis_limbs[2].element.normalize().witness_index,
62+
opening_pair.challenge.binary_basis_limbs[3].element.normalize().witness_index,
63+
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1153): Uncomment this when we turn the
64+
// eval into witnesses.
65+
// opening_pair.evaluation.binary_basis_limbs[0].element.normalize().witness_index,
66+
// opening_pair.evaluation.binary_basis_limbs[1].element.normalize().witness_index,
67+
// opening_pair.evaluation.binary_basis_limbs[2].element.normalize().witness_index,
68+
// opening_pair.evaluation.binary_basis_limbs[3].element.normalize().witness_index,
69+
commitment.x.normalize().witness_index, // no idea if we need these normalize() calls...
70+
commitment.y.normalize().witness_index };
71+
}
72+
73+
auto get_native_opening_claim() const
74+
requires(Curve::is_stdlib_type)
75+
{
76+
return OpeningClaim<typename Curve::NativeCurve>{
77+
{ static_cast<typename Curve::NativeCurve::ScalarField>(opening_pair.challenge.get_value()),
78+
static_cast<typename Curve::NativeCurve::ScalarField>(opening_pair.evaluation.get_value()) },
79+
commitment.get_value()
80+
};
81+
}
5482
/**
5583
* @brief inefficiently check that the claim is correct by recomputing the commitment
5684
* and evaluating the polynomial in r.

barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp

+22-5
Original file line numberDiff line numberDiff line change
@@ -749,20 +749,21 @@ template <typename Curve_> class IPA {
749749
}
750750

751751
/**
752-
* @brief Takes two IPA claims and accumulates them into 1 IPA claim.
753-
* @details We create an IPA accumulator by running the IPA recursive verifier on each claim. Then, we generate challenges, and use these challenges to compute the new accumulator. We also create the accumulated polynomial.
752+
* @brief Takes two IPA claims and accumulates them into 1 IPA claim. Also computes IPA proof for the claim.
753+
* @details We create an IPA accumulator by running the IPA recursive verifier on each claim. Then, we generate challenges, and use these challenges to compute the new accumulator. We also create the accumulated polynomial, and generate the IPA proof for the accumulated claim.
754754
* More details are described here: https://hackmd.io/IXoLIPhVT_ej8yhZ_Ehvuw?both.
755755
*
756756
* @param verifier_ck
757757
* @param transcript_1
758758
* @param claim_1
759759
* @param transcript_2
760760
* @param claim_2
761-
* @return std::pair<OpeningClaim<Curve>, Polynomial<bb::fq>>
761+
* @return std::pair<OpeningClaim<Curve>, HonkProof>
762762
*/
763-
static std::pair<OpeningClaim<Curve>, Polynomial<bb::fq>> accumulate(auto& transcript_1, OpeningClaim<Curve> claim_1, auto& transcript_2, OpeningClaim<Curve> claim_2)
763+
static std::pair<OpeningClaim<Curve>, HonkProof> accumulate(const std::shared_ptr<CommitmentKey<curve::Grumpkin>>& ck, auto& transcript_1, OpeningClaim<Curve> claim_1, auto& transcript_2, OpeningClaim<Curve> claim_2)
764764
requires Curve::is_stdlib_type
765765
{
766+
using NativeCurve = curve::Grumpkin;
766767
using Builder = typename Curve::Builder;
767768
// Step 1: Run the verifier for each IPA instance
768769
VerifierAccumulator pair_1 = reduce_verify(claim_1, transcript_1);
@@ -793,7 +794,23 @@ template <typename Curve_> class IPA {
793794
for (Fr u_inv_i : pair_2.u_challenges_inv) {
794795
native_u_challenges_inv_2.push_back(bb::fq(u_inv_i.get_value()));
795796
}
796-
return {output_claim, create_challenge_poly(uint32_t(pair_1.log_poly_length.get_value()), native_u_challenges_inv_1, uint32_t(pair_2.log_poly_length.get_value()), native_u_challenges_inv_2, fq(alpha.get_value()))};
797+
798+
// Compute proof for the claim
799+
auto prover_transcript = std::make_shared<NativeTranscript>();
800+
const OpeningPair<NativeCurve> opening_pair{ bb::fq(output_claim.opening_pair.challenge.get_value()),
801+
bb::fq(output_claim.opening_pair.evaluation.get_value()) };
802+
Polynomial<fq> challenge_poly = create_challenge_poly(uint32_t(pair_1.log_poly_length.get_value()), native_u_challenges_inv_1, uint32_t(pair_2.log_poly_length.get_value()), native_u_challenges_inv_2, fq(alpha.get_value()));
803+
804+
ASSERT(challenge_poly.evaluate(opening_pair.challenge) == opening_pair.evaluation && "Opening claim does not hold for challenge polynomial.");
805+
806+
IPA<NativeCurve>::compute_opening_proof(ck, { challenge_poly, opening_pair }, prover_transcript);
807+
808+
// Since we know this circuit will not have any more IPA claims to accumulate, add IPA Claim to public inputs of circuit and add the proof to the builder.
809+
Builder* builder = r.get_context();
810+
builder->add_ipa_claim(output_claim.get_witness_indices());
811+
builder->ipa_proof = prover_transcript->proof_data;
812+
813+
return {output_claim, prover_transcript->proof_data};
797814
}
798815
};
799816

barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/ipa_recursive.test.cpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ class IPARecursiveTests : public CommitmentTest<NativeCurve> {
5656
OpeningClaim<Curve> stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm };
5757

5858
// Construct stdlib verifier transcript
59-
auto recursive_verifier_transcript =
60-
std::make_shared<StdlibTranscript>(bb::convert_proof_to_witness(&builder, prover_transcript->proof_data));
59+
auto recursive_verifier_transcript = std::make_shared<StdlibTranscript>(
60+
bb::convert_native_proof_to_stdlib(&builder, prover_transcript->proof_data));
6161
return { recursive_verifier_transcript, stdlib_opening_claim };
6262
}
6363

@@ -158,25 +158,21 @@ class IPARecursiveTests : public CommitmentTest<NativeCurve> {
158158

159159
// Creates two IPA accumulators and accumulators from the two claims. Also constructs the accumulated h
160160
// polynomial.
161-
auto [output_claim, challenge_poly] = RecursiveIPA::accumulate(transcript_1, claim_1, transcript_2, claim_2);
161+
auto [output_claim, ipa_proof] =
162+
RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2);
162163
builder.finalize_circuit(/*ensure_nonzero=*/false);
163164
info("Circuit with 2 IPA Recursive Verifiers and IPA Accumulation num finalized gates = ",
164165
builder.get_num_finalized_gates());
165166

166167
EXPECT_TRUE(CircuitChecker::check(builder));
167168

168-
// Run the IPA prover on this new accumulated claim.
169-
auto prover_transcript = std::make_shared<NativeTranscript>();
170169
const OpeningPair<NativeCurve> opening_pair{ bb::fq(output_claim.opening_pair.challenge.get_value()),
171170
bb::fq(output_claim.opening_pair.evaluation.get_value()) };
172171
Commitment native_comm = output_claim.commitment.get_value();
173172
const OpeningClaim<NativeCurve> opening_claim{ opening_pair, native_comm };
174173

175-
NativeIPA::compute_opening_proof(this->ck(), { challenge_poly, opening_pair }, prover_transcript);
176-
177-
EXPECT_EQ(challenge_poly.evaluate(opening_pair.challenge), opening_pair.evaluation);
178174
// Natively verify this proof to check it.
179-
auto verifier_transcript = std::make_shared<NativeTranscript>(prover_transcript->proof_data);
175+
auto verifier_transcript = std::make_shared<NativeTranscript>(ipa_proof);
180176

181177
auto result = NativeIPA::reduce_verify(this->vk(), opening_claim, verifier_transcript);
182178
EXPECT_TRUE(result);

barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle)
8888
N, RefVector(f_polynomials), RefVector(g_polynomials), u_challenge, commitment_key, prover_transcript);
8989
KZG<NativeCurve>::compute_opening_proof(commitment_key, prover_opening_claims, prover_transcript);
9090
Builder builder;
91-
StdlibProof<Builder> stdlib_proof = bb::convert_proof_to_witness(&builder, prover_transcript->proof_data);
91+
StdlibProof<Builder> stdlib_proof = bb::convert_native_proof_to_stdlib(&builder, prover_transcript->proof_data);
9292
auto stdlib_verifier_transcript = std::make_shared<Transcript>(stdlib_proof);
9393
stdlib_verifier_transcript->template receive_from_prover<Fr>("Init");
9494

barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ TEST(ZeroMorphRecursionTest, ProveAndVerifySingle)
9595
prover_transcript);
9696

9797
Builder builder;
98-
StdlibProof<Builder> stdlib_proof = bb::convert_proof_to_witness(&builder, prover_transcript->proof_data);
98+
StdlibProof<Builder> stdlib_proof = bb::convert_native_proof_to_stdlib(&builder, prover_transcript->proof_data);
9999
auto stdlib_verifier_transcript = std::make_shared<Transcript>(stdlib_proof);
100100
[[maybe_unused]] auto _ = stdlib_verifier_transcript->template receive_from_prover<Fr>("Init");
101101

barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp

+2-9
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ void process_plonk_recursion_constraints(Builder& builder,
299299
// they want these constants set by keeping the nested aggregation object attached to
300300
// the proof as public inputs. As this is the only object that can prepended to the
301301
// proof if the proof is above the expected size (with public inputs stripped)
302-
PairingPointAccumPubInputIndices nested_aggregation_object = {};
302+
PairingPointAccumulatorPubInputIndices nested_aggregation_object = {};
303303
// If the proof has public inputs attached to it, we should handle setting the nested
304304
// aggregation object
305305
if (constraint.proof.size() > proof_size_no_pub_inputs) {
@@ -343,16 +343,9 @@ void process_plonk_recursion_constraints(Builder& builder,
343343
// inputs.
344344
if (!constraint_system.recursion_constraints.empty()) {
345345

346-
// First add the output aggregation object as public inputs
347-
// Set the indices as public inputs because they are no longer being
348-
// created in ACIR
349-
for (const auto& idx : current_output_aggregation_object) {
350-
builder.set_public_input(idx);
351-
}
352-
353346
// Make sure the verification key records the public input indices of the
354347
// final recursion output.
355-
builder.set_pairing_point_accumulator(current_output_aggregation_object);
348+
builder.add_pairing_point_accumulator(current_output_aggregation_object);
356349
}
357350
}
358351

barretenberg/cpp/src/barretenberg/examples/join_split/join_split.test.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ using namespace bb::join_split_example::proofs::notes::native;
3333
using key_pair = join_split_example::fixtures::grumpkin_key_pair;
3434

3535
auto create_account_leaf_data(fr const& account_alias_hash,
36-
grumpkin::g1::affine_element const& owner_key,
37-
grumpkin::g1::affine_element const& signing_key)
36+
bb::grumpkin::g1::affine_element const& owner_key,
37+
bb::grumpkin::g1::affine_element const& signing_key)
3838
{
3939
return notes::native::account::account_note{ account_alias_hash, owner_key, signing_key }.commit();
4040
}
@@ -869,7 +869,7 @@ TEST_P(test_allow_chain_to_other_users_fail, )
869869
{
870870
join_split_tx tx = simple_setup();
871871
tx.allow_chain = GetParam();
872-
tx.output_note[tx.allow_chain - 1].owner = grumpkin::g1::element::random_element(); // i.e. not owned by self.
872+
tx.output_note[tx.allow_chain - 1].owner = bb::grumpkin::g1::element::random_element(); // i.e. not owned by self.
873873
auto result = sign_and_verify_logic(tx, user.owner);
874874
EXPECT_FALSE(result.valid);
875875
EXPECT_EQ(result.err, "inter-user chaining disallowed");
@@ -1028,7 +1028,7 @@ TEST_F(join_split_tests, test_total_output_value_larger_than_total_input_value_f
10281028
TEST_F(join_split_tests, test_different_input_note_owners_fails)
10291029
{
10301030
join_split_tx tx = simple_setup({ 1, 2 });
1031-
tx.input_note[0].owner = grumpkin::g1::affine_element::hash_to_curve({ 1 });
1031+
tx.input_note[0].owner = bb::grumpkin::g1::affine_element::hash_to_curve({ 1 });
10321032

10331033
auto result = sign_and_verify_logic(tx, user.owner);
10341034
EXPECT_FALSE(result.valid);
@@ -1073,7 +1073,7 @@ TEST_F(join_split_tests, test_different_note_account_required_vs_account_require
10731073
TEST_F(join_split_tests, test_wrong_input_note_owner_fails)
10741074
{
10751075
join_split_tx tx = simple_setup();
1076-
tx.input_note[0].owner = grumpkin::g1::element::random_element();
1076+
tx.input_note[0].owner = bb::grumpkin::g1::element::random_element();
10771077
tx.input_note[1].owner = tx.input_note[0].owner;
10781078

10791079
auto result = sign_and_verify_logic(tx, user.owner);
@@ -1084,8 +1084,8 @@ TEST_F(join_split_tests, test_wrong_input_note_owner_fails)
10841084
TEST_F(join_split_tests, test_random_output_note_owners)
10851085
{
10861086
join_split_tx tx = simple_setup();
1087-
tx.output_note[0].owner = grumpkin::g1::element::random_element();
1088-
tx.output_note[1].owner = grumpkin::g1::element::random_element();
1087+
tx.output_note[0].owner = bb::grumpkin::g1::element::random_element();
1088+
tx.output_note[1].owner = bb::grumpkin::g1::element::random_element();
10891089

10901090
EXPECT_TRUE(sign_and_verify_logic(tx, user.owner).valid);
10911091
}
@@ -1097,7 +1097,7 @@ TEST_F(join_split_tests, test_random_output_note_owners)
10971097
TEST_F(join_split_tests, test_wrong_account_private_key_fails)
10981098
{
10991099
join_split_tx tx = simple_setup();
1100-
tx.account_private_key = grumpkin::fr::random_element();
1100+
tx.account_private_key = bb::grumpkin::fr::random_element();
11011101

11021102
auto result = sign_and_verify_logic(tx, user.owner);
11031103
EXPECT_FALSE(result.valid);

0 commit comments

Comments
 (0)