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>(stdlib_proof);
99 [[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover<Fr>("Init");
100 [[maybe_unused]] auto batched_verifier_claim =
101 ShplonkVerifier::reduce_verification(Commitment::one(&builder), stdlib_opening_claims, verifier_transcript);
102
103 EXPECT_TRUE(CircuitChecker::check(builder));
104}
105
107{
108 using Builder = TypeParam;
112 using ShplonkVerifier = ShplonkVerifier_<Curve>;
113 using Fr = typename Curve::ScalarField;
114 using GroupElement = Curve::Element;
115 using Commitment = typename Curve::AffineElement;
118 using StdlibProof = stdlib::Proof<Builder>;
119
120 // Prover transcript
121 auto prover_transcript = NativeTranscript::prover_init_empty();
122
123 // Generate two random (unrelated) polynomials of two different sizes and a random linear combinations
124 auto setup = this->generate_claim_data({ MAX_POLY_DEGREE, MAX_POLY_DEGREE / 2 });
125
126 // Extract the commitments to be used in the Shplonk verifier
127 auto commitments = ClaimData::polynomial_commitments(setup);
128
129 // Linearly combine the polynomials and evalu
130 auto [coefficients, evals] = this->combine_claims(setup);
131
132 // Shplonk prover functionality
133 auto prover_opening_claims = ClaimData::prover_opening_claims(setup);
134 auto batched_prover_claim = ShplonkProver::prove(this->ck(), prover_opening_claims, prover_transcript);
135 this->verify_opening_pair(batched_prover_claim.opening_pair, batched_prover_claim.polynomial);
136 auto proof = prover_transcript->export_proof();
137
138 auto native_opening_claims = ClaimData::verifier_opening_claims(setup);
139 {
140 // Shplonk verifier functionality - expensive way
141 // Convert proof to stdlib
143 StdlibProof stdlib_proof(builder, proof);
144
145 auto coeff1 = Fr::from_witness(&builder, coefficients[0]);
146 auto coeff2 = Fr::from_witness(&builder, coefficients[1]);
147 // Removing the free witness tag, since the coefficients in the full scheme are supposed to
148 // be fiat-shamirred or derived from the transcript earlier
149 coeff1.unset_free_witness_tag();
150 coeff2.unset_free_witness_tag();
151
152 // Convert opening claims to witnesses
153 auto stdlib_opening_claims =
154 this->native_to_stdlib_opening_claims(&builder, native_opening_claims, native_opening_claims.size() - 1);
155
156 // Compute last commitment as it would happen in a circuit
157 Commitment commit = GroupElement::batch_mul(
158 { stdlib_opening_claims[0].commitment, stdlib_opening_claims[1].commitment }, { coeff1, coeff2 });
159
160 // Opening pair for the linear combination as it would be received by the Verifier from the Prover
161 Fr r = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.challenge);
162 Fr eval = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.evaluation);
163 // Removing the free witness tag, since the opening pairs in the full scheme are supposed to
164 // be fiat-shamirred or derived from the transcript earlier
165 r.unset_free_witness_tag();
166 eval.unset_free_witness_tag();
167
168 // Opening claim for the linear combination
169 stdlib_opening_claims.emplace_back(OpeningClaim({ r, eval }, commit));
170
171 auto verifier_transcript = std::make_shared<Transcript>(stdlib_proof);
172 [[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover<Fr>("Init");
173 [[maybe_unused]] auto batched_verifier_claim =
174 ShplonkVerifier::reduce_verification(Commitment::one(&builder), stdlib_opening_claims, verifier_transcript);
175
176 EXPECT_TRUE(CircuitChecker::check(builder));
177
179 info("Num gates UltraCircuitBuilder (non-efficient way: size-5 MSM + size-2 MSM): ", builder.num_gates());
180 } else if constexpr (std::is_same_v<Builder, MegaCircuitBuilder>) {
181 info("Num MSM rows MegaCircuitBuilder (non-efficient way: size-5 MSM + size-2 MSM): ",
182 builder.op_queue->get_num_rows());
183 }
184 }
185
186 {
187 // Shplonk verifier functionality - efficient way
188 // Convert proof to stdlib
190 StdlibProof stdlib_proof(builder, proof);
191
192 auto coeff1 = Fr::from_witness(&builder, coefficients[0]);
193 auto coeff2 = Fr::from_witness(&builder, coefficients[1]);
194 // Removing the free witness tag, since the coefficients in the full scheme are supposed to
195 // be fiat-shamirred or derived from the transcript earlier
196 coeff1.unset_free_witness_tag();
197 coeff2.unset_free_witness_tag();
198
199 // Convert opening claims to witnesses
200 auto [stdlib_commitments, stdlib_opening_pairs] = this->native_to_stdlib_pairs_and_commitments(
201 &builder, native_opening_claims, native_opening_claims.size() - 1);
202
203 // Opening pair for the linear combination as it would be received by the Verifier from the Prover
204 Fr r = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.challenge);
205 Fr eval = Fr::from_witness(&builder, native_opening_claims[2].opening_pair.evaluation);
206 // Removing the free witness tag, since the opening pairs in the full scheme are supposed to
207 // be fiat-shamirred or derived from the transcript earlier
208 r.unset_free_witness_tag();
209 eval.unset_free_witness_tag();
210
211 // Update data
213 { { 0 }, { Fr(1) }, stdlib_opening_pairs[0] },
214 { { 1 }, { Fr(1) }, stdlib_opening_pairs[1] },
215 { { 0, 1 }, { coeff1, coeff2 }, { r, eval } }
216 };
217
218 // Shplonk verifier functionality - cheap way
219 auto verifier_transcript = std::make_shared<Transcript>(stdlib_proof);
220 [[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover<Fr>("Init");
221
222 ShplonkVerifier verifier(stdlib_commitments, verifier_transcript, native_opening_claims.size());
223
224 // Execute the shplonk verifier functionality
225 [[maybe_unused]] auto batched_verifier_claim =
226 verifier.reduce_verification_vector_claims(this->vk().get_g1_identity(), update_data);
227
228 EXPECT_TRUE(CircuitChecker::check(builder));
229
231 info("Num gates UltraCircuitBuilder (efficient way: size-4 MSM): ", builder.num_gates());
232 } else if constexpr (std::is_same_v<Builder, MegaCircuitBuilder>) {
233 info("Num MSM rows MegaCircuitBuilder (efficient way: size-4 MSM): ", builder.op_queue->get_num_rows());
234 }
235 }
236}
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:62
typename Group::affine_element AffineElement
Definition grumpkin.hpp:63
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:454
void info(Args... args)
Definition log.hpp:75
AluTraceBuilder builder
Definition alu.test.cpp:124
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
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