Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
sparse_commitment.test.cpp
Go to the documentation of this file.
5
6#include <gtest/gtest.h>
7
8namespace bb {
9
10template <typename Curve> class CommitmentKeyTest : public ::testing::Test {
12
13 using Fr = typename Curve::ScalarField;
16
21
22 public:
23 template <class CK> CK create_commitment_key(size_t num_points);
24
25 // Construct a random poly with the prescribed block structure; complement is zero/constant if non_zero_complement =
26 // false/true (to mimic wire/z_perm)
27 StructuredPolyData create_structured_test_polynomial(std::vector<uint32_t> fixed_sizes,
28 std::vector<uint32_t> actual_sizes,
29 bool non_zero_complement = false)
30 {
31 // Add zero row offset to mimic actual structure of wire/z_perm
32 const size_t ZERO_ROW_OFFSET = 1;
33
34 uint32_t full_size = ZERO_ROW_OFFSET;
35 for (auto size : fixed_sizes) {
36 full_size += size;
37 }
38 // In practice the polynomials will have a power-of-2 size
39 auto log2_n = static_cast<size_t>(numeric::get_msb(full_size));
40 if ((1UL << log2_n) != (full_size)) {
41 ++log2_n;
42 }
43 full_size = 1 << log2_n;
44
45 // Construct polynomial with the specified form and track active range endpoints
46 Polynomial polynomial(full_size - 1, full_size, 1);
47 uint32_t start_idx = ZERO_ROW_OFFSET;
48 uint32_t end_idx = 0;
49 std::vector<std::pair<size_t, size_t>> active_range_endpoints;
50 for (auto [fixed_size, actual_size] : zip_view(fixed_sizes, actual_sizes)) {
51 end_idx = start_idx + actual_size;
52 active_range_endpoints.emplace_back(start_idx, end_idx);
53 for (size_t idx = start_idx; idx < end_idx; ++idx) {
54 polynomial.at(idx) = Fr::random_element();
55 }
56 start_idx += fixed_size;
57 }
58
59 // If non_zero_complement, populate the space between active regions with a random constant value
60 if (non_zero_complement) {
61 for (size_t i = 0; i < active_range_endpoints.size() - 1; ++i) {
62 const size_t start = active_range_endpoints[i].second;
63 const size_t end = active_range_endpoints[i + 1].first;
64 Fr const_val = Fr::random_element();
65 for (size_t idx = start; idx < end; ++idx) {
66 polynomial.at(idx) = const_val;
67 }
68 }
69 }
70
71 return { polynomial, active_range_endpoints };
72 }
73};
74
75template <>
76template <>
77CommitmentKey<curve::BN254> CommitmentKeyTest<curve::BN254>::create_commitment_key<CommitmentKey<curve::BN254>>(
78 const size_t num_points)
79{
81 return CommitmentKey<curve::BN254>(num_points);
82}
83
84template <>
85template <>
87 CommitmentKey<curve::Grumpkin>>(const size_t num_points)
88{
90 return CommitmentKey<curve::Grumpkin>(num_points);
91}
92
93using Curves = ::testing::Types<curve::BN254, curve::Grumpkin>;
94
96
97// Check that commit for a structured polynomial and the same polynomial but full return the same results
99{
100 using Curve = TypeParam;
101 using CK = CommitmentKey<Curve>;
102 using G1 = Curve::AffineElement;
103 using Fr = Curve::ScalarField;
105
106 const size_t num_points = 1 << 5; // large enough to ensure normal pippenger logic is used
107 const size_t start_index = 13; // random start index
108 const size_t num_nonzero = 13; // random size
109
110 // Construct a random structured polynomial
111 Polynomial poly{ num_nonzero, num_points, start_index };
112 for (size_t i = start_index; i < start_index + num_nonzero; ++i) {
113 poly.at(i) = Fr::random_element();
114 }
115
116 // Commit to the polynomial and the same polynomial but full
117 auto key = TestFixture::template create_commitment_key<CK>(num_points);
118 G1 commit_result = key.commit(poly);
119 auto full_poly = poly.full();
120 G1 full_commit_result = key.commit(full_poly);
121
122 EXPECT_EQ(commit_result, full_commit_result);
123}
124
125// Check that commit for a structured polynomial and the same polynomial but full return the same results
127{
128 using Curve = TypeParam;
129 using CK = CommitmentKey<Curve>;
130 using G1 = Curve::AffineElement;
131 using Fr = Curve::ScalarField;
133
134 const size_t num_points = 4096; // large enough to ensure normal pippenger logic is used
135 const size_t start_index = 1402; // random start index
136 const size_t num_nonzero = 1392; // random size
137
138 // Construct a random structured polynomial
139 Polynomial poly{ num_nonzero, num_points, start_index };
140 for (size_t i = start_index; i < start_index + num_nonzero; ++i) {
141 poly.at(i) = Fr::random_element();
142 }
143
144 // Commit to the polynomial and the same polynomial but full
145 auto key = TestFixture::template create_commitment_key<CK>(num_points);
146 G1 commit_result = key.commit(poly);
147 auto full_poly = poly.full();
148 G1 full_commit_result = key.commit(full_poly);
149
150 EXPECT_EQ(commit_result, full_commit_result);
151}
152
153// Check that commit for a structured polynomial doesn't require more SRS points beyond the size of the polynomial
155{
156 using Curve = TypeParam;
157 using CK = CommitmentKey<Curve>;
158 using G1 = Curve::AffineElement;
159 using Fr = Curve::ScalarField;
161
162 const size_t num_points = 32; // large enough to ensure normal pippenger logic is used
163 const size_t start_index = 15; // just slightly less than half
164 const size_t num_nonzero = 17; // fill to the end of the size
165
166 // Construct a random structured polynomial
167 Polynomial poly{ num_nonzero, num_points, start_index };
168 for (size_t i = start_index; i < start_index + num_nonzero; ++i) {
169 poly.at(i) = Fr::random_element();
170 }
171
172 // Commit to the polynomial and the same polynomial but full
173 auto key = TestFixture::template create_commitment_key<CK>(num_points);
174 G1 commit_result = key.commit(poly);
175 auto full_poly = poly.full();
176 G1 full_commit_result = key.commit(full_poly);
177
178 EXPECT_EQ(commit_result, full_commit_result);
179}
180
185TYPED_TEST(CommitmentKeyTest, CommitStructuredWire)
186{
187 using Curve = TypeParam;
188 using CK = CommitmentKey<Curve>;
189 using G1 = Curve::AffineElement;
190
192 GTEST_SKIP() << "Skipping test for Grumpkin as it has too small a CRS.";
193 }
194
195 // Arbitrary but realistic block structure in the ivc setting (roughly 2^19 full size with 2^17 utlization)
196 std::vector<uint32_t> fixed_sizes = { 1000, 4000, 180000, 90000, 9000, 137000, 72000, 4000, 2500, 11500 };
197 std::vector<uint32_t> actual_sizes = { 10, 16, 48873, 18209, 4132, 23556, 35443, 3, 2, 2 };
198
199 // Construct a random polynomial resembling the wires in the structured trace setting
200 const bool non_zero_complement = false;
201 auto [polynomial, active_range_endpoints] =
202 TestFixture::create_structured_test_polynomial(fixed_sizes, actual_sizes, non_zero_complement);
203
204 // Commit to the polynomial using both the conventional commit method and the sparse commitment method
205 auto key = TestFixture::template create_commitment_key<CK>(polynomial.virtual_size());
206
207 auto full_poly = polynomial.full();
208 G1 actual_expected_result = key.commit(full_poly);
209 G1 expected_result = key.commit(polynomial);
210 G1 result = key.commit_structured(polynomial, active_range_endpoints);
211 EXPECT_EQ(actual_expected_result, expected_result);
212 EXPECT_EQ(result, expected_result);
213}
214
219TYPED_TEST(CommitmentKeyTest, CommitStructuredMaskedWire)
220{
221 using Curve = TypeParam;
222 using CK = CommitmentKey<Curve>;
223 using G1 = Curve::AffineElement;
224
225 const uint32_t circuit_size = 8192;
226 // To ensure that commit_structured is used.
227 const uint32_t actual_size = circuit_size / 8;
228
229 // Create a polynomial with a block of zeroes between actual_size and circuit_size - NUM_DISABLED_ROWS_IN_SUMCHECK.
230 // We subtract 1 to account for ZERO_ROW_OFFSET
231 std::vector<uint32_t> fixed_sizes = { circuit_size - 1 - NUM_DISABLED_ROWS_IN_SUMCHECK,
232 NUM_DISABLED_ROWS_IN_SUMCHECK };
233 std::vector<uint32_t> actual_sizes = { actual_size, NUM_DISABLED_ROWS_IN_SUMCHECK };
234
235 // Construct a random polynomial resembling a masked structured wire
236 const bool non_zero_complement = false;
237 auto [polynomial, active_range_endpoints] =
238 TestFixture::create_structured_test_polynomial(fixed_sizes, actual_sizes, non_zero_complement);
239
240 // Commit to the polynomial using both the conventional commit method and the sparse commitment method
241 auto key = TestFixture::template create_commitment_key<CK>(polynomial.virtual_size());
242
243 auto full_poly = polynomial.full();
244 G1 actual_expected_result = key.commit(full_poly);
245 G1 expected_result = key.commit(polynomial);
246 G1 result = key.commit_structured(polynomial, active_range_endpoints);
247 EXPECT_EQ(actual_expected_result, expected_result);
248 EXPECT_EQ(result, expected_result);
249}
250
256TYPED_TEST(CommitmentKeyTest, CommitStructuredNonzeroComplement)
257{
258 using Curve = TypeParam;
259 using CK = CommitmentKey<Curve>;
260 using G1 = Curve::AffineElement;
261
263 GTEST_SKIP() << "Skipping test for Grumpkin as it has too small a CRS.";
264 }
265
266 // Arbitrary but realistic block structure in the ivc setting (roughly 2^19 full size with 2^17 utlization)
267 std::vector<uint32_t> fixed_sizes = { 1000, 4000, 180000, 90000, 9000, 137000, 72000, 4000, 2500, 11500 };
268 std::vector<uint32_t> actual_sizes = { 10, 16, 48873, 18209, 4132, 23556, 35443, 3, 2, 2 };
269
270 // Construct a random polynomial resembling z_perm in the structured trace setting
271 const bool non_zero_complement = true;
272 auto [polynomial, active_range_endpoints] =
273 TestFixture::create_structured_test_polynomial(fixed_sizes, actual_sizes, non_zero_complement);
274
275 // Commit to the polynomial using both the conventional commit method and the sparse commitment method
276 auto key = TestFixture::template create_commitment_key<CK>(polynomial.virtual_size());
277
278 G1 expected_result = key.commit(polynomial);
279 G1 result = key.commit_structured_with_nonzero_complement(polynomial, active_range_endpoints);
280
281 EXPECT_EQ(result, expected_result);
282}
283
284} // namespace bb
CommitmentKey object over a pairing group 𝔾₁.
typename Curve::AffineElement Commitment
CK create_commitment_key(size_t num_points)
StructuredPolyData create_structured_test_polynomial(std::vector< uint32_t > fixed_sizes, std::vector< uint32_t > actual_sizes, bool non_zero_complement=false)
typename Curve::ScalarField Fr
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
typename Group::affine_element AffineElement
Definition grumpkin.hpp:56
bool expected_result
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
::testing::Types< curve::BN254, curve::Grumpkin > Curves
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Curve::AffineElement G1
std::vector< std::pair< size_t, size_t > > active_range_endpoints
static field random_element(numeric::RNG *engine=nullptr) noexcept