Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
biggroup_secp256k1.test.cpp
Go to the documentation of this file.
1#include "../bigfield/bigfield.hpp"
2#include "../biggroup/biggroup.hpp"
3#include "../bool/bool.hpp"
4#include "../field/field.hpp"
14#include "gtest/gtest.h"
15#include <vector>
16
17using namespace bb;
18
19namespace {
21}
22
23template <typename Curve> class stdlibBiggroupSecp256k1 : public testing::Test {
24 public:
25 // We always use bigfield for secp256k1 as the scalar field is large.
26 using element_ct = typename Curve::Group;
27 using scalar_ct = typename Curve::ScalarField;
28
29 using fq = typename Curve::BaseFieldNative;
30 using fr = typename Curve::ScalarFieldNative;
31 using g1 = typename Curve::GroupNative;
33 using element = typename g1::element;
34
35 using Builder = typename Curve::Builder;
38
39 static constexpr auto EXPECT_CIRCUIT_CORRECTNESS = [](Builder& builder, bool expected_result = true) {
40 info("num gates = ", builder.get_num_finalized_gates_inefficient());
42 };
43
44 // Primitives functions for computing wnafs over secp256k1 scalars
45 template <size_t wnaf_size> void test_get_staggered_wnaf_fragment_value()
46 {
47 // Helper for easier invocation
48 auto get_val = [](uint64_t fragment_u64, uint64_t stagger, bool is_negative, bool wnaf_skew) {
49 return stdlib::element_default::element_test_accessor::
50 get_staggered_wnaf_fragment_value<Builder, typename Curve::BaseField, scalar_ct, g1, wnaf_size>(
51 fragment_u64, stagger, is_negative, wnaf_skew);
52 };
53
54 // Test: stagger == 0 returns (0, wnaf_skew)
55 {
56 auto [frag, skew] = get_val(123, 0, false, false);
57 EXPECT_EQ(frag, 0);
58 EXPECT_EQ(skew, false);
59
60 auto [frag2, skew2] = get_val(456, 0, true, true);
61 EXPECT_EQ(frag2, 0);
62 EXPECT_EQ(skew2, true);
63 }
64 // Test: random positive values (honest case)
65 {
66 for (size_t i = 0; i < 20; ++i) {
67 // Check for various stagger values ≤ 10
68 for (size_t num_stagger_bits = 1; num_stagger_bits <= 10; ++num_stagger_bits) {
69 uint64_t input_frag = engine.get_random_uint32() % (1ULL << num_stagger_bits);
70 bool inp_skew = engine.get_random_uint32() & 1;
71 bool is_negative = false;
72
73 auto [output_frag, output_skew] = get_val(input_frag, num_stagger_bits, is_negative, inp_skew);
74
75 // input_frag - inp_skew * 2^t == output_wnaf - output_skew
76 int lhs = static_cast<int>(input_frag) - static_cast<int>(inp_skew * (1ULL << num_stagger_bits));
77
78 int output_wnaf_value =
79 (2 * static_cast<int>(output_frag) + 1) - static_cast<int>(1ULL << wnaf_size);
80 int rhs = output_wnaf_value - static_cast<int>(output_skew);
81
82 EXPECT_EQ(lhs, rhs);
83 }
84 }
85 }
86 // Test: random negative values
87 {
88 for (size_t i = 0; i < 20; ++i) {
89 // Check for various stagger values ≤ 10
90 for (size_t num_stagger_bits = 1; num_stagger_bits <= 10; ++num_stagger_bits) {
91 uint64_t input_frag = engine.get_random_uint32() % (1ULL << num_stagger_bits);
92 bool inp_skew = engine.get_random_uint32() & 1;
93 bool is_negative = true;
94
95 auto [output_frag, output_skew] = get_val(input_frag, num_stagger_bits, is_negative, inp_skew);
96
97 // In case of is_negative = true and input is even, we subtract 1 to make it odd and set skew = 1,
98 // which must be added to the output wnaf value.
99 // - input_frag + inp_skew * 2^t == output_wnaf + output_skew
100 int lhs = -static_cast<int>(input_frag) + static_cast<int>(inp_skew * (1ULL << num_stagger_bits));
101
102 int output_wnaf_value =
103 (2 * static_cast<int>(output_frag) + 1) - static_cast<int>(1ULL << wnaf_size);
104 int rhs = output_wnaf_value + static_cast<int>(output_skew);
105 EXPECT_EQ(lhs, rhs);
106 }
107 }
108 }
109 }
110
111 // Add the necessary utility methods used in tests
113 {
115 {
116 // Generate a random even scalar
117 fr scalar_a(fr::random_element());
118 if ((uint256_t(scalar_a).get_bit(0) & 1) == 1) {
119 scalar_a -= fr(1); // skew bit is 1
120 }
121 scalar_ct x_a = scalar_ct::from_witness(&builder, scalar_a);
122 element_ct::template compute_secp256k1_endo_wnaf<4, 0, 3>(x_a, false);
123 element_ct::template compute_secp256k1_endo_wnaf<4, 1, 2>(x_a, false);
124 element_ct::template compute_secp256k1_endo_wnaf<4, 2, 1>(x_a, false);
125 element_ct::template compute_secp256k1_endo_wnaf<4, 3, 0>(x_a, false);
126 }
127 {
128 // Generate a random odd scalar
129 fr scalar_b(fr::random_element());
130 if ((uint256_t(scalar_b).get_bit(0) & 1) == 0) {
131 scalar_b += fr(1); // skew bit is 0
132 }
133 scalar_ct x_b = scalar_ct::from_witness(&builder, scalar_b);
134 element_ct::template compute_secp256k1_endo_wnaf<4, 0, 3>(x_b, false);
135 element_ct::template compute_secp256k1_endo_wnaf<4, 1, 2>(x_b, false);
136 element_ct::template compute_secp256k1_endo_wnaf<4, 2, 1>(x_b, false);
137 element_ct::template compute_secp256k1_endo_wnaf<4, 3, 0>(x_b, false);
138 }
139
141 }
142
144 {
146 const uint512_t scalar_field_modulus = scalar_ct::modulus_u512;
147
148 // Generate a random scalar k < r (r is the scalar field modulus).
149 const fr scalar_a = fr::random_element();
150 scalar_ct scalar_a_ct = scalar_ct::from_witness(&builder, scalar_a);
151
152 // Generate a large scalar k' := (k + mr) > r where r is the scalar field modulus and m >= 1
153 // We need k' be larger than 256 bits to test the edge case properly. We achieve this by choosing
154 // m = 2^256 / r + 1, which guarantees that r < 2^256 < k'.
155 uint512_t m = ((uint512_t(1) << 256) / scalar_field_modulus) + 1;
156 uint512_t large_value = uint512_t(scalar_a) + (m * scalar_field_modulus);
157 scalar_ct large_scalar_ct = scalar_ct::create_from_u512_as_witness(&builder, large_value, true);
158 EXPECT_EQ(large_scalar_ct.get_value() >= (uint512_t(1) << 256), true);
159 EXPECT_EQ(large_scalar_ct.get_value() >= uint512_t(scalar_field_modulus), true);
160 EXPECT_EQ(large_scalar_ct.get_value() % uint512_t(scalar_field_modulus), uint512_t(scalar_a));
161
162 // circuit wnaf computation should work fine for scalar k
163 element_ct::template compute_secp256k1_endo_wnaf<4, 0, 1>(scalar_a_ct, false);
164
165 // circuit wnaf computation should also work for the large scalar k'
166 element_ct::template compute_secp256k1_endo_wnaf<4, 0, 1>(large_scalar_ct, false);
167
169 }
170
172 {
174 const uint512_t scalar_field_modulus = scalar_ct::modulus_u512;
175
176 // Generate a scalar k such that k < (2^256 - r)
177 const size_t num_allowed_bits = ((uint512_t(1) << 256) - scalar_field_modulus).get_msb();
178 const fr scalar_a = uint256_t(fr::random_element()) & ((uint256_t(1) << num_allowed_bits) - 1);
179 scalar_ct scalar_a_ct = scalar_ct::from_witness(&builder, scalar_a);
180
181 // Generate a large scalar k' := (k + r) < 2^256 (because k < 2^256 - r)
182 uint512_t large_value = uint512_t(scalar_a) + scalar_field_modulus;
183 scalar_ct large_scalar_ct = scalar_ct::create_from_u512_as_witness(&builder, large_value, true);
184 EXPECT_EQ(large_scalar_ct.get_value() < (uint512_t(1) << 256), true);
185 EXPECT_EQ(large_scalar_ct.get_value() >= uint512_t(scalar_field_modulus), true);
186 EXPECT_EQ(large_scalar_ct.get_value() % uint512_t(scalar_field_modulus), uint512_t(scalar_a));
187
188 // circuit wnaf computation should work fine for scalar k
189 element_ct::template compute_secp256k1_endo_wnaf<4, 0, 1>(scalar_a_ct, false);
190
191 // circuit wnaf computation should also work for the large scalar k'
192 element_ct::template compute_secp256k1_endo_wnaf<4, 0, 1>(large_scalar_ct, false);
193
195 }
196
198 {
200 { // Generate a random even scalar
201 fr scalar_a(fr::random_element());
202 if ((uint256_t(scalar_a).get_bit(0) & 1) == 1) {
203 scalar_a -= fr(1); // skew bit is 1
204 }
205 scalar_ct x_a = scalar_ct::from_witness(&builder, scalar_a);
206 element_ct::template compute_secp256k1_endo_wnaf<8, 0, 3>(x_a, false);
207 element_ct::template compute_secp256k1_endo_wnaf<8, 1, 2>(x_a, false);
208 element_ct::template compute_secp256k1_endo_wnaf<8, 2, 1>(x_a, false);
209 element_ct::template compute_secp256k1_endo_wnaf<8, 3, 0>(x_a, false);
210 }
211 {
212 // Generate a random odd scalar
213 fr scalar_b(fr::random_element());
214 if ((uint256_t(scalar_b).get_bit(0) & 1) == 0) {
215 scalar_b += fr(1); // skew bit is 0
216 }
217 scalar_ct x_b = scalar_ct::from_witness(&builder, scalar_b);
218 element_ct::template compute_secp256k1_endo_wnaf<8, 0, 3>(x_b, false);
219 element_ct::template compute_secp256k1_endo_wnaf<8, 1, 2>(x_b, false);
220 element_ct::template compute_secp256k1_endo_wnaf<8, 2, 1>(x_b, false);
221 element_ct::template compute_secp256k1_endo_wnaf<8, 3, 0>(x_b, false);
222 }
223
225 }
226
228 {
230 size_t num_repetitions = 1;
231 for (size_t i = 0; i < num_repetitions; ++i) {
232 fr scalar_a(fr::random_element());
233 fr scalar_b(fr::random_element());
234 fr scalar_c(fr::random_element());
235 if ((uint256_t(scalar_a).get_bit(0) & 1) == 1) {
236 scalar_a -= fr(1); // skew bit is 1
237 }
238 element_ct P_a = element_ct::from_witness(&builder, g1::one * scalar_c);
239 scalar_ct u1 = scalar_ct::from_witness(&builder, scalar_a);
240 scalar_ct u2 = scalar_ct::from_witness(&builder, scalar_b);
241
242 fr alo;
243 fr ahi;
244 fr blo;
245 fr bhi;
246
249
250 auto output = element_ct::secp256k1_ecdsa_mul(P_a, u1, u2);
251
252 auto expected = affine_element(g1::one * (scalar_c * scalar_b) + g1::one * scalar_a);
253 EXPECT_EQ(output.x().get_value().lo, uint256_t(expected.x));
254 EXPECT_EQ(output.y().get_value().lo, uint256_t(expected.y));
255 }
256
258 }
259
261 {
262 // The scalars s1, u1, u2 are chosen such that:
263 // Public key: P = (s1 * G)
264 //
265 // u1 * G + u2 * (s1 * G) = ø
266 //
267 // where ø is the point at infinity.
268 //
269 // The issue with such input was that we were not setting the point at infinity correctly
270 // while adding the skew points. For the cases when we reach the point at infinity and still have
271 // skew to add, we did not correctly set the flag _is_point_at_infinity. For this example, we have:
272 //
273 // u1_low skew: 0
274 // u1_high skew: 1
275 // u2_low skew: 1
276 // u2_high skew: 0
277 //
278 // After adding the u2_low skew (i.e., its base point), we get the point at infinity. Then we handle the
279 // u2 high skew as follows:
280 // result = acc ± u1_high_base_point
281 // result.x() = u2_high_skew ? result.x() : acc.x();
282 // result.y() = u2_high_skew ? result.y() : acc.y();
283 //
284 // However, we did not set the flag _is_point_at_infinity for result. We must copy the flag from the
285 // accumulator in this case, i.e., we must do:
286 // result.x() = u2_high_skew ? result.x() : acc.x();
287 // result.y() = u2_high_skew ? result.y() : acc.y();
288 // result._is_point_at_infinity = u2_high_skew ? result._is_point_at_infinity :
289 // acc._is_point_at_infinity;
290 //
291 // We define a new function `conditional_select` that does this operation and use it to handle the skew
292 // addition.
293 const uint256_t scalar_s1("0x66ad81e84534c20431c795de922fb592c3d8c68edcacfc6c5b52ab7ad10e47d3");
294 const uint256_t scalar_u1("0x37e0ba2e9c4dd42077fd751a7426a8484a8ff2928a6c85a651e4470b461c6215");
295 const uint256_t scalar_u2("0xdefbb9bbabde5b9f8d7175946e75babc2f11203a8bfb71beaeec1d7a2bff17dd");
296
297 // Check the assumptions
298 BB_ASSERT(scalar_s1 < fr::modulus);
299 BB_ASSERT(scalar_u1 < fr::modulus);
300 BB_ASSERT(scalar_u2 < fr::modulus);
301 BB_ASSERT((fr(scalar_s1) * fr(scalar_u2) + fr(scalar_u1)).is_zero());
302 BB_ASSERT((g1::one * fr(scalar_u1) + (g1::one * fr(scalar_s1)) * fr(scalar_u2)).is_point_at_infinity());
303
304 // Check that the wnaf skews of the lo and hi parts of u2 are as expected
305 fr u2_lo;
306 fr u2_hi;
307 fr::split_into_endomorphism_scalars(fr(scalar_u2).from_montgomery_form(), u2_lo, u2_hi);
308 BB_ASSERT(uint256_t(u2_lo).get_bit(0) == 0); // u2_lo skew is 1 (even)
309 BB_ASSERT(uint256_t(u2_hi).get_bit(0) == 1); // u2_hi skew is 0 (odd)
310
312 element_ct P_a = element_ct::from_witness(&builder, g1::one * fr(scalar_s1));
313 scalar_ct u1 = scalar_ct::from_witness(&builder, fr(scalar_u1));
314 scalar_ct u2 = scalar_ct::from_witness(&builder, fr(scalar_u2));
315 auto output = element_ct::secp256k1_ecdsa_mul(P_a, u1, u2);
316
317 // Check that the output is the point at infinity
318 EXPECT_EQ(output.is_point_at_infinity().get_value(), true);
319
321 }
322
324 {
325 // This test uses the same idea as the skew handling regression test above.
326 // However, in this test, we use scalars to ensure that we are correctly handling the stagger offsets
327 // before adding the skew points. The scalars s1, u1, u2 are chosen such that: Public key: P = (s1 * G)
328 //
329 // u1 * G + u2 * (s1 * G) = ø
330 //
331 // where ø is the point at infinity. For this set of scalars, we have all the skews as 0.
332 // This means that we will reach the point at infinity while adding the stagger fragments of the
333 // scalars. Since we compute the wnaf with stagger offsets:
334 //
335 // compute_secp256k1_endo_wnaf<8, 2, 3>(u1, false);
336 // compute_secp256k1_endo_wnaf<4, 0, 1>(u2, false);
337 //
338 // we have the following stagger offsets:
339 // u1_low stagger bits: 2 <== add_3 = 2G
340 // u1_high stagger bits: 3 <== add_1 = 3λG
341 // u2_low stagger bits: 0
342 // u2_high stagger bits: 1 <== add_2 = λG
343 //
344 // Hence we add these terms to the accumulator using addition chain:
345 // acc += (((add_1) + add_2) + add_3).
346 //
347 // After adding add_2, the x-coordinate of the accumulator is equal to the x-coordinate of add_3.
348 // Using incomplete addition formulae, we catch a circuit error as the addition is not valid if the
349 // x-coordinates are equal. To avoid this, we use the complete addition formulae to add add_1, add_2,
350 // add_3 to the accumulator. The increases the circuit size for secp256k1_ecdsa_mul by 730 gates but we
351 // accept that for now to ensure correctness.
352 //
353 const uint256_t scalar_g1("0x9d496650d261d31af6aa4cf41e435ed739d0fe2c34728a21a0df5c66a3504ccd");
354 const uint256_t scalar_u1("0xf3d9f52f0f55d3da6f902aa842aa604005633f3d165bc800f3a3aa661b18df5f");
355 const uint256_t scalar_u2("0x1323b0342b1a56a076cbf5e3899156fbf3f439f2c3b0d5a95b9ef74622447f2e");
356
357 // Check the assumptions
358 BB_ASSERT(scalar_g1 < fr::modulus);
359 BB_ASSERT(scalar_u1 < fr::modulus);
360 BB_ASSERT(scalar_u2 < fr::modulus);
361 BB_ASSERT((fr(scalar_g1) * fr(scalar_u2) + fr(scalar_u1)).is_zero());
362 BB_ASSERT((g1::one * fr(scalar_u1) + (g1::one * fr(scalar_g1)) * fr(scalar_u2)).is_point_at_infinity());
363
364 // Create the circuit
366 element_ct P_a = element_ct::from_witness(&builder, g1::one * fr(scalar_g1));
367 scalar_ct u1 = scalar_ct::from_witness(&builder, fr(scalar_u1));
368 scalar_ct u2 = scalar_ct::from_witness(&builder, fr(scalar_u2));
369 auto output = element_ct::secp256k1_ecdsa_mul(P_a, u1, u2);
370
371 // Check that the output is the point at infinity
372 EXPECT_EQ(output.is_point_at_infinity().get_value(), true);
373
375 }
376
378 {
379 // ============================================================================
380 // REGRESSION TEST: Intermediate collision in Montgomery ladder
381 // ============================================================================
382 //
383 // Edge case: u1·G + u2·P = O (point at infinity).
384 //
385 // The secp256k1_ecdsa_mul function uses multiple_montgomery_ladder which computes:
386 // multiple_montgomery_ladder([A, B, C]) = 2·(2·(2·Q + A) + B) + C
387 //
388 // At each step, it computes R_{i+1} = 2·R_i + P_i using the Montgomery ladder:
389 // 1. Compute (R_i + P_i) with coordinates (x_3, y_3)
390 // 2. Compute (R_i + P_i) + R_i with slope λ₂ = (y_Ri - y_3) / (x_Ri - x_3)
391 //
392 // When x_Ri == x_3 (R_i and R_i+P_i have the same x-coordinate), we run into division by zero!
393 //
394 // When computing u1·G + u2·P = O with random scalars, the probability of hitting
395 // an intermediate collision is negligible (~1/2^256).
396 //
397 // But when we CONSTRAIN u1 = -(u2·s), the wNAF digits of u1 and u2 become correlated.
398 // Some (u2, s) pairs produce wNAF decompositions where an intermediate partial sum leads to
399 // a point at infinity. We are testing one such (u2, s) pair here.
400 //
401 // Disable asserts to test circuit error handling
403
404 const uint256_t scalar_s_val("0xa829a047d570ff736a868434729a1d364547f538ead58ddf5acf9b9811da7017");
405 const uint256_t scalar_u1_val("0x5ab31ec9ed17cb51e6c706b3ebcd7aaef9f33b4e0fa80f68d2923b7aa432ac3c");
406 const uint256_t scalar_u2_val("0x089dc0bec4aba71bc35daf714bf21f221890b47a12944e8a156a32fd27d8e963");
407
408 fr scalar_s(scalar_s_val);
409 fr scalar_u1(scalar_u1_val);
410 fr scalar_u2(scalar_u2_val);
411
412 // Verify the relationship: u1 = -u2 * s (mod r)
413 EXPECT_EQ(scalar_u1, -(scalar_u2 * scalar_s));
414
415 // Verify u1*G + u2*P = O (the final result is point at infinity)
416 element expected_result = g1::one * scalar_u1 + (g1::one * scalar_s) * scalar_u2;
417 EXPECT_TRUE(expected_result.is_point_at_infinity());
418
419 // Create circuit elements
421 element_ct P_a = element_ct::from_witness(&builder, g1::one * scalar_s);
422 scalar_ct u1 = scalar_ct::from_witness(&builder, scalar_u1);
423 scalar_ct u2 = scalar_ct::from_witness(&builder, scalar_u2);
424
425 // Call secp256k1_ecdsa_mul
426 element_ct::secp256k1_ecdsa_mul(P_a, u1, u2);
427
428 // Verify that circuit fails
430 EXPECT_EQ(builder.err(), "biggroup::multiple_montgomery_ladder: x-coordinates must be distinct.");
431 }
432};
433
434// Then define the test types
436 testing::Types<stdlib::secp256k1<bb::UltraCircuitBuilder>, stdlib::secp256k1<bb::MegaCircuitBuilder>>;
437
438// Now register the test suite with the types
440
441// Define the individual tests
442TYPED_TEST(stdlibBiggroupSecp256k1, GetStaggeredWnafFragmentValue4bit)
443{
444 TestFixture::template test_get_staggered_wnaf_fragment_value<4>();
445}
446TYPED_TEST(stdlibBiggroupSecp256k1, GetStaggeredWnafFragmentValue8bit)
447{
448 TestFixture::template test_get_staggered_wnaf_fragment_value<8>();
449}
451{
452 TestFixture::test_wnaf_secp256k1();
453}
454TYPED_TEST(stdlibBiggroupSecp256k1, WnafSecp256k1LargeScalarRegression1)
455{
456 TestFixture::test_wnaf_secp256k1_scalar_exceeding_modulus_regression_1();
457}
458TYPED_TEST(stdlibBiggroupSecp256k1, WnafSecp256k1LargeScalarRegression2)
459{
460 TestFixture::test_wnaf_secp256k1_scalar_exceeding_modulus_regression_2();
461}
463{
464 TestFixture::test_wnaf_8bit_secp256k1();
465}
467{
468 TestFixture::test_ecdsa_mul_secp256k1();
469}
470TYPED_TEST(stdlibBiggroupSecp256k1, EcdsaMulSecp256k1SkewHandlingRegression)
471{
472 TestFixture::test_secp256k1_ecdsa_mul_skew_handling_regression();
473}
474TYPED_TEST(stdlibBiggroupSecp256k1, EcdsaMulSecp256k1StaggerRegression)
475{
476 TestFixture::test_secp256k1_ecdsa_mul_stagger_regression();
477}
478TYPED_TEST(stdlibBiggroupSecp256k1, EcdsaMulSecp256k1PointAtInfinityFails)
479{
480 TestFixture::test_secp256k1_ecdsa_mul_point_at_infinity_fails();
481}
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:33
testing::Types< stdlib::secp256k1< bb::UltraCircuitBuilder >, stdlib::secp256k1< bb::MegaCircuitBuilder > > Secp256k1TestTypes
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
typename grumpkin::g1 Group
Definition grumpkin.hpp:63
group_elements::affine_element< Fq, Fr, Params > affine_element
Definition group.hpp:42
static constexpr element one
Definition group.hpp:46
group_elements::element< Fq, Fr, Params > element
Definition group.hpp:41
virtual uint32_t get_random_uint32()=0
constexpr uint64_t get_msb() const
Definition uintx.hpp:68
Implements boolean logic in-circuit.
Definition bool.hpp:60
typename Curve::BaseFieldNative fq
static void test_secp256k1_ecdsa_mul_skew_handling_regression()
static void test_wnaf_secp256k1_scalar_exceeding_modulus_regression_1()
static constexpr auto EXPECT_CIRCUIT_CORRECTNESS
typename Curve::ScalarFieldNative fr
static void test_wnaf_secp256k1_scalar_exceeding_modulus_regression_2()
typename Curve::ScalarField scalar_ct
typename Curve::Builder Builder
typename g1::affine_element affine_element
static void test_secp256k1_ecdsa_mul_stagger_regression()
typename Curve::GroupNative g1
static void test_secp256k1_ecdsa_mul_point_at_infinity_fails()
#define info(...)
Definition log.hpp:93
AluTraceBuilder builder
Definition alu.test.cpp:124
bool expected_result
numeric::RNG & engine
uintx< uint256_t > uint512_t
Definition uintx.hpp:306
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:217
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TYPED_TEST_SUITE(CommitmentKeyTest, Curves)
TYPED_TEST(CommitmentKeyTest, CommitToZeroPoly)
This file contains part of the logic for the Origin Tag mechanism that tracks the use of in-circuit p...
static constexpr uint256_t modulus
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
Full-width endomorphism decomposition: k ≡ k1 - k2·λ (mod r). Modifies the field elements k1 and k2.
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field from_montgomery_form() const noexcept