Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
field_gt.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
20
21namespace bb::avm2::constraining {
22namespace {
23
24using ::testing::NiceMock;
25using ::testing::TestWithParam;
26
27using tracegen::FieldGreaterThanTraceBuilder;
28using tracegen::RangeCheckTraceBuilder;
29using tracegen::TestTraceContainer;
30
31using simulation::DeduplicatingEventEmitter;
32using simulation::EventEmitter;
33using simulation::FieldGreaterThan;
34using simulation::FieldGreaterThanEvent;
35using simulation::MockRangeCheck;
36using simulation::RangeCheck;
37using simulation::RangeCheckEvent;
38using simulation::U256Decomposition;
39
41using C = Column;
42using ff_gt = bb::avm2::ff_gt<FF>;
43
44const uint256_t TWO_POW_128 = uint256_t{ 1 } << 128;
45
46TEST(FieldGreaterThanConstrainingTest, EmptyRow)
47{
48 check_relation<ff_gt>(testing::empty_trace());
49}
50
51struct GtTestParams {
55};
56struct DecTestParams {
57 FF a;
58 U256Decomposition expected_result;
59};
60
61std::vector<GtTestParams> comparison_tests = {
62 // GT
63 GtTestParams{ 27, 0, true },
64 GtTestParams{ TWO_POW_128, 0, true },
65 GtTestParams{ -1, 0, true },
66 // EQ
67 GtTestParams{ 27, 27, false },
68 GtTestParams{ TWO_POW_128, TWO_POW_128, false },
69 GtTestParams{ -1, -1, false },
70 // LT
71 GtTestParams{ 0, 1, false },
72 GtTestParams{ 0, TWO_POW_128, false },
73 GtTestParams{ 0, -1, false }
74};
75
76std::vector<DecTestParams> decomposition_tests = {
77 DecTestParams{ 0, { .lo = 0, .hi = 0 } },
78 DecTestParams{ 1, { .lo = 1, .hi = 0 } },
79 DecTestParams{ uint256_t(1) << 128, { .lo = 0, .hi = 1 } },
80 DecTestParams{ (uint256_t(1) << 200) - 1,
81 { .lo = static_cast<uint128_t>((uint256_t(1) << 128) - 1), .hi = (uint128_t(1) << 72) - 1 } },
82};
83
84class GtBasicTest : public TestWithParam<GtTestParams> {};
85
86TEST_P(GtBasicTest, BasicComparison)
87{
88 const auto& param = GetParam();
89
90 NiceMock<MockRangeCheck> range_check;
91 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
92 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
93
94 EXPECT_EQ(field_gt_simulator.ff_gt(param.a, param.b), param.expected_result);
95
96 TestTraceContainer trace({
97 { { C::precomputed_first_row, 1 } },
98 });
99
100 FieldGreaterThanTraceBuilder builder;
101 builder.process(event_emitter.dump_events(), trace);
102 EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 5);
103 check_relation<ff_gt>(trace);
104}
105
106INSTANTIATE_TEST_SUITE_P(FieldGreaterThanConstrainingTest, GtBasicTest, ::testing::ValuesIn(comparison_tests));
107
108class DecBasicTest : public TestWithParam<DecTestParams> {};
109
110TEST_P(DecBasicTest, BasicDecomposition)
111{
112 const auto& param = GetParam();
113
114 NiceMock<MockRangeCheck> range_check;
115 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
116 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
117
118 EXPECT_EQ(field_gt_simulator.canon_dec(param.a), param.expected_result);
119
120 TestTraceContainer trace({
121 { { C::precomputed_first_row, 1 } },
122 });
123
124 FieldGreaterThanTraceBuilder builder;
125 builder.process(event_emitter.dump_events(), trace);
126 EXPECT_EQ(trace.get_num_rows(), /*start_row=*/1 + 2);
127 check_relation<ff_gt>(trace);
128}
129
130INSTANTIATE_TEST_SUITE_P(FieldGreaterThanConstrainingTest, DecBasicTest, ::testing::ValuesIn(decomposition_tests));
131
132class GtInteractionTests : public TestWithParam<GtTestParams> {};
133
134TEST_P(GtInteractionTests, InteractionsWithRangeCheck)
135{
136 const auto& param = GetParam();
137
138 EventEmitter<RangeCheckEvent> range_check_event_emitter;
140 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
141 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
142
143 EXPECT_EQ(field_gt_simulator.ff_gt(param.a, param.b), param.expected_result);
144
145 TestTraceContainer trace({
146 { { C::precomputed_first_row, 1 } },
147 });
148
149 FieldGreaterThanTraceBuilder builder;
150 RangeCheckTraceBuilder range_check_builder;
151
152 builder.process(event_emitter.dump_events(), trace);
154
155 check_interaction<FieldGreaterThanTraceBuilder, //
158
159 check_relation<ff_gt>(trace);
160}
161
162INSTANTIATE_TEST_SUITE_P(FieldGreaterThanConstrainingTest, GtInteractionTests, ::testing::ValuesIn(comparison_tests));
163
164class DecInteractionTests : public TestWithParam<DecTestParams> {};
165
166TEST_P(DecInteractionTests, InteractionsWithRangeCheck)
167{
168 const auto& param = GetParam();
169
170 EventEmitter<RangeCheckEvent> range_check_event_emitter;
172 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
173 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
174
175 EXPECT_EQ(field_gt_simulator.canon_dec(param.a), param.expected_result);
176
177 TestTraceContainer trace({
178 { { C::precomputed_first_row, 1 } },
179 });
180
181 FieldGreaterThanTraceBuilder builder;
182 RangeCheckTraceBuilder range_check_builder;
183
184 builder.process(event_emitter.dump_events(), trace);
186
187 check_interaction<FieldGreaterThanTraceBuilder, //
190
191 check_relation<ff_gt>(trace);
192}
193
194INSTANTIATE_TEST_SUITE_P(FieldGreaterThanConstrainingTest,
195 DecInteractionTests,
196 ::testing::ValuesIn(decomposition_tests));
197
198TEST(FieldGreaterThanConstrainingTest, NegativeManipulatedDecompositions)
199{
200 NiceMock<MockRangeCheck> range_check;
201 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
202 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
203
204 field_gt_simulator.ff_gt(0, 0);
205
206 TestTraceContainer trace({
207 { { C::precomputed_first_row, 1 } },
208 });
209
210 FieldGreaterThanTraceBuilder builder;
211 builder.process(event_emitter.dump_events(), trace);
212 check_relation<ff_gt>(trace);
213
214 trace.set(Column::ff_gt_a_lo, 1, 1);
215 trace.set(Column::ff_gt_b_hi, 1, 1);
216
217 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_A_DECOMPOSITION), "A_DECOMPOSITION");
218 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_B_DECOMPOSITION), "B_DECOMPOSITION");
219}
220
221TEST(FieldGreaterThanConstrainingTest, NegativeManipulatedComparisonsWithP)
222{
223 NiceMock<MockRangeCheck> range_check;
224 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
225 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
226
227 field_gt_simulator.ff_gt(0, 0);
228
229 TestTraceContainer trace({
230 { { C::precomputed_first_row, 1 } },
231 });
232
233 FieldGreaterThanTraceBuilder builder;
234 builder.process(event_emitter.dump_events(), trace);
235 check_relation<ff_gt>(trace);
236
237 auto p_limbs = simulation::decompose(FF::modulus);
238 uint256_t p_lo = uint256_t::from_uint128(p_limbs.lo);
239 uint256_t p_hi = uint256_t::from_uint128(p_limbs.hi);
240
241 // Manipulate the decomposition in a way that passes the decomposition check due to overflow
242 trace.set(Column::ff_gt_a_lo, 1, p_lo);
243 trace.set(Column::ff_gt_a_hi, 1, p_hi);
244 trace.set(Column::ff_gt_b_lo, 1, p_lo);
245 trace.set(Column::ff_gt_b_hi, 1, p_hi);
246
247 trace.set(Column::ff_gt_p_sub_a_hi, 1, p_lo - 1);
248 trace.set(Column::ff_gt_p_sub_a_lo, 1, p_hi - 1);
249 trace.set(Column::ff_gt_p_sub_b_hi, 1, p_lo - 1);
250 trace.set(Column::ff_gt_p_sub_b_lo, 1, p_hi - 1);
251
252 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_P_SUB_A_LO), "P_SUB_A_LO");
253 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_P_SUB_A_HI), "P_SUB_A_HI");
254 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_P_SUB_B_LO), "P_SUB_B_LO");
255 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_P_SUB_B_HI), "P_SUB_B_HI");
256}
257
258TEST(FieldGreaterThanConstrainingTest, NegativeLessRangeChecks)
259{
260 NiceMock<MockRangeCheck> range_check;
261 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
262 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
263
264 field_gt_simulator.ff_gt(0, 0);
265
266 TestTraceContainer trace({
267 { { C::precomputed_first_row, 1 } },
268 });
269
270 FieldGreaterThanTraceBuilder builder;
271 builder.process(event_emitter.dump_events(), trace);
272 check_relation<ff_gt>(trace);
273
274 trace.set(Column::ff_gt_cmp_rng_ctr, 1, 3);
275 trace.set(Column::ff_gt_cmp_rng_ctr, 2, 0);
276
277 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_RNG_CTR_GT_INIT), "RNG_CTR_GT_INIT");
278 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_RNG_CTR_DECREMENT), "RNG_CTR_DECREMENT");
279}
280
281TEST(FieldGreaterThanConstrainingTest, NegativeRangeCheckCtrInitInDec)
282{
283 NiceMock<MockRangeCheck> range_check;
284 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
285 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
286
287 field_gt_simulator.canon_dec(0);
288
289 TestTraceContainer trace({
290 { { C::precomputed_first_row, 1 } },
291 });
292
293 FieldGreaterThanTraceBuilder builder;
294 builder.process(event_emitter.dump_events(), trace);
295 check_relation<ff_gt>(trace);
296
297 trace.set(Column::ff_gt_cmp_rng_ctr, 1, 4);
298 trace.set(Column::ff_gt_cmp_rng_ctr, 2, 2);
299
300 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_RNG_CTR_DEC_INIT), "RNG_CTR_DEC_INIT");
301 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_RNG_CTR_DECREMENT), "RNG_CTR_DECREMENT");
302}
303
304TEST(FieldGreaterThanConstrainingTest, NegativeSelectorConsistency)
305{
306 NiceMock<MockRangeCheck> range_check;
307 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
308 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
309
310 field_gt_simulator.ff_gt(0, 0);
311
312 TestTraceContainer trace({
313 { { C::precomputed_first_row, 1 } },
314 });
315
316 FieldGreaterThanTraceBuilder builder;
317 builder.process(event_emitter.dump_events(), trace);
318 check_relation<ff_gt>(trace);
319
320 // Disable the selector after the first row
321 trace.set(Column::ff_gt_sel, 2, 0);
322
323 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_SEL_CONSISTENCY), "SEL_CONSISTENCY");
324}
325
326TEST(FieldGreaterThanConstrainingTest, NegativeEraseShift)
327{
328 NiceMock<MockRangeCheck> range_check;
329 DeduplicatingEventEmitter<FieldGreaterThanEvent> event_emitter;
330 FieldGreaterThan field_gt_simulator(range_check, event_emitter);
331
332 field_gt_simulator.ff_gt(42, 27);
333
334 TestTraceContainer trace({
335 { { C::precomputed_first_row, 1 } },
336 });
337
338 FieldGreaterThanTraceBuilder builder;
339 builder.process(event_emitter.dump_events(), trace);
340 check_relation<ff_gt>(trace);
341
342 trace.set(Column::ff_gt_a_lo, 2, 0);
343 trace.set(Column::ff_gt_a_hi, 2, 0);
344 trace.set(Column::ff_gt_p_sub_a_lo, 2, 0);
345 trace.set(Column::ff_gt_p_sub_a_hi, 2, 0);
346 trace.set(Column::ff_gt_b_lo, 2, 0);
347 trace.set(Column::ff_gt_b_hi, 2, 0);
348 trace.set(Column::ff_gt_p_sub_b_lo, 2, 0);
349 trace.set(Column::ff_gt_p_sub_b_hi, 2, 0);
350
351 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_SHIFT_0), "SHIFT_0");
352 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_SHIFT_1), "SHIFT_1");
353 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_SHIFT_2), "SHIFT_2");
354 EXPECT_THROW_WITH_MESSAGE(check_relation<ff_gt>(trace, ff_gt::SR_SHIFT_3), "SHIFT_3");
355}
356
357} // namespace
358} // namespace bb::avm2::constraining
INSTANTIATE_TEST_SUITE_P(AcirTests, AcirIntegrationSingleTest, testing::Values("a_1327_concrete_in_generic", "a_1_mul", "a_2_div", "a_3_add", "a_4_sub", "a_5_over", "a_6", "a_6_array", "a_7", "a_7_function", "aes128_encrypt", "arithmetic_binary_operations", "array_dynamic", "array_dynamic_blackbox_input", "array_dynamic_main_output", "array_dynamic_nested_blackbox_input", "array_eq", "array_if_cond_simple", "array_len", "array_neq", "array_sort", "array_to_slice", "array_to_slice_constant_length", "assert", "assert_statement", "assign_ex", "bigint", "bit_and", "bit_not", "bit_shifts_comptime", "bit_shifts_runtime", "blake3", "bool_not", "bool_or", "break_and_continue", "brillig_acir_as_brillig", "brillig_array_eq", "brillig_array_to_slice", "brillig_arrays", "brillig_assert", "brillig_bit_shifts_runtime", "brillig_blake2s", "brillig_blake3", "brillig_calls", "brillig_calls_array", "brillig_calls_conditionals", "brillig_conditional", "brillig_cow", "brillig_cow_assign", "brillig_cow_regression", "brillig_ecdsa_secp256k1", "brillig_ecdsa_secp256r1", "brillig_embedded_curve", "brillig_fns_as_values", "brillig_hash_to_field", "brillig_identity_function", "brillig_keccak", "brillig_loop", "brillig_nested_arrays", "brillig_not", "brillig_oracle", "brillig_pedersen", "brillig_recursion", "brillig_references", "brillig_schnorr", "brillig_sha256", "brillig_signed_cmp", "brillig_signed_div", "brillig_slices", "brillig_to_be_bytes", "brillig_to_bits", "brillig_to_bytes_integration", "brillig_to_le_bytes", "brillig_top_level", "brillig_uninitialized_arrays", "brillig_wrapping", "cast_bool", "closures_mut_ref", "conditional_1", "conditional_2", "conditional_regression_421", "conditional_regression_547", "conditional_regression_661", "conditional_regression_short_circuit", "conditional_regression_underflow", "custom_entry", "databus", "debug_logs", "diamond_deps_0", "double_verify_nested_proof", "double_verify_proof", "ecdsa_secp256k1", "ecdsa_secp256r1", "ecdsa_secp256r1_3x", "eddsa", "embedded_curve_ops", "field_attribute", "generics", "global_consts", "hash_to_field", "hashmap", "higher_order_functions", "if_else_chain", "import", "inline_never_basic", "integer_array_indexing", "keccak256", "main_bool_arg", "main_return", "merkle_insert", "missing_closure_env", "modules", "modules_more", "modulus", "nested_array_dynamic", "nested_array_dynamic_simple", "nested_array_in_slice", "nested_arrays_from_brillig", "no_predicates_basic", "no_predicates_brillig", "no_predicates_numeric_generic_poseidon", "operator_overloading", "pedersen_check", "pedersen_commitment", "pedersen_hash", "poseidon_bn254_hash", "poseidonsponge_x5_254", "pred_eq", "prelude", "references", "regression", "regression_2660", "regression_3051", "regression_3394", "regression_3607", "regression_3889", "regression_4088", "regression_4124", "regression_4202", "regression_4449", "regression_4709", "regression_5045", "regression_capacity_tracker", "regression_mem_op_predicate", "regression_method_cannot_be_found", "regression_struct_array_conditional", "schnorr", "sha256", "sha2_byte", "side_effects_constrain_array", "signed_arithmetic", "signed_comparison", "signed_division", "simple_2d_array", "simple_add_and_ret_arr", "simple_array_param", "simple_bitwise", "simple_comparison", "simple_mut", "simple_not", "simple_print", "simple_program_addition", "simple_radix", "simple_shield", "simple_shift_left_right", "slice_coercion", "slice_dynamic_index", "slice_loop", "slices", "strings", "struct", "struct_array_inputs", "struct_fields_ordering", "struct_inputs", "submodules", "to_be_bytes", "to_bytes_consistent", "to_bytes_integration", "to_le_bytes", "trait_as_return_type", "trait_impl_base_type", "traits_in_crates_1", "traits_in_crates_2", "tuple_inputs", "tuples", "type_aliases", "u128", "u16_support", "unconstrained_empty", "unit_value", "unsafe_range_constraint", "witness_compression", "xor"))
TEST_P(AcirIntegrationSingleTest, DISABLED_ProveAndVerifyProgram)
static constexpr size_t SR_P_SUB_B_LO
Definition ff_gt.hpp:43
static constexpr size_t SR_RNG_CTR_GT_INIT
Definition ff_gt.hpp:47
static constexpr size_t SR_SEL_CONSISTENCY
Definition ff_gt.hpp:55
static constexpr size_t SR_RNG_CTR_DECREMENT
Definition ff_gt.hpp:49
static constexpr size_t SR_P_SUB_A_LO
Definition ff_gt.hpp:40
static constexpr size_t SR_SHIFT_2
Definition ff_gt.hpp:53
static constexpr size_t SR_B_DECOMPOSITION
Definition ff_gt.hpp:42
static constexpr size_t SR_P_SUB_B_HI
Definition ff_gt.hpp:44
static constexpr size_t SR_SHIFT_1
Definition ff_gt.hpp:52
static constexpr size_t SR_SHIFT_3
Definition ff_gt.hpp:54
static constexpr size_t SR_SHIFT_0
Definition ff_gt.hpp:51
static constexpr size_t SR_P_SUB_A_HI
Definition ff_gt.hpp:41
static constexpr size_t SR_A_DECOMPOSITION
Definition ff_gt.hpp:39
static constexpr size_t SR_RNG_CTR_DEC_INIT
Definition ff_gt.hpp:48
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::RangeCheckEvent >::Container &events, TraceContainer &trace)
void set(Column col, uint32_t row, const FF &value)
static constexpr uint256_t from_uint128(const uint128_t a) noexcept
Definition uint256.hpp:94
RangeCheckTraceBuilder range_check_builder
Definition alu.test.cpp:120
AluTraceBuilder builder
Definition alu.test.cpp:123
EventEmitter< RangeCheckEvent > range_check_event_emitter
EventEmitter< DataCopyEvent > event_emitter
RangeCheck range_check
TestTraceContainer trace
FF a
FF b
bool expected_result
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(TxExecutionConstrainingTest, WriteTreeValue)
Definition tx.test.cpp:402
U256Decomposition decompose(const uint256_t &x)
const uint256_t TWO_POW_128
TestTraceContainer empty_trace()
Definition fixtures.cpp:153
lookup_settings< lookup_ff_gt_a_lo_range_settings_ > lookup_ff_gt_a_lo_range_settings
lookup_settings< lookup_ff_gt_a_hi_range_settings_ > lookup_ff_gt_a_hi_range_settings
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
unsigned __int128 uint128_t
Definition serialize.hpp:44