Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
pedersen.test.cpp
Go to the documentation of this file.
9#include "pedersen.hpp"
10
11using namespace bb;
13namespace {
15}
16
17template <typename Builder> class StdlibPedersen : public testing::Test {
19
20 using fr_ct = typename _curve::ScalarField;
24
25 // Helper to verify pedersen commitment against native implementation
26 static void verify_commitment(Builder& builder [[maybe_unused]],
27 const std::vector<stdlib::field_t<Builder>>& inputs,
29 {
30 // Extract native values from circuit inputs
31 std::vector<fr> input_vals;
32 for (const auto& input : inputs) {
33 input_vals.push_back(input.get_value());
34 }
35
36 auto result = pedersen_commitment::commit(inputs, context);
37 auto expected = crypto::pedersen_commitment::commit_native(input_vals, context);
38
39 EXPECT_EQ(result.x.get_value(), expected.x);
40 EXPECT_EQ(result.y.get_value(), expected.y);
41 }
42
43 public:
44 static void test_pedersen()
45 {
47
48 fr left_in = fr::random_element();
49 fr right_in = fr::random_element();
50
51 // ensure left has skew 1, right has skew 0
52 if ((left_in.from_montgomery_form().data[0] & 1) == 1) {
53 left_in += fr::one();
54 }
55 if ((right_in.from_montgomery_form().data[0] & 1) == 0) {
56 right_in += fr::one();
57 }
58
59 fr_ct left = public_witness_ct(&builder, left_in);
60 fr_ct right = witness_ct(&builder, right_in);
61
62 builder.fix_witness(left.witness_index, left.get_value());
63 builder.fix_witness(right.witness_index, right.get_value());
64
65 std::vector<stdlib::field_t<Builder>> inputs = { left, right };
66
68
69 check_circuit_and_gate_count(builder, 2912);
70 }
71
73 {
76
77 for (size_t i = 0; i < 8; ++i) {
79 if (i % 2 == 0) {
80 inputs.push_back(fr_ct(&builder, value));
81 } else {
82 inputs.push_back(witness_ct(&builder, value));
83 }
84 }
85
87
88 // Gate count different for Mega because it adds constants for ECC op codes that get reused in ROM table access
90 check_circuit_and_gate_count(builder, 3994);
91 } else {
92 check_circuit_and_gate_count(builder, 3997);
93 }
94 }
95
96 static void test_empty_input()
97 {
99 std::vector<fr> inputs;
101
102 // Empty input should return the zero/identity point
103 auto result = pedersen_commitment::commit(witness_inputs);
104
105 // For empty inputs, the circuit returns (0, 0) which is the identity point
106 EXPECT_EQ(result.x.get_value(), fr::zero());
107 EXPECT_EQ(result.y.get_value(), fr::zero());
108
109 check_circuit_and_gate_count(builder, 0);
110 }
111
112 static void test_single_input()
113 {
115 fr input = fr::random_element();
116 std::vector<stdlib::field_t<Builder>> circuit_inputs = { witness_ct(&builder, input) };
117
118 verify_commitment(builder, circuit_inputs);
119 check_circuit_and_gate_count(builder, 2838);
120
121 // Expect table size to be 14340 for single input
122 // i.e. 254 bit scalars handled via 28 9-bit tables (size 2^9) plus one 2-bit table (size 2^2)
123 // i.e. (28*2^9) + (1*2^2) = 14340
124 EXPECT_EQ(builder.get_tables_size(), 14340);
125 }
126
127 // Test demonstrates lookup table optimization for 2 inputs
128 static void test_two_inputs()
129 {
132
133 for (size_t i = 0; i < 2; ++i) {
134 circuit_inputs.push_back(witness_ct(&builder, fr::random_element()));
135 }
136
137 verify_commitment(builder, circuit_inputs);
138 check_circuit_and_gate_count(builder, 2910);
139
140 // Expect table size to be 28680 = 2*14340 for two inputs
141 // Each input uses one Multitable of size 14340
142 EXPECT_EQ(builder.get_tables_size(), 28680);
143 }
144
145 // Test demonstrates gate count jump when lookup tables can't be used (3+ inputs)
146 static void test_three_inputs()
147 {
150
151 for (size_t i = 0; i < 3; ++i) {
152 circuit_inputs.push_back(witness_ct(&builder, fr::random_element()));
153 }
154
155 verify_commitment(builder, circuit_inputs);
156
157 // Gate count different for Mega because it adds constants for ECC op codes that get reused in ROM table access
159 check_circuit_and_gate_count(builder, 3485);
160 } else {
161 check_circuit_and_gate_count(builder, 3488);
162 }
163
164 // Lookup tables size is same as 2 inputs since only the first 2 inputs use lookup tables
165 EXPECT_EQ(builder.get_tables_size(), 28680);
166 }
167
168 static void test_large_input()
169 {
172
173 for (size_t i = 0; i < 32; ++i) {
174 circuit_inputs.push_back(witness_ct(&builder, fr::random_element()));
175 }
176
177 verify_commitment(builder, circuit_inputs);
178
179 // Gate count different for Mega because it adds constants for ECC op codes that get reused in ROM table access
181 check_circuit_and_gate_count(builder, 12156);
182 } else {
183 check_circuit_and_gate_count(builder, 12159);
184 }
185 }
186
187 static void test_zero_values()
188 {
190
191 // Mix of witness and constant zeros/non-zeros
192 std::vector<stdlib::field_t<Builder>> circuit_inputs = {
195 fr_ct(&builder, fr::zero()), // constant zero
196 fr_ct(&builder, fr::random_element()) // constant non-zero
197 };
198
199 verify_commitment(builder, circuit_inputs);
200 }
201
203 {
206
207 for (size_t i = 0; i < 4; ++i) {
208 circuit_inputs.push_back(witness_ct(&builder, fr::random_element()));
209 }
210
212 context.offset = 10;
213
214 verify_commitment(builder, circuit_inputs, context);
215 }
216
217 static void test_all_constants()
218 {
221
222 for (size_t i = 0; i < 6; ++i) {
223 circuit_inputs.push_back(fr_ct(&builder, fr::random_element()));
224 }
225
226 verify_commitment(builder, circuit_inputs);
227 check_circuit_and_gate_count(builder, 0);
228 }
229
231 {
233
235 fr(-1)), // p-1, the maximum field element
236 witness_ct(&builder, fr(-2)), // p-2
238
239 verify_commitment(builder, circuit_inputs);
240 }
241
242 static void test_determinism()
243 {
245 std::vector<fr> inputs;
247
248 for (size_t i = 0; i < 5; ++i) {
249 inputs.push_back(fr::random_element());
250 witness_inputs.push_back(witness_ct(&builder, inputs[i]));
251 }
252
253 // Commit twice with same inputs
254 auto result1 = pedersen_commitment::commit(witness_inputs);
255 auto result2 = pedersen_commitment::commit(witness_inputs);
256
257 // Should produce identical results
258 EXPECT_EQ(result1.x.get_value(), result2.x.get_value());
259 EXPECT_EQ(result1.y.get_value(), result2.y.get_value());
260
261 auto expected = crypto::pedersen_commitment::commit_native(inputs);
262 EXPECT_EQ(result1.x.get_value(), expected.x);
263 EXPECT_EQ(result1.y.get_value(), expected.y);
264
265 bool check_result = CircuitChecker::check(builder);
266 EXPECT_EQ(check_result, true);
267 }
268};
269
270using CircuitTypes = testing::Types<bb::UltraCircuitBuilder, bb::MegaCircuitBuilder>;
271
273
275{
276 TestFixture::test_pedersen();
277};
278
279TYPED_TEST(StdlibPedersen, MixedWitnessesAndConstants)
280{
281 TestFixture::test_mixed_witnesses_and_constants();
282};
283
285{
286 TestFixture::test_empty_input();
287};
288
290{
291 TestFixture::test_single_input();
292};
293
295{
296 TestFixture::test_two_inputs();
297};
298
300{
301 TestFixture::test_three_inputs();
302};
303
305{
306 TestFixture::test_large_input();
307};
308
310{
311 TestFixture::test_zero_values();
312};
313
314TYPED_TEST(StdlibPedersen, CustomGeneratorContext)
315{
316 TestFixture::test_custom_generator_context();
317};
318
320{
321 TestFixture::test_all_constants();
322};
323
324TYPED_TEST(StdlibPedersen, SpecialFieldElement)
325{
326 TestFixture::test_special_field_element();
327};
328
330{
331 TestFixture::test_determinism();
332};
static void test_all_constants()
static void test_custom_generator_context()
typename stdlib::pedersen_commitment< Builder > pedersen_commitment
static void test_two_inputs()
static void test_zero_values()
static void verify_commitment(Builder &builder, const std::vector< stdlib::field_t< Builder > > &inputs, crypto::GeneratorContext< curve::Grumpkin > context={})
static void test_single_input()
typename _curve::witness_ct witness_ct
static void test_empty_input()
static void test_mixed_witnesses_and_constants()
typename _curve::ScalarField fr_ct
typename _curve::public_witness_ct public_witness_ct
static void test_determinism()
static void test_large_input()
static void test_special_field_element()
static void test_three_inputs()
static void test_pedersen()
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
static AffineElement commit_native(const std::vector< Fq > &inputs, GeneratorContext context={})
Given a vector of fields, generate a pedersen commitment using the indexed generators.
Definition pedersen.cpp:24
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:829
uint32_t witness_index
Definition field.hpp:132
In-circuit Pedersen commitment implementation.
Definition pedersen.hpp:19
AluTraceBuilder builder
Definition alu.test.cpp:123
StrictMock< MockContext > context
testing::Types< bb::UltraCircuitBuilder, bb::MegaCircuitBuilder > CircuitTypes
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
Definition engine.cpp:190
void check_circuit_and_gate_count(Builder &builder, uint32_t expected_gates_without_base)
Utility function for gate count checking and circuit verification.
Entry point for Barretenberg command-line interface.
TYPED_TEST_SUITE(ShpleminiTest, TestSettings)
field< Bn254FrParams > fr
Definition fr.hpp:174
TYPED_TEST(ShpleminiTest, CorrectnessOfMultivariateClaimBatching)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field one()
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field from_montgomery_form() const noexcept
static constexpr field zero()
field_t< CircuitBuilder > ScalarField
Definition bn254.hpp:33
public_witness_t< CircuitBuilder > public_witness_ct
Definition bn254.hpp:42
witness_t< CircuitBuilder > witness_ct
Definition bn254.hpp:41