Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
retrieved_bytecodes_tree_check.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cmath>
5#include <cstdint>
6
30
31namespace bb::avm2::constraining {
32namespace {
33
34using ::testing::NiceMock;
35
37using simulation::ClassIdLeafValue;
38using simulation::DeduplicatingEventEmitter;
39using simulation::EventEmitter;
40using simulation::FieldGreaterThan;
41using simulation::FieldGreaterThanEvent;
42using simulation::MerkleCheck;
43using simulation::MerkleCheckEvent;
44using simulation::MockExecutionIdManager;
45using simulation::MockGreaterThan;
46using simulation::MockRangeCheck;
47using simulation::NoopEventEmitter;
48using simulation::Poseidon2;
49using simulation::Poseidon2HashEvent;
50using simulation::Poseidon2PermutationEvent;
51using simulation::Poseidon2PermutationMemoryEvent;
53using simulation::RetrievedBytecodesTreeCheck;
54using simulation::RetrievedBytecodesTreeCheckEvent;
56
57using tracegen::FieldGreaterThanTraceBuilder;
58using tracegen::MerkleCheckTraceBuilder;
59using tracegen::Poseidon2TraceBuilder;
60using tracegen::RetrievedBytecodesTreeCheckTraceBuilder;
61using tracegen::TestTraceContainer;
62
64using C = Column;
65using retrieved_bytecodes_tree = bb::avm2::retrieved_bytecodes_tree_check<FF>;
67
68class RetrievedBytecodesTreeCheckConstrainingTest : public ::testing::Test {
69 protected:
70 RetrievedBytecodesTreeCheckConstrainingTest() = default;
71
72 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
73 // Interactions involve the poseidon2 hash, so the others can be noop
74 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
75 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
76
77 NiceMock<MockGreaterThan> mock_gt;
78 NiceMock<MockExecutionIdManager> mock_execution_id_manager;
79
81 Poseidon2(mock_execution_id_manager, mock_gt, hash_event_emitter, perm_event_emitter, perm_mem_event_emitter);
82};
83
84TEST_F(RetrievedBytecodesTreeCheckConstrainingTest, EmptyRow)
85{
86 check_relation<retrieved_bytecodes_tree>(testing::empty_trace());
87}
88
89struct TestParams {
91 bool exists;
93};
94
95std::vector<TestParams> positive_read_tests = {
96 // Exists = true, leaf pointers to infinity
97 TestParams{ .class_id = 42, .exists = true, .pre_existing_leaves = { { ClassIdLeafValue(42) } } },
98 // Exists = true, leaf points to higher value
99 TestParams{
100 .class_id = 42, .exists = true, .pre_existing_leaves = { { ClassIdLeafValue(42), ClassIdLeafValue(42 + 1) } } },
101 // Exists = false, low leaf points to infinity
102 TestParams{ .class_id = 42, .exists = false, .pre_existing_leaves = { {} } },
103 // Exists = false, low leaf points to higher value
104 TestParams{ .class_id = 42, .exists = false, .pre_existing_leaves = { { ClassIdLeafValue(42 + 1) } } }
105};
106
107class RetrievedBytecodesReadPositiveTests : public RetrievedBytecodesTreeCheckConstrainingTest,
108 public ::testing::WithParamInterface<TestParams> {};
109
110TEST_P(RetrievedBytecodesReadPositiveTests, Positive)
111{
112 const auto& param = GetParam();
113
114 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
115 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
116
117 NiceMock<MockRangeCheck> range_check;
118
119 DeduplicatingEventEmitter<FieldGreaterThanEvent> field_gt_event_emitter;
120 FieldGreaterThan field_gt(range_check, field_gt_event_emitter);
121
122 EventEmitter<RetrievedBytecodesTreeCheckEvent> retrieved_bytecodes_tree_event_emitter;
123
124 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
125
126 Poseidon2TraceBuilder poseidon2_builder;
127 MerkleCheckTraceBuilder merkle_check_builder;
128 FieldGreaterThanTraceBuilder field_gt_builder;
129 RetrievedBytecodesTreeCheckTraceBuilder retrieved_bytecodes_tree_builder;
130
132 initial_state.insert_indexed_leaves(param.pre_existing_leaves);
133
134 RetrievedBytecodesTreeCheck retrieved_bytecodes_tree_simulator(
135 poseidon2, merkle_check, field_gt, initial_state, retrieved_bytecodes_tree_event_emitter);
136
137 retrieved_bytecodes_tree_simulator.contains(param.class_id);
138
139 retrieved_bytecodes_tree_builder.process(retrieved_bytecodes_tree_event_emitter.dump_events(), trace);
140 EXPECT_EQ(trace.get_num_rows(), 1);
141
143 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
145
146 check_relation<retrieved_bytecodes_tree>(trace);
147 check_all_interactions<RetrievedBytecodesTreeCheckTraceBuilder>(trace);
148}
149
150INSTANTIATE_TEST_SUITE_P(RetrievedBytecodesTreeCheckConstrainingTest,
151 RetrievedBytecodesReadPositiveTests,
152 ::testing::ValuesIn(positive_read_tests));
153
154TEST_F(RetrievedBytecodesTreeCheckConstrainingTest, PositiveWriteAppend)
155{
156 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
157 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
158
159 NiceMock<MockRangeCheck> range_check;
160
161 DeduplicatingEventEmitter<FieldGreaterThanEvent> field_gt_event_emitter;
162 FieldGreaterThan field_gt(range_check, field_gt_event_emitter);
163
164 EventEmitter<RetrievedBytecodesTreeCheckEvent> retrieved_bytecodes_tree_event_emitter;
165
166 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
167
168 Poseidon2TraceBuilder poseidon2_builder;
169 MerkleCheckTraceBuilder merkle_check_builder;
170 FieldGreaterThanTraceBuilder field_gt_builder;
171 RetrievedBytecodesTreeCheckTraceBuilder retrieved_bytecodes_tree_builder;
172
173 FF class_id = 100;
174
176
177 RetrievedBytecodesTreeCheck retrieved_bytecodes_tree_simulator(
178 poseidon2, merkle_check, field_gt, initial_state, retrieved_bytecodes_tree_event_emitter);
179
180 retrieved_bytecodes_tree_simulator.insert(class_id);
181
182 retrieved_bytecodes_tree_builder.process(retrieved_bytecodes_tree_event_emitter.dump_events(), trace);
183
184 EXPECT_EQ(trace.get_num_rows(), 1);
185
187 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
189
190 check_relation<retrieved_bytecodes_tree>(trace);
191 check_all_interactions<RetrievedBytecodesTreeCheckTraceBuilder>(trace);
192}
193
194TEST_F(RetrievedBytecodesTreeCheckConstrainingTest, PositiveWriteMembership)
195{
196 FF class_id = 42;
197 auto low_leaf = RetrievedBytecodesTreeLeafPreimage(ClassIdLeafValue(class_id), 0, 0);
198
199 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
200 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
201
202 NiceMock<MockRangeCheck> range_check;
203
204 DeduplicatingEventEmitter<FieldGreaterThanEvent> field_gt_event_emitter;
205 FieldGreaterThan field_gt(range_check, field_gt_event_emitter);
206
207 EventEmitter<RetrievedBytecodesTreeCheckEvent> retrieved_bytecodes_tree_event_emitter;
208
209 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
210
211 Poseidon2TraceBuilder poseidon2_builder;
212 MerkleCheckTraceBuilder merkle_check_builder;
213 FieldGreaterThanTraceBuilder field_gt_builder;
214 RetrievedBytecodesTreeCheckTraceBuilder retrieved_bytecodes_tree_builder;
215
217 initial_state.insert_indexed_leaves({ { ClassIdLeafValue(class_id) } });
218
219 RetrievedBytecodesTreeCheck retrieved_bytecodes_tree_simulator(
220 poseidon2, merkle_check, field_gt, initial_state, retrieved_bytecodes_tree_event_emitter);
221
222 retrieved_bytecodes_tree_simulator.insert(class_id);
223
224 retrieved_bytecodes_tree_builder.process(retrieved_bytecodes_tree_event_emitter.dump_events(), trace);
225
226 EXPECT_EQ(trace.get_num_rows(), 1);
227
229 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
231
232 check_relation<retrieved_bytecodes_tree>(trace);
233 check_all_interactions<RetrievedBytecodesTreeCheckTraceBuilder>(trace);
234}
235
236TEST_F(RetrievedBytecodesTreeCheckConstrainingTest, NegativeExistsFlagCheck)
237{
238 // Test constraint: sel * (CLASS_ID_LOW_LEAF_CLASS_ID_DIFF * (EXISTS * (1 - class_id_low_leaf_class_id_diff_inv)
239 // + class_id_low_leaf_class_id_diff_inv) - 1 + EXISTS) = 0
240 TestTraceContainer trace({
241 { { C::retrieved_bytecodes_tree_check_sel, 1 },
242 { C::retrieved_bytecodes_tree_check_class_id, 27 },
243 { C::retrieved_bytecodes_tree_check_low_leaf_class_id, 27 },
244 { C::retrieved_bytecodes_tree_check_class_id_low_leaf_class_id_diff_inv, 0 },
245 { C::retrieved_bytecodes_tree_check_leaf_not_exists, 0 } },
246 { { C::retrieved_bytecodes_tree_check_sel, 1 },
247 { C::retrieved_bytecodes_tree_check_class_id, 28 },
248 { C::retrieved_bytecodes_tree_check_low_leaf_class_id, 27 },
249 { C::retrieved_bytecodes_tree_check_class_id_low_leaf_class_id_diff_inv, FF(1).invert() },
250 { C::retrieved_bytecodes_tree_check_leaf_not_exists, 1 } },
251 });
252
253 check_relation<retrieved_bytecodes_tree>(trace, retrieved_bytecodes_tree::SR_EXISTS_CHECK);
254 trace.set(C::retrieved_bytecodes_tree_check_leaf_not_exists, 0, 1);
255
257 check_relation<retrieved_bytecodes_tree>(trace, retrieved_bytecodes_tree::SR_EXISTS_CHECK), "EXISTS_CHECK");
258 trace.set(C::retrieved_bytecodes_tree_check_leaf_not_exists, 0, 0);
259 trace.set(C::retrieved_bytecodes_tree_check_leaf_not_exists, 1, 0);
260
262 check_relation<retrieved_bytecodes_tree>(trace, retrieved_bytecodes_tree::SR_EXISTS_CHECK), "EXISTS_CHECK");
263}
264
265TEST_F(RetrievedBytecodesTreeCheckConstrainingTest, NegativeNextSlotIsZero)
266{
267 // Test constraint: leaf_not_exists * (low_leaf_next_class_id * (NEXT_CLASS_ID_IS_ZERO * (1 - next_class_id_inv) +
268 // next_class_id_inv) - 1 + NEXT_CLASS_ID_IS_ZERO) = 0;
269
270 TestTraceContainer trace({
271 {
272 { C::retrieved_bytecodes_tree_check_leaf_not_exists, 1 },
273 { C::retrieved_bytecodes_tree_check_low_leaf_next_class_id, 0 },
274 { C::retrieved_bytecodes_tree_check_next_class_id_inv, 0 },
275 { C::retrieved_bytecodes_tree_check_next_class_id_is_nonzero, 0 },
276 },
277 {
278 { C::retrieved_bytecodes_tree_check_leaf_not_exists, 1 },
279 { C::retrieved_bytecodes_tree_check_low_leaf_next_class_id, 1 },
280 { C::retrieved_bytecodes_tree_check_next_class_id_inv, FF(1).invert() },
281 { C::retrieved_bytecodes_tree_check_next_class_id_is_nonzero, 1 },
282 },
283 });
284
285 check_relation<retrieved_bytecodes_tree>(trace, retrieved_bytecodes_tree::SR_NEXT_CLASS_ID_IS_ZERO_CHECK);
286
287 trace.set(C::retrieved_bytecodes_tree_check_next_class_id_is_nonzero, 0, 1);
288
290 check_relation<retrieved_bytecodes_tree>(trace, retrieved_bytecodes_tree::SR_NEXT_CLASS_ID_IS_ZERO_CHECK),
291 "NEXT_CLASS_ID_IS_ZERO_CHECK");
292
293 trace.set(C::retrieved_bytecodes_tree_check_next_class_id_is_nonzero, 0, 0);
294 trace.set(C::retrieved_bytecodes_tree_check_next_class_id_is_nonzero, 1, 0);
295
297 check_relation<retrieved_bytecodes_tree>(trace, retrieved_bytecodes_tree::SR_NEXT_CLASS_ID_IS_ZERO_CHECK),
298 "NEXT_CLASS_ID_IS_ZERO_CHECK");
299}
300
301} // namespace
302} // 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)
StrictMock< MockGreaterThan > mock_gt
EventEmitter< Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
EventEmitter< Poseidon2PermutationEvent > perm_event_emitter
EventEmitter< Poseidon2HashEvent > hash_event_emitter
Poseidon2TraceBuilder poseidon2_builder
StrictMock< MockExecutionIdManager > mock_execution_id_manager
void process(const simulation::EventEmitterInterface< simulation::FieldGreaterThanEvent >::Container &events, TraceContainer &trace)
void process_hash(const simulation::EventEmitterInterface< simulation::Poseidon2HashEvent >::Container &hash_events, TraceContainer &trace)
void set(Column col, uint32_t row, const FF &value)
Implements a parallelized batch insertion indexed tree Accepts template argument of the type of store...
FieldGreaterThanTraceBuilder field_gt_builder
Definition alu.test.cpp:121
RangeCheck range_check
TestTraceContainer trace
NullifierTreeLeafPreimage low_leaf
std::vector< ClassIdLeafValue > pre_existing_leaves
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
Definition macros.hpp:7
TEST_F(AvmRecursiveTests, GoblinRecursion)
A test of the Goblinized AVM recursive verifier.
IndexedMemoryTree< ClassIdLeafValue, Poseidon2HashPolicy > RetrievedBytecodesTree
IndexedLeaf< ClassIdLeafValue > RetrievedBytecodesTreeLeafPreimage
RetrievedBytecodesTree build_retrieved_bytecodes_tree()
TestTraceContainer empty_trace()
Definition fixtures.cpp:153
AvmFlavorSettings::FF FF
Definition field.hpp:10
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
FieldGreaterThan field_gt
NoopEventEmitter< FieldGreaterThanEvent > field_gt_event_emitter