1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
34using ::testing::NiceMock;
35using ::testing::TestWithParam;
37using testing::TestMemoryTree;
39using simulation::EventEmitter;
40using simulation::ExecutionIdManager;
41using simulation::FieldGreaterThan;
42using simulation::FieldGreaterThanEvent;
43using simulation::MerkleCheck;
44using simulation::MerkleCheckEvent;
45using simulation::MockExecutionIdManager;
46using simulation::MockGreaterThan;
47using simulation::MockRangeCheck;
48using simulation::NoopEventEmitter;
49using simulation::NullifierTreeCheck;
52using simulation::Poseidon2;
53using simulation::Poseidon2HashEvent;
54using simulation::Poseidon2PermutationEvent;
55using simulation::Poseidon2PermutationMemoryEvent;
58using tracegen::NullifierTreeCheckTraceBuilder;
59using tracegen::TestTraceContainer;
66TEST(NullifierTreeCheckConstrainingTest, EmptyRow)
90class NullifierReadPositiveTests :
public TestWithParam<TestParams> {};
92TEST_P(NullifierReadPositiveTests, Positive)
94 const auto& param = GetParam();
100 NiceMock<MockGreaterThan>
mock_gt;
101 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
103 NoopEventEmitter<MerkleCheckEvent> merkle_event_emitter;
104 MerkleCheck merkle_check(
poseidon2, merkle_event_emitter);
111 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
112 NullifierTreeCheck nullifier_tree_check_simulator(
115 TestTraceContainer
trace({ { { C::precomputed_first_row, 1 } } });
116 NullifierTreeCheckTraceBuilder nullifier_tree_check_builder;
119 uint64_t leaf_index = 30;
120 std::vector<FF> sibling_path;
123 sibling_path.emplace_back(i);
127 nullifier_tree_check_simulator.assert_read(
134 AppendOnlyTreeSnapshot{ .root = root, .next_available_leaf_index = 128 });
136 nullifier_tree_check_builder.process(nullifier_tree_check_event_emitter.dump_events(), trace);
139 check_relation<nullifier_check>(trace);
143 NullifierReadPositiveTests,
144 ::testing::ValuesIn(positive_read_tests));
146TEST(NullifierTreeCheckConstrainingTest, PositiveWriteAppend)
152 NiceMock<MockGreaterThan>
mock_gt;
153 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
155 NoopEventEmitter<MerkleCheckEvent> merkle_event_emitter;
156 MerkleCheck merkle_check(
poseidon2, merkle_event_emitter);
163 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
164 NullifierTreeCheck nullifier_tree_check_simulator(
167 TestTraceContainer
trace({ { { C::precomputed_first_row, 1 } } });
168 NullifierTreeCheckTraceBuilder nullifier_tree_check_builder;
171 FF low_nullifier = 40;
177 uint64_t low_leaf_index = 0;
178 nullifier_tree.update_element(low_leaf_index, low_leaf_hash);
180 AppendOnlyTreeSnapshot prev_snapshot =
181 AppendOnlyTreeSnapshot{ .root = nullifier_tree.root(), .next_available_leaf_index = 128 };
182 std::vector<FF> low_leaf_sibling_path = nullifier_tree.get_sibling_path(low_leaf_index);
185 updated_low_leaf.
nextIndex = prev_snapshot.next_available_leaf_index;
188 nullifier_tree.update_element(low_leaf_index, updated_low_leaf_hash);
190 std::vector<FF> insertion_sibling_path = nullifier_tree.get_sibling_path(prev_snapshot.next_available_leaf_index);
195 nullifier_tree.update_element(prev_snapshot.next_available_leaf_index, new_leaf_hash);
197 nullifier_tree_check_simulator.write(
nullifier,
202 low_leaf_sibling_path,
204 insertion_sibling_path);
206 nullifier_tree_check_builder.process(nullifier_tree_check_event_emitter.dump_events(), trace);
210 check_relation<nullifier_check>(trace);
213TEST(NullifierTreeCheckConstrainingTest, PositiveWriteMembership)
221 NiceMock<MockGreaterThan>
mock_gt;
222 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
224 NoopEventEmitter<MerkleCheckEvent> merkle_event_emitter;
225 MerkleCheck merkle_check(
poseidon2, merkle_event_emitter);
232 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
233 NullifierTreeCheck nullifier_tree_check_simulator(
236 TestTraceContainer
trace({ { { C::precomputed_first_row, 1 } } });
237 NullifierTreeCheckTraceBuilder nullifier_tree_check_builder;
240 uint64_t leaf_index = 30;
241 std::vector<FF> sibling_path;
244 sibling_path.emplace_back(i);
248 nullifier_tree_check_simulator.write(
nullifier,
254 AppendOnlyTreeSnapshot{ .root = root, .next_available_leaf_index = 128 },
257 nullifier_tree_check_builder.process(nullifier_tree_check_event_emitter.dump_events(), trace);
260 check_relation<nullifier_check>(trace);
263TEST(NullifierTreeCheckConstrainingTest, Siloing)
273 NiceMock<MockGreaterThan>
mock_gt;
274 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
276 NoopEventEmitter<MerkleCheckEvent> merkle_event_emitter;
277 MerkleCheck merkle_check(
poseidon2, merkle_event_emitter);
284 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
285 NullifierTreeCheck nullifier_tree_check_simulator(
288 TestTraceContainer
trace({ { { C::precomputed_first_row, 1 } } });
289 NullifierTreeCheckTraceBuilder nullifier_tree_check_builder;
292 uint64_t leaf_index = 30;
293 std::vector<FF> sibling_path;
296 sibling_path.emplace_back(i);
300 nullifier_tree_check_simulator.write(
nullifier,
306 AppendOnlyTreeSnapshot{ .root = root, .next_available_leaf_index = 128 },
309 nullifier_tree_check_builder.process(nullifier_tree_check_event_emitter.dump_events(), trace);
312 check_relation<nullifier_check>(trace);
315TEST(NullifierTreeCheckConstrainingTest, NegativeExistsFlagCheck)
319 TestTraceContainer
trace({
320 { { C::nullifier_check_sel, 1 },
321 { C::nullifier_check_siloed_nullifier, 27 },
322 { C::nullifier_check_low_leaf_nullifier, 27 },
323 { C::nullifier_check_nullifier_low_leaf_nullifier_diff_inv, 0 },
324 { C::nullifier_check_exists, 1 } },
325 { { C::nullifier_check_sel, 1 },
326 { C::nullifier_check_siloed_nullifier, 28 },
327 { C::nullifier_check_low_leaf_nullifier, 27 },
328 { C::nullifier_check_nullifier_low_leaf_nullifier_diff_inv,
FF(1).invert() },
329 { C::nullifier_check_exists, 0 } },
333 trace.
set(C::nullifier_check_exists, 0, 0);
336 trace.
set(C::nullifier_check_exists, 0, 1);
337 trace.
set(C::nullifier_check_exists, 1, 1);
342TEST(NullifierTreeCheckConstrainingTest, NegativeNextSlotIsZero)
346 TestTraceContainer
trace({
348 { C::nullifier_check_leaf_not_exists, 1 },
349 { C::nullifier_check_low_leaf_next_nullifier, 0 },
350 { C::nullifier_check_next_nullifier_inv, 0 },
351 { C::nullifier_check_next_nullifier_is_nonzero, 0 },
354 { C::nullifier_check_leaf_not_exists, 1 },
355 { C::nullifier_check_low_leaf_next_nullifier, 1 },
356 { C::nullifier_check_next_nullifier_inv,
FF(1).invert() },
357 { C::nullifier_check_next_nullifier_is_nonzero, 1 },
363 trace.
set(C::nullifier_check_next_nullifier_is_nonzero, 0, 1);
366 "NEXT_NULLIFIER_IS_ZERO_CHECK");
368 trace.
set(C::nullifier_check_next_nullifier_is_nonzero, 0, 0);
369 trace.
set(C::nullifier_check_next_nullifier_is_nonzero, 1, 0);
372 "NEXT_NULLIFIER_IS_ZERO_CHECK");
375TEST(NullifierTreeCheckConstrainingTest, NegativePassthrougSiloing)
378 TestTraceContainer
trace({
380 { C::nullifier_check_sel, 1 },
381 { C::nullifier_check_should_silo, 1 },
382 { C::nullifier_check_nullifier, 27 },
383 { C::nullifier_check_siloed_nullifier, 42 },
386 { C::nullifier_check_sel, 1 },
387 { C::nullifier_check_should_silo, 0 },
388 { C::nullifier_check_nullifier, 27 },
389 { C::nullifier_check_siloed_nullifier, 27 },
395 trace.
set(C::nullifier_check_siloed_nullifier, 1, 28);
398 "PASSTHROUGH_SILOING");
FieldGreaterThan field_gt
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
#define NULLIFIER_TREE_HEIGHT
StrictMock< MockGreaterThan > mock_gt
EventEmitter< Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
EventEmitter< Poseidon2PermutationEvent > perm_event_emitter
EventEmitter< Poseidon2HashEvent > hash_event_emitter
static constexpr size_t SR_NEXT_NULLIFIER_IS_ZERO_CHECK
static constexpr size_t SR_PASSTHROUGH_SILOING
static constexpr size_t SR_EXISTS_CHECK
uint32_t get_num_rows() const
void set(Column col, uint32_t row, const FF &value)
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
NullifierTreeLeafPreimage low_leaf
AztecAddress contract_address
INSTANTIATE_TEST_SUITE_P(PaddingVariants, AvmRecursiveTestsParameterized, ::testing::Values(false, true), [](const auto &info) { return info.param ? "Padded" :"Unpadded";})
TEST_P(AvmRecursiveTestsParameterized, GoblinRecursion)
A test of the Goblinized AVM recursive verifier.
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
crypto::merkle_tree::IndexedLeaf< crypto::merkle_tree::NullifierLeafValue > NullifierTreeLeafPreimage
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
::bb::crypto::merkle_tree::NullifierLeafValue NullifierLeafValue
FF unconstrained_root_from_path(const FF &leaf_value, const uint64_t leaf_index, std::span< const FF > path)
std::variant< NullifierTreeReadWriteEvent, CheckPointEventType > NullifierTreeCheckEvent
FF unconstrained_silo_nullifier(const AztecAddress &contract_address, const FF &nullifier)
TestTraceContainer empty_trace()
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
NoopEventEmitter< FieldGreaterThanEvent > field_gt_event_emitter
std::vector< fr > get_hash_inputs() const