Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
graph_description_ipa_recursive.test.cpp
Go to the documentation of this file.
12
13using namespace bb;
14using namespace cdg;
18
19class BoomerangIPARecursiveTests : public CommitmentTest<NativeCurve> {
20 public:
21 using Fr = typename NativeCurve::ScalarField;
28
30 // `FailureMode::None` corresponds to a normal, completeness test. The other cases are legitimate failure modes,
31 // where the test should fail. As neither `a_0` nor `G_0` are hashed, the corresponding variants will not fail for
32 // Fiat-Shamir reasons. The last failure mode is: we send an OpeningClaim to the hash buffer, then
33 // we have the prover run the IPA process with a _different polynomial_.
35
51 template <size_t log_poly_length>
53 Polynomial& poly,
54 Fr x)
55 {
56 using NativeIPA = IPA<NativeCurve, log_poly_length>;
57 EXPECT_EQ(1UL << log_poly_length, poly.size());
58 Commitment commitment = this->commit(poly);
59 auto eval = poly.evaluate(x);
60
61 const OpeningPair<NativeCurve> opening_pair = { x, eval };
62 const ProverOpeningClaim<NativeCurve> prover_claim{ poly, opening_pair };
63 // initialize empty prover transcript
64 auto prover_transcript = std::make_shared<NativeTranscript>();
65 using DataType = NativeTranscript::DataType;
66 std::vector<DataType> proof;
67 // Normal operation
68 NativeIPA::compute_opening_proof(this->ck(), prover_claim, prover_transcript);
69 proof = prover_transcript->export_proof();
70
71 // initialize verifier transcript from proof data
72 auto verifier_transcript = std::make_shared<NativeTranscript>(proof);
73
74 // Recursively verify the proof
75 auto stdlib_comm = Curve::Group::from_witness(&builder, commitment);
76 auto stdlib_x = Curve::ScalarField::from_witness(&builder, x);
77 auto stdlib_eval = Curve::ScalarField::from_witness(&builder, eval);
78 OpeningClaim<Curve> stdlib_opening_claim{ { stdlib_x, stdlib_eval }, stdlib_comm };
79
80 // Construct stdlib verifier transcript
81 auto recursive_verifier_transcript = std::make_shared<StdlibTranscript>(StdlibProof(builder, proof));
82 return { recursive_verifier_transcript, stdlib_opening_claim };
83 }
84
93 template <size_t log_poly_length> Builder build_ipa_recursive_verifier_circuit(Polynomial& poly, Fr x)
94 {
95 using RecursiveIPA = IPA<Curve, log_poly_length>;
96
98 auto [stdlib_transcript, stdlib_claim] = create_ipa_claim<log_poly_length>(builder, poly, x);
99
100 RecursiveIPA::reduce_verify(stdlib_claim, stdlib_transcript);
102 builder.finalize_circuit(/*ensure_nonzero=*/true);
103 return builder;
104 }
105 // flag to determine what type of polynomial to generate
107
108 template <size_t log_poly_length>
110 {
111
112 static constexpr size_t poly_length = 1UL << log_poly_length;
113 Polynomial poly(poly_length);
114 switch (poly_type) {
115 case PolyType::Random:
116 poly = Polynomial::random(poly_length);
117 break;
119 poly = Polynomial::random(poly_length);
120 for (size_t i = 0; i < poly_length / 2; ++i) {
121 poly.at(i) = Fr::zero();
122 }
123 break;
124 case PolyType::Sparse:
125 // set a few coefficients to be non-zero
126 for (size_t i = 0; i < std::min<size_t>(100, poly_length / 2); ++i) {
127 size_t idx = static_cast<size_t>(this->engine->get_random_uint64() % poly_length);
128 poly.at(idx) = this->random_element();
129 }
130 break;
131 case PolyType::Zero:
132 break;
133 }
134 auto x = this->random_element();
135 return { poly, x };
136 }
137
142 template <size_t log_poly_length> void test_recursive_ipa(Polynomial& poly, Fr x)
143 {
145 Builder builder(build_ipa_recursive_verifier_circuit<log_poly_length>(poly, x));
146 info("IPA Recursive Verifier num finalized gates = ", builder.get_num_finalized_gates());
147 EXPECT_TRUE(CircuitChecker::check(builder));
148 }
149
156 template <size_t log_poly_length> void test_accumulation(Polynomial& poly1, Polynomial& poly2, Fr x1, Fr x2)
157 {
158 using NativeIPA = IPA<NativeCurve, log_poly_length>;
159 using RecursiveIPA = IPA<Curve, log_poly_length>;
160
161 // We create a circuit that does two IPA verifications. However, we don't do the full verifications and instead
162 // accumulate the claims into one claim. This accumulation is done in circuit. Create two accumulators, which
163 // contain the commitment and an opening claim.
165 auto [transcript_1, claim_1] = create_ipa_claim<log_poly_length>(builder, poly1, x1);
166 auto [transcript_2, claim_2] = create_ipa_claim<log_poly_length>(builder, poly2, x2);
167
168 // Creates two IPA accumulators and accumulators from the two claims. Also constructs the accumulated h
169 // polynomial.
170 auto [output_claim, ipa_proof] =
171 RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2);
172 output_claim.set_public();
173 output_claim.commitment.fix_witness();
174 builder.ipa_proof = ipa_proof;
175 builder.finalize_circuit(/*ensure_nonzero=*/false);
176 EXPECT_TRUE(CircuitChecker::check(builder));
177
178 const OpeningPair<NativeCurve> opening_pair{ bb::fq(output_claim.opening_pair.challenge.get_value()),
179 bb::fq(output_claim.opening_pair.evaluation.get_value()) };
180 Commitment native_comm = output_claim.commitment.get_value();
181 const OpeningClaim<NativeCurve> opening_claim{ opening_pair, native_comm };
182
183 // Natively verify this proof to check it.
184 auto verifier_transcript = std::make_shared<NativeTranscript>(ipa_proof);
185
186 auto result = NativeIPA::reduce_verify(this->vk(), opening_claim, verifier_transcript);
187 EXPECT_TRUE(result);
188
189 auto tool = StaticAnalyzer(builder);
190 auto tool_results = tool.analyze_circuit();
191 EXPECT_EQ(tool_results.first.size(), 1);
192 EXPECT_EQ(tool_results.second.size(), 0);
193 }
194};
195
196TEST_F(BoomerangIPARecursiveTests, FullRecursiveVerifierMediumRandom)
197{
198 static constexpr size_t log_poly_length = 10;
199 static constexpr size_t poly_length = 1UL << log_poly_length;
200 using RecursiveIPA = IPA<Curve, log_poly_length>;
201
203 auto [poly, x] = generate_poly_and_challenge<log_poly_length>();
204 auto [stdlib_transcript, stdlib_claim] = create_ipa_claim<log_poly_length>(builder, poly, x);
205
206 VerifierCommitmentKey<Curve> stdlib_pcs_vkey(&builder, poly_length, this->vk());
207 auto result = RecursiveIPA::full_verify_recursive(stdlib_pcs_vkey, stdlib_claim, stdlib_transcript);
208 EXPECT_TRUE(result);
209 builder.finalize_circuit(/*ensure_nonzero=*/true);
210
211 auto tool = StaticAnalyzer(builder);
212 auto tool_results = tool.analyze_circuit();
213 EXPECT_EQ(tool_results.first.size(), 1);
214 EXPECT_EQ(tool_results.second.size(), 0);
215}
216
217TEST_F(BoomerangIPARecursiveTests, AccumulateSmallRandom)
218{
219 static constexpr size_t log_poly_length = 2;
220 auto [poly1, x1] = generate_poly_and_challenge<log_poly_length>(PolyType::Random);
221 auto [poly2, x2] = generate_poly_and_challenge<log_poly_length>(PolyType::Random);
222 test_accumulation<log_poly_length>(poly1, poly2, x1, x2);
223}
224
225TEST_F(BoomerangIPARecursiveTests, AccumulateMediumRandom)
226{
227 static constexpr size_t log_poly_length = 10;
228 auto [poly1, x1] = generate_poly_and_challenge<log_poly_length>();
229 auto [poly2, x2] = generate_poly_and_challenge<log_poly_length>();
230 test_accumulation<log_poly_length>(poly1, poly2, x1, x2);
231}
232
233TEST_F(BoomerangIPARecursiveTests, AccumulateMediumFirstZeroPoly)
234{
235 static constexpr size_t log_poly_length = 10;
236 static constexpr size_t poly_length = 1UL << log_poly_length;
237 Polynomial poly1(poly_length);
238 auto x1 = this->random_element();
239 auto [poly2, x2] = generate_poly_and_challenge<log_poly_length>();
240 test_accumulation<log_poly_length>(poly1, poly2, x1, x2);
241}
242
243TEST_F(BoomerangIPARecursiveTests, AccumulationAndFullRecursiveVerifierMediumRandom)
244{
245 static constexpr size_t log_poly_length = 10;
246 using RecursiveIPA = IPA<Curve, log_poly_length>;
247
248 // We create a circuit that does two IPA verifications. However, we don't do the full verifications and instead
249 // accumulate the claims into one claim. This accumulation is done in circuit. Create two accumulators, which
250 // contain the commitment and an opening claim.
252
253 auto [poly1, x1] = generate_poly_and_challenge<log_poly_length>();
254 auto [poly2, x2] = generate_poly_and_challenge<log_poly_length>();
255
256 auto [transcript_1, claim_1] = create_ipa_claim<log_poly_length>(builder, poly1, x1);
257 auto [transcript_2, claim_2] = create_ipa_claim<log_poly_length>(builder, poly2, x2);
258
259 // Creates two IPA accumulators and accumulators from the two claims. Also constructs the accumulated h
260 // polynomial.
261 auto [output_claim, ipa_proof] = RecursiveIPA::accumulate(this->ck(), transcript_1, claim_1, transcript_2, claim_2);
262 output_claim.set_public();
263 builder.ipa_proof = ipa_proof;
264 builder.finalize_circuit(/*ensure_nonzero=*/false);
265
266 Builder root_rollup;
267 // Fully recursively verify this proof to check it.
268 VerifierCommitmentKey<Curve> stdlib_pcs_vkey(&root_rollup, 1UL << log_poly_length, this->vk());
269 auto stdlib_verifier_transcript = std::make_shared<StdlibTranscript>(StdlibProof(root_rollup, ipa_proof));
270 OpeningClaim<Curve> ipa_claim;
271 ipa_claim.opening_pair.challenge =
272 Curve::ScalarField::create_from_u512_as_witness(&root_rollup, output_claim.opening_pair.challenge.get_value());
273 ipa_claim.opening_pair.evaluation =
274 Curve::ScalarField::create_from_u512_as_witness(&root_rollup, output_claim.opening_pair.evaluation.get_value());
275 ipa_claim.commitment = Curve::AffineElement::from_witness(&root_rollup, output_claim.commitment.get_value());
276 auto result = RecursiveIPA::full_verify_recursive(stdlib_pcs_vkey, ipa_claim, stdlib_verifier_transcript);
277 root_rollup.finalize_circuit(/*ensure_nonzero=*/true);
278 EXPECT_TRUE(result);
279
280 auto tool = StaticAnalyzer(root_rollup);
281 auto tool_results = tool.analyze_circuit();
282 EXPECT_EQ(tool_results.first.size(), 1);
283 EXPECT_EQ(tool_results.second.size(), 0);
284}
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:32
std::pair< std::shared_ptr< StdlibTranscript >, OpeningClaim< Curve > > create_ipa_claim(Builder &builder, Polynomial &poly, Fr x)
Given a builder, polynomial, and challenge point, return the transcript and opening claim in circuit.
std::tuple< Polynomial, Fr > generate_poly_and_challenge(PolyType poly_type=PolyType::Random)
Builder build_ipa_recursive_verifier_circuit(Polynomial &poly, Fr x)
Given a poly and a challenge x, return the recursive verifier circuit.
void test_accumulation(Polynomial &poly1, Polynomial &poly2, Fr x1, Fr x2)
Tests IPA accumulation by accumulating two IPA claims and proving the accumulated claim.
typename NativeCurve::AffineElement Commitment
void test_recursive_ipa(Polynomial &poly, Fr x)
Tests IPA recursion.
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
typename Codec::DataType DataType
CommitmentKey object over a pairing group 𝔾₁.
Commitment commit(const Polynomial &polynomial)
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:93
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:53
OpeningPair< Curve > opening_pair
Definition claim.hpp:62
Commitment commitment
Definition claim.hpp:64
Opening pair (r,v) for some witness polynomial p(X) such that p(r) = v.
Definition claim.hpp:19
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
static Polynomial random(size_t size, size_t start_index=0)
Fr evaluate(const Fr &z, size_t target_size) const
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
std::size_t size() const
Polynomial p and an opening pair (r,v) such that p(r) = v.
Definition claim.hpp:34
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
typename Group::element Element
Definition grumpkin.hpp:62
typename Group::affine_element AffineElement
Definition grumpkin.hpp:63
virtual uint64_t get_random_uint64()=0
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:19
static void add_default(Builder &builder)
Add default public inputs when they are not present.
void info(Args... args)
Definition log.hpp:75
AluTraceBuilder builder
Definition alu.test.cpp:124
TEST_F(BoomerangIPARecursiveTests, FullRecursiveVerifierMediumRandom)
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
field< Bn254FqParams > fq
Definition fq.hpp:169
BaseTranscript< stdlib::StdlibCodec< stdlib::field_t< UltraCircuitBuilder > >, stdlib::poseidon2< UltraCircuitBuilder > > UltraStdlibTranscript
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
Definition graph.cpp:14
UltraStaticAnalyzer StaticAnalyzer
Definition graph.hpp:187
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field zero()
Curve grumpkin in circuit setting.
Definition grumpkin.hpp:21