Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
triple_ipa.test.cpp
Go to the documentation of this file.
5
6#include <array>
7#include <numeric>
8
9using namespace bb;
10
11namespace {
12
14
15class TripleIPATest : public CommitmentTest<Curve> {
16 public:
17 using Fr = typename Curve::ScalarField;
18 using CK = CommitmentKey<Curve>;
20 using Poly = bb::Polynomial<Fr>;
21
22 static constexpr size_t LOG_N = 4;
23 static constexpr size_t N = 1UL << LOG_N;
25
26 static CK ck;
27 static VK vk;
28
29 static void SetUpTestSuite()
30 {
31 // Use the shared file CRS factory (like every other commitment-scheme suite). Installing a small in-memory
32 // Grumpkin factory here would shrink the global factory and starve later Grumpkin suites in the same binary.
34 ck = CK(N);
36 }
37
38 static Fr inner_product(const Poly& left, std::span<const Fr> right)
39 {
40 BB_ASSERT_EQ(right.size(), N);
41 Fr result = Fr::zero();
42 for (size_t idx = 0; idx < N; ++idx) {
43 result += left[idx] * right[idx];
44 }
45 return result;
46 }
47
48 // The non-cyclic shift tensor (b_sh[0] = 0, b_sh[i] = eq(u)_{i-1}) used to compute the shifted-source evaluations.
49 // There is no production materializer for it, and evaluate_mle(shift=true) asserts a zero constant term that the
50 // random sources here violate, so it is built explicitly off the production eq. (The fold itself is unit-tested in
51 // polynomials/shifted_eq_polynomial.test.cpp.)
52 static std::vector<Fr> shift_tensor(const std::vector<Fr>& point)
53 {
54 const auto eq = ProverEqPolynomial<Fr>::construct(point, LOG_N);
55 std::vector<Fr> result(N, Fr::zero());
56 for (size_t idx = 1; idx < N; ++idx) {
57 result[idx] = eq[idx - 1];
58 }
59 return result;
60 }
61
62 PCS::TripleIpaInput create_input()
63 {
65 const auto multilinear_challenge = this->random_evaluation_point(LOG_N);
66 input.claim_data.unshifted.multilinear_challenge = multilinear_challenge;
67
68 const auto shift = shift_tensor(multilinear_challenge);
69
70 for (size_t idx = 0; idx < 5; ++idx) {
71 auto polynomial = this->random_polynomial(N);
72 input.claim_data.unshifted.evaluations.emplace_back(
73 polynomial.evaluate_mle(std::span<const Fr>(multilinear_challenge)));
74 input.claim_data.unshifted.commitments.emplace_back(ck.commit(polynomial));
75 input.unshifted_polynomials.emplace_back(std::move(polynomial));
76 }
77 input.claim_data.unshifted.rho_powers =
78 PCS::TripleIpaClaimData::rho_powers(this->random_element(), input.unshifted_polynomials.size());
79
80 const std::array<size_t, 2> shifted_sources = { 1, 3 };
81 input.claim_data.shifted.rho_powers =
82 PCS::TripleIpaClaimData::rho_powers(this->random_element(), shifted_sources.size());
83 for (const size_t source_idx : shifted_sources) {
84 input.claim_data.shifted.commitments.emplace_back(input.claim_data.unshifted.commitments[source_idx]);
85 input.claim_data.shifted.source_unshifted_evaluations.emplace_back(
86 input.claim_data.unshifted.evaluations[source_idx]);
87 input.claim_data.shifted.shifted_evaluations.emplace_back(
88 inner_product(input.unshifted_polynomials[source_idx], std::span<const Fr>(shift)));
89 input.shifted_polynomials.emplace_back(input.unshifted_polynomials[source_idx].share());
90 }
91
92 input.univariate_polynomial = this->random_polynomial(N);
93 input.claim_data.univariate.opening_pair.challenge = this->random_element();
94 input.claim_data.univariate.opening_pair.evaluation =
95 input.univariate_polynomial.evaluate(input.claim_data.univariate.opening_pair.challenge);
96 input.claim_data.univariate.commitment = ck.commit(input.univariate_polynomial);
97 return input;
98 }
99
100 static NativeTranscript::Proof prove(const PCS::TripleIpaInput& input)
101 {
102 auto prover_transcript = std::make_shared<NativeTranscript>();
103 PCS::compute_opening_proof(ck, input, prover_transcript);
104 return prover_transcript->export_proof();
105 }
106
107 static bool verify(const PCS::TripleIpaInput& input, const NativeTranscript::Proof& proof)
108 {
109 auto verifier_transcript = std::make_shared<NativeTranscript>(proof);
110 return PCS::reduce_verify(vk, input.claim_data.batch(), verifier_transcript);
111 }
112};
113
114TripleIPATest::CK TripleIPATest::ck;
115TripleIPATest::VK TripleIPATest::vk;
116
117} // namespace
118
119TEST_F(TripleIPATest, NativeProveVerify)
120{
121 const auto input = create_input();
122 const auto proof = prove(input);
123 EXPECT_TRUE(verify(input, proof));
124}
125
126TEST_F(TripleIPATest, NativeVerifierDoesNotNeedWitnessPolynomials)
127{
128 const auto input = create_input();
129 const auto proof = prove(input);
130
131 auto verifier_input = input;
132 verifier_input.unshifted_polynomials.clear();
133 verifier_input.univariate_polynomial = Poly();
134 EXPECT_TRUE(verify(verifier_input, proof));
135}
136
137// Deferred discharge: reduce each proof to a NativeAccumulator (no SRS-MSM), then settle all of them with a single
138// combined MSM via batch_verify_accumulators. This is the path chonk uses to fold many ECCVM openings into one MSM.
139TEST_F(TripleIPATest, NativeBatchVerifyAccumulatorsDischargesMultipleProofs)
140{
141 const auto input1 = create_input();
142 const auto proof1 = prove(input1);
143 const auto input2 = create_input();
144 const auto proof2 = prove(input2);
145
147 PCS::reduce_to_accumulator(input1.claim_data.batch(), std::make_shared<NativeTranscript>(proof1)),
148 PCS::reduce_to_accumulator(input2.claim_data.batch(), std::make_shared<NativeTranscript>(proof2)),
149 };
150
151 EXPECT_TRUE(PCS::batch_verify_accumulators(vk, std::span<const PCS::NativeAccumulator>(accumulators)));
152}
153
154TEST_F(TripleIPATest, NativeBatchVerifyAccumulatorsRejectsTamperedProof)
155{
156 const auto input1 = create_input();
157 const auto proof1 = prove(input1);
158 const auto input2 = create_input();
159 auto proof2 = prove(input2);
160
161 ASSERT_FALSE(proof2.empty());
162 proof2[0] += bb::fr::one();
163
165 PCS::reduce_to_accumulator(input1.claim_data.batch(), std::make_shared<NativeTranscript>(proof1)),
166 PCS::reduce_to_accumulator(input2.claim_data.batch(), std::make_shared<NativeTranscript>(proof2)),
167 };
168
169 EXPECT_FALSE(PCS::batch_verify_accumulators(vk, std::span<const PCS::NativeAccumulator>(accumulators)));
170}
constexpr size_t N
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
std::vector< DataType > Proof
CommitmentKey object over a pairing group 𝔾₁.
CommitmentKey< Curve > CK
Polynomial random_polynomial(const size_t poly_size)
VerifierCommitmentKey< Curve > VK
std::vector< Fr > random_evaluation_point(const size_t num_variables)
static void SetUpTestSuite()
IPA (inner product argument) commitment scheme class.
Definition ipa.hpp:87
static Polynomial< FF > construct(std::span< const FF > challenges, size_t log_num_monomials)
Construct eq(X, r) coefficient table over Boolean hypercube {0,1}^d.
static bool reduce_verify(const VK &vk, const TripleIpaClaim &claim, const std::shared_ptr< Transcript > &transcript)
static void compute_opening_proof(const CK &ck, const TripleIpaInput &input, const std::shared_ptr< Transcript > &transcript)
bb::TripleIpaInput< Curve > TripleIpaInput
Representation of the Grumpkin Verifier Commitment Key inside a bn254 circuit.
void init_grumpkin_file_crs_factory(const std::filesystem::path &path)
std::filesystem::path bb_crs_path()
std::shared_ptr< factories::CrsFactory< curve::Grumpkin > > get_grumpkin_crs_factory()
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:160
constexpr ScalarIndex shift(ScalarIndex ctx, size_t d)
CommitmentKey< Curve > ck
VerifierCommitmentKey< Curve > vk
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field one()
static constexpr field zero()
VectorField result