Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
shplonk.test.cpp
Go to the documentation of this file.
7#include <gtest/gtest.h>
8
9using namespace bb;
10
11static constexpr size_t LOG_DEGREE = 4;
12static constexpr size_t MAX_POLY_DEGREE = 1UL << LOG_DEGREE;
13template <class Builder> class ShplonkRecursionTest : public CommitmentTest<typename curve::BN254> {
14 public:
19
21 Builder* builder, std::vector<OpeningClaim<NativeCurve>>& opening_claims, const size_t num_claims)
22 {
24 for (size_t idx = 0; idx < num_claims; idx++) {
25 auto r = Fr::from_witness(builder, opening_claims[idx].opening_pair.challenge);
26 auto eval = Fr::from_witness(builder, opening_claims[idx].opening_pair.evaluation);
27 auto commit = Commitment::from_witness(builder, opening_claims[idx].commitment);
28 // Removing the free witness tag, since the opening claims in the full scheme are supposed to
29 // be fiat-shamirred or derived from the transcript earlier
30 r.unset_free_witness_tag();
31 eval.unset_free_witness_tag();
32 commit.unset_free_witness_tag();
33 stdlib_opening_claims.emplace_back(OpeningClaim<Curve>({ r, eval }, commit));
34 }
35
36 return stdlib_opening_claims;
37 }
38
40 Builder* builder, std::vector<OpeningClaim<NativeCurve>>& opening_claims, const size_t num_claims)
41 {
42 std::vector<OpeningPair<Curve>> stdlib_opening_pairs;
43 std::vector<Commitment> stdlib_commitments;
44 for (size_t idx = 0; idx < num_claims; idx++) {
45 auto opening_claim = opening_claims[idx];
46 auto r = Fr::from_witness(builder, opening_claim.opening_pair.challenge);
47 auto eval = Fr::from_witness(builder, opening_claim.opening_pair.evaluation);
48 auto commit = Commitment::from_witness(builder, opening_claim.commitment);
49 // Removing the free witness tag, since the opening pairs and commitments in the full scheme are supposed to
50 // be fiat-shamirred or derived from the transcript earlier
51 r.unset_free_witness_tag();
52 eval.unset_free_witness_tag();
53 commit.unset_free_witness_tag();
54 stdlib_opening_pairs.emplace_back(OpeningPair<Curve>(r, eval));
55 stdlib_commitments.emplace_back(commit);
56 }
57
58 return std::make_pair(stdlib_commitments, stdlib_opening_pairs);
59 }
60};
61
62using BuilderTypes = ::testing::Types<UltraCircuitBuilder, MegaCircuitBuilder>;
64
66{
67 using Builder = TypeParam;
71 using ShplonkVerifier = ShplonkVerifier_<Curve>;
72 using Fr = typename Curve::ScalarField;
73 using Commitment = typename Curve::AffineElement;
75 using StdlibProof = stdlib::Proof<Builder>;
76
77 // Prover transcript
78 auto prover_transcript = NativeTranscript::prover_init_empty();
79
80 // Test data
81 auto setup = this->generate_claim_data({ MAX_POLY_DEGREE, MAX_POLY_DEGREE / 2 });
82
83 // Shplonk prover functionality
84 auto prover_opening_claims = ClaimData::prover_opening_claims(setup);
85 auto batched_prover_claim = ShplonkProver::prove(this->ck(), prover_opening_claims, prover_transcript);
86 this->verify_opening_pair(batched_prover_claim.opening_pair, batched_prover_claim.polynomial);
87
88 // Convert proof to stdlib
90 StdlibProof stdlib_proof(builder, prover_transcript->export_proof());
91
92 // Convert opening claims to witnesses
93 auto native_verifier_claims = ClaimData::verifier_opening_claims(setup);
94 auto stdlib_opening_claims =
95 this->native_to_stdlib_opening_claims(&builder, native_verifier_claims, native_verifier_claims.size());
96
97 // Shplonk verifier functionality
98 auto verifier_transcript = std::make_shared<Transcript>();
99 verifier_transcript->load_proof(stdlib_proof);
100 [[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover<Fr>("Init");
101 [[maybe_unused]] auto batched_verifier_claim =
102 ShplonkVerifier::reduce_verification(Commitment::one(&builder), stdlib_opening_claims, verifier_transcript);
103
104 EXPECT_TRUE(CircuitChecker::check(builder));
105}
106
108{
109 using Builder = TypeParam;
113 using ShplonkVerifier = ShplonkVerifier_<Curve>;
114 using Fr = typename Curve::ScalarField;
115 using GroupElement = Curve::Element;
116 using Commitment = typename Curve::AffineElement;
119 using StdlibProof = stdlib::Proof<Builder>;
120
121 // Prover transcript
122 auto prover_transcript = NativeTranscript::prover_init_empty();
123
124 // Generate two random (unrelated) polynomials of two different sizes and a random linear combinations
125 auto setup = this->generate_claim_data({ MAX_POLY_DEGREE, MAX_POLY_DEGREE / 2 });
126
127 // Extract the commitments to be used in the Shplonk verifier
128 auto commitments = ClaimData::polynomial_commitments(setup);
129
130 // Linearly combine the polynomials and evalu
131 auto [coefficients, evals] = this->combine_claims(setup);
132
133 // Shplonk prover functionality
134 auto prover_opening_claims = ClaimData::prover_opening_claims(setup);
135 auto batched_prover_claim = ShplonkProver::prove(this->ck(), prover_opening_claims, prover_transcript);
136 this->verify_opening_pair(batched_prover_claim.opening_pair, batched_prover_claim.polynomial);
137 auto proof = prover_transcript->export_proof();
138
139 auto native_opening_claims = ClaimData::verifier_opening_claims(setup);
140 {
141 // Shplonk verifier functionality - expensive way
142 // Convert proof to stdlib
144 StdlibProof stdlib_proof(builder, proof);
145
146 auto coeff1 = Fr::from_witness(&builder, coefficients[0]);
147 auto coeff2 = Fr::from_witness(&builder, coefficients[1]);
148 // Removing the free witness tag, since the coefficients in the full scheme are supposed to
149 // be fiat-shamirred or derived from the transcript earlier
150 coeff1.unset_free_witness_tag();
151 coeff2.unset_free_witness_tag();
152
153 // Convert opening claims to witnesses
154 auto stdlib_opening_claims =
155 this->native_to_stdlib_opening_claims(&builder, native_opening_claims, native_opening_claims.size() - 1);
156
157 // Compute last commitment as it would happen in a circuit
158 Commitment commit = GroupElement::batch_mul(
159 { stdlib_opening_claims[0].commitment, stdlib_opening_claims[1].commitment }, { coeff1, coeff2 });
160
161 // Opening pair for the linear combination as it would be received by the Verifier from the Prover
162 Fr r = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.challenge);
163 Fr eval = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.evaluation);
164 // Removing the free witness tag, since the opening pairs in the full scheme are supposed to
165 // be fiat-shamirred or derived from the transcript earlier
166 r.unset_free_witness_tag();
167 eval.unset_free_witness_tag();
168
169 // Opening claim for the linear combination
170 stdlib_opening_claims.emplace_back(OpeningClaim({ r, eval }, commit));
171
172 auto verifier_transcript = std::make_shared<Transcript>();
173 verifier_transcript->load_proof(stdlib_proof);
174 [[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover<Fr>("Init");
175 [[maybe_unused]] auto batched_verifier_claim =
176 ShplonkVerifier::reduce_verification(Commitment::one(&builder), stdlib_opening_claims, verifier_transcript);
177
178 EXPECT_TRUE(CircuitChecker::check(builder));
179
181 info("Num gates UltraCircuitBuilder (non-efficient way: size-5 MSM + size-2 MSM): ", builder.num_gates);
182 } else if constexpr (std::is_same_v<Builder, MegaCircuitBuilder>) {
183 info("Num MSM rows MegaCircuitBuilder (non-efficient way: size-5 MSM + size-2 MSM): ",
184 builder.op_queue->get_num_rows());
185 }
186 }
187
188 {
189 // Shplonk verifier functionality - efficient way
190 // Convert proof to stdlib
192 StdlibProof stdlib_proof(builder, proof);
193
194 auto coeff1 = Fr::from_witness(&builder, coefficients[0]);
195 auto coeff2 = Fr::from_witness(&builder, coefficients[1]);
196 // Removing the free witness tag, since the coefficients in the full scheme are supposed to
197 // be fiat-shamirred or derived from the transcript earlier
198 coeff1.unset_free_witness_tag();
199 coeff2.unset_free_witness_tag();
200
201 // Convert opening claims to witnesses
202 auto [stdlib_commitments, stdlib_opening_pairs] = this->native_to_stdlib_pairs_and_commitments(
203 &builder, native_opening_claims, native_opening_claims.size() - 1);
204
205 // Opening pair for the linear combination as it would be received by the Verifier from the Prover
206 Fr r = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.challenge);
207 Fr eval = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.evaluation);
208 // Removing the free witness tag, since the opening pairs in the full scheme are supposed to
209 // be fiat-shamirred or derived from the transcript earlier
210 r.unset_free_witness_tag();
211 eval.unset_free_witness_tag();
212
213 // Update data
215 { { 0 }, { Fr(1) }, stdlib_opening_pairs[0] },
216 { { 1 }, { Fr(1) }, stdlib_opening_pairs[1] },
217 { { 0, 1 }, { coeff1, coeff2 }, { r, eval } }
218 };
219
220 // Shplonk verifier functionality - cheap way
221 auto verifier_transcript = std::make_shared<Transcript>();
222 verifier_transcript->load_proof(stdlib_proof);
223 [[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover<Fr>("Init");
224
225 ShplonkVerifier verifier(stdlib_commitments, verifier_transcript, native_opening_claims.size());
226
227 // Execute the shplonk verifier functionality
228 [[maybe_unused]] auto batched_verifier_claim =
229 verifier.reduce_verification_vector_claims(this->vk().get_g1_identity(), update_data);
230
231 EXPECT_TRUE(CircuitChecker::check(builder));
232
234 info("Num gates UltraCircuitBuilder (efficient way: size-4 MSM): ", builder.num_gates);
235 } else if constexpr (std::is_same_v<Builder, MegaCircuitBuilder>) {
236 info("Num MSM rows MegaCircuitBuilder (efficient way: size-4 MSM): ", builder.op_queue->get_num_rows());
237 }
238 }
239}
Curve::AffineElement Commitment
std::vector< OpeningClaim< Curve > > native_to_stdlib_opening_claims(Builder *builder, std::vector< OpeningClaim< NativeCurve > > &opening_claims, const size_t num_claims)
std::pair< std::vector< Commitment >, std::vector< OpeningPair< Curve > > > native_to_stdlib_pairs_and_commitments(Builder *builder, std::vector< OpeningClaim< NativeCurve > > &opening_claims, const size_t num_claims)
Common transcript class for both parties. Stores the data for the current round, as well as the manif...
static std::shared_ptr< BaseTranscript > prover_init_empty()
For testing: initializes transcript with some arbitrary data so that a challenge can be generated aft...
Commitment commit(const Polynomial &polynomial)
Unverified claim (C,r,v) for some witness polynomial p(X) such that.
Definition claim.hpp:53
Opening pair (r,v) for some witness polynomial p(X) such that p(r) = v.
Definition claim.hpp:19
Shplonk Prover.
Definition shplonk.hpp:36
Shplonk Verifier.
Definition shplonk.hpp:343
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
typename Group::element Element
Definition grumpkin.hpp:55
typename Group::affine_element AffineElement
Definition grumpkin.hpp:56
A simple wrapper around a vector of stdlib field elements representing a proof.
Definition proof.hpp:19
static field_t from_witness(Builder *ctx, const bb::fr &input)
Definition field.hpp:432
void info(Args... args)
Definition log.hpp:74
AluTraceBuilder builder
Definition alu.test.cpp:123
Entry point for Barretenberg command-line interface.
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::ScalarField Fr
::testing::Types< UltraCircuitBuilder, MegaCircuitBuilder > BuilderTypes
field_t< CircuitBuilder > ScalarField
Definition bn254.hpp:33
Group AffineElement
Definition bn254.hpp:37
curve::BN254 NativeCurve
Definition bn254.hpp:21