1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
25using tracegen::ExecutionTraceBuilder;
26using tracegen::NullifierTreeCheckTraceBuilder;
27using tracegen::TestTraceContainer;
29using simulation::EventEmitter;
30using simulation::MockFieldGreaterThan;
31using simulation::MockMerkleCheck;
32using simulation::MockPoseidon2;
33using simulation::MockRangeCheck;
34using simulation::NullifierTreeCheck;
40using testing::StrictMock;
47TEST(EmitNullifierConstrainingTest, Positive)
50 TestTraceContainer
trace({ {
51 { C::execution_sel_execute_emit_nullifier, 1 },
52 { C::execution_register_0_, 42 },
53 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
55 { C::execution_sel_write_nullifier, 1 },
56 { C::execution_sel_opcode_error, 0 },
58 { C::execution_prev_nullifier_tree_size, 1 },
59 { C::execution_nullifier_tree_size, 2 },
60 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
61 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted + 1 },
63 check_relation<emit_nullifier>(
trace);
66TEST(EmitNullifierConstrainingTest, LimitReached)
69 TestTraceContainer
trace({ {
70 { C::execution_sel_execute_emit_nullifier, 1 },
71 { C::execution_register_0_, 42 },
72 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
73 { C::execution_sel_reached_max_nullifiers, 1 },
74 { C::execution_remaining_nullifiers_inv, 0 },
75 { C::execution_sel_write_nullifier, 0 },
76 { C::execution_sel_opcode_error, 1 },
78 { C::execution_prev_nullifier_tree_size, 1 },
79 { C::execution_nullifier_tree_size, 1 },
80 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
81 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted },
83 check_relation<emit_nullifier>(
trace);
86 trace.
set(C::execution_sel_reached_max_nullifiers, 0, 0);
88 "MAX_NULLIFIER_WRITES_REACHED");
89 trace.
set(C::execution_sel_reached_max_nullifiers, 0, 1);
92 trace.
set(C::execution_sel_opcode_error, 0, 0);
95 "OPCODE_ERROR_IF_VALIDATION_ERROR");
96 trace.
set(C::execution_sel_opcode_error, 0, 1);
99 trace.
set(C::execution_nullifier_tree_root, 0, 28);
102 "EMIT_NULLIFIER_TREE_ROOT_NOT_CHANGED");
105 trace.
set(C::execution_nullifier_tree_size, 0, 2);
108 "EMIT_NULLIFIER_TREE_SIZE_INCREASE");
111 trace.
set(C::execution_num_nullifiers_emitted, 0, prev_num_nullifiers_emitted + 1);
114 "EMIT_NULLIFIER_NUM_NULLIFIERS_EMITTED_INCREASE");
117TEST(EmitNullifierConstrainingTest, Interactions)
120 StrictMock<MockMerkleCheck> merkle_check;
122 StrictMock<MockFieldGreaterThan>
field_gt;
124 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
125 NullifierTreeCheck nullifier_tree_check(
poseidon2, merkle_check,
field_gt, nullifier_tree_check_event_emitter);
129 FF siloed_nullifier = 66;
130 FF low_leaf_nullifier = 99;
131 FF low_leaf_hash = 77;
132 FF updated_low_leaf_hash = 101;
133 FF new_leaf_hash = 111;
134 FF pre_write_root = 27;
135 FF intermediate_root = 33;
136 FF post_write_root = 88;
139 std::vector<FF> insertion_sibling_path = { 1, 2, 3 };
141 AppendOnlyTreeSnapshot prev_snapshot = AppendOnlyTreeSnapshot{
142 .root = pre_write_root,
143 .nextAvailableLeafIndex = 128,
145 uint32_t prev_num_nullifiers_emitted = 2;
148 EXPECT_CALL(
field_gt, ff_gt).WillOnce(Return(
true));
151 .WillOnce(Return(siloed_nullifier))
152 .WillOnce(Return(low_leaf_hash))
153 .WillOnce(Return(updated_low_leaf_hash))
154 .WillOnce(Return(new_leaf_hash));
156 EXPECT_CALL(merkle_check,
write).WillOnce(Return(intermediate_root)).WillOnce(Return(post_write_root));
161 AppendOnlyTreeSnapshot next_snapshot = nullifier_tree_check.write(
nullifier,
163 prev_num_nullifiers_emitted,
168 insertion_sibling_path);
170 TestTraceContainer
trace({ {
171 { C::execution_sel_execute_emit_nullifier, 1 },
173 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
175 { C::execution_sel_write_nullifier, 1 },
176 { C::execution_sel_opcode_error, 0 },
178 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
179 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted + 1 },
180 { C::execution_prev_nullifier_tree_root, prev_snapshot.root },
181 { C::execution_nullifier_tree_root, next_snapshot.root },
182 { C::execution_prev_nullifier_tree_size, prev_snapshot.nextAvailableLeafIndex },
183 { C::execution_nullifier_tree_size, next_snapshot.nextAvailableLeafIndex },
187 NullifierTreeCheckTraceBuilder nullifier_tree_check_trace_builder;
188 nullifier_tree_check_trace_builder.process(nullifier_tree_check_event_emitter.dump_events(),
trace);
189 check_relation<emit_nullifier>(
trace);
191 check_interaction<ExecutionTraceBuilder, lookup_emit_nullifier_write_nullifier_settings>(
trace);
194TEST(EmitNullifierConstrainingTest, InteractionsCollision)
197 StrictMock<MockMerkleCheck> merkle_check;
199 StrictMock<MockFieldGreaterThan>
field_gt;
201 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
202 NullifierTreeCheck nullifier_tree_check(
poseidon2, merkle_check,
field_gt, nullifier_tree_check_event_emitter);
206 FF siloed_nullifier = 66;
207 FF low_leaf_hash = 77;
208 FF pre_write_root = 27;
210 AppendOnlyTreeSnapshot prev_snapshot = AppendOnlyTreeSnapshot{
211 .root = pre_write_root,
212 .nextAvailableLeafIndex = 128,
214 uint32_t prev_num_nullifiers_emitted = 2;
217 EXPECT_CALL(
poseidon2,
hash).WillOnce(Return(siloed_nullifier)).WillOnce(Return(low_leaf_hash));
219 EXPECT_CALL(merkle_check, assert_membership).WillOnce(Return());
224 AppendOnlyTreeSnapshot next_snapshot = nullifier_tree_check.write(
nullifier,
226 prev_num_nullifiers_emitted,
233 TestTraceContainer
trace({ {
234 { C::execution_sel_execute_emit_nullifier, 1 },
236 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
238 { C::execution_sel_write_nullifier, 1 },
239 { C::execution_sel_opcode_error, 1 },
241 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
242 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted },
243 { C::execution_prev_nullifier_tree_root, prev_snapshot.root },
244 { C::execution_nullifier_tree_root, next_snapshot.root },
245 { C::execution_prev_nullifier_tree_size, prev_snapshot.nextAvailableLeafIndex },
246 { C::execution_nullifier_tree_size, next_snapshot.nextAvailableLeafIndex },
250 NullifierTreeCheckTraceBuilder nullifier_tree_check_trace_builder;
251 nullifier_tree_check_trace_builder.process(nullifier_tree_check_event_emitter.dump_events(),
trace);
252 check_relation<emit_nullifier>(
trace);
254 check_interaction<ExecutionTraceBuilder, lookup_emit_nullifier_write_nullifier_settings>(
trace);
#define AVM_EXEC_OP_ID_EMIT_NULLIFIER
#define MAX_NULLIFIERS_PER_TX
static constexpr size_t SR_OPCODE_ERROR_IF_VALIDATION_ERROR
static constexpr size_t SR_EMIT_NULLIFIER_TREE_ROOT_NOT_CHANGED
static constexpr size_t SR_EMIT_NULLIFIER_NUM_NULLIFIERS_EMITTED_INCREASE
static constexpr size_t SR_MAX_NULLIFIER_WRITES_REACHED
static constexpr size_t SR_EMIT_NULLIFIER_TREE_SIZE_INCREASE
void set(Column col, uint32_t row, const FF &value)
AztecAddress contract_address
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessage)
void hash(State &state) noexcept
TEST(TxExecutionConstrainingTest, WriteTreeValue)
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
::bb::crypto::merkle_tree::NullifierLeafValue NullifierLeafValue
IndexedLeaf< NullifierLeafValue > NullifierTreeLeafPreimage
std::variant< NullifierTreeReadWriteEvent, CheckPointEventType > NullifierTreeCheckEvent
void write(B &buf, field2< base_field, Params > const &value)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
NiceMock< MockFieldGreaterThan > field_gt