1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
26using tracegen::ExecutionTraceBuilder;
27using tracegen::NullifierTreeCheckTraceBuilder;
28using tracegen::TestTraceContainer;
30using simulation::EventEmitter;
31using simulation::MockFieldGreaterThan;
32using simulation::MockMerkleCheck;
33using simulation::MockPoseidon2;
34using simulation::MockRangeCheck;
35using simulation::NullifierTreeCheck;
41using testing::StrictMock;
48TEST(EmitNullifierConstrainingTest, Positive)
51 TestTraceContainer
trace({ {
52 { C::execution_sel_execute_emit_nullifier, 1 },
53 { C::execution_register_0_, 42 },
54 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
56 { C::execution_sel_write_nullifier, 1 },
57 { C::execution_sel_opcode_error, 0 },
59 { C::execution_prev_nullifier_tree_size, 1 },
60 { C::execution_nullifier_tree_size, 2 },
61 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
62 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted + 1 },
64 check_relation<emit_nullifier>(
trace);
67TEST(EmitNullifierConstrainingTest, LimitReached)
70 TestTraceContainer
trace({ {
71 { C::execution_sel_execute_emit_nullifier, 1 },
72 { C::execution_register_0_, 42 },
73 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
74 { C::execution_sel_reached_max_nullifiers, 1 },
75 { C::execution_remaining_nullifiers_inv, 0 },
76 { C::execution_sel_write_nullifier, 0 },
77 { C::execution_sel_opcode_error, 1 },
79 { C::execution_prev_nullifier_tree_size, 1 },
80 { C::execution_nullifier_tree_size, 1 },
81 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
82 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted },
84 check_relation<emit_nullifier>(
trace);
87 trace.
set(C::execution_sel_reached_max_nullifiers, 0, 0);
89 "MAX_NULLIFIER_WRITES_REACHED");
90 trace.
set(C::execution_sel_reached_max_nullifiers, 0, 1);
93 trace.
set(C::execution_sel_opcode_error, 0, 0);
96 "OPCODE_ERROR_IF_VALIDATION_ERROR");
97 trace.
set(C::execution_sel_opcode_error, 0, 1);
100 trace.
set(C::execution_nullifier_tree_root, 0, 28);
103 "EMIT_NULLIFIER_TREE_ROOT_NOT_CHANGED");
106 trace.
set(C::execution_nullifier_tree_size, 0, 2);
109 "EMIT_NULLIFIER_TREE_SIZE_INCREASE");
112 trace.
set(C::execution_num_nullifiers_emitted, 0, prev_num_nullifiers_emitted + 1);
115 "EMIT_NULLIFIER_NUM_NULLIFIERS_EMITTED_INCREASE");
118TEST(EmitNullifierConstrainingTest, Interactions)
121 StrictMock<MockMerkleCheck> merkle_check;
123 StrictMock<MockFieldGreaterThan>
field_gt;
125 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
126 NullifierTreeCheck nullifier_tree_check(
poseidon2, merkle_check,
field_gt, nullifier_tree_check_event_emitter);
130 FF siloed_nullifier = 66;
131 FF low_leaf_nullifier = 99;
132 FF low_leaf_hash = 77;
133 FF updated_low_leaf_hash = 101;
134 FF new_leaf_hash = 111;
135 FF pre_write_root = 27;
136 FF intermediate_root = 33;
137 FF post_write_root = 88;
140 std::vector<FF> insertion_sibling_path = { 1, 2, 3 };
142 AppendOnlyTreeSnapshot prev_snapshot = AppendOnlyTreeSnapshot{
143 .root = pre_write_root,
144 .nextAvailableLeafIndex = 128,
146 uint32_t prev_num_nullifiers_emitted = 2;
149 EXPECT_CALL(
field_gt, ff_gt).WillOnce(Return(
true));
152 .WillOnce(Return(siloed_nullifier))
153 .WillOnce(Return(low_leaf_hash))
154 .WillOnce(Return(updated_low_leaf_hash))
155 .WillOnce(Return(new_leaf_hash));
157 EXPECT_CALL(merkle_check,
write).WillOnce(Return(intermediate_root)).WillOnce(Return(post_write_root));
162 AppendOnlyTreeSnapshot next_snapshot = nullifier_tree_check.write(
nullifier,
164 prev_num_nullifiers_emitted,
169 insertion_sibling_path);
171 TestTraceContainer
trace({ {
172 { C::execution_sel_execute_emit_nullifier, 1 },
174 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
176 { C::execution_sel_write_nullifier, 1 },
177 { C::execution_sel_opcode_error, 0 },
179 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
180 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted + 1 },
181 { C::execution_prev_nullifier_tree_root, prev_snapshot.root },
182 { C::execution_nullifier_tree_root, next_snapshot.root },
183 { C::execution_prev_nullifier_tree_size, prev_snapshot.nextAvailableLeafIndex },
184 { C::execution_nullifier_tree_size, next_snapshot.nextAvailableLeafIndex },
188 NullifierTreeCheckTraceBuilder nullifier_tree_check_trace_builder;
189 nullifier_tree_check_trace_builder.process(nullifier_tree_check_event_emitter.dump_events(),
trace);
190 check_relation<emit_nullifier>(
trace);
192 check_interaction<ExecutionTraceBuilder, lookup_emit_nullifier_write_nullifier_settings>(
trace);
195TEST(EmitNullifierConstrainingTest, InteractionsCollision)
198 StrictMock<MockMerkleCheck> merkle_check;
200 StrictMock<MockFieldGreaterThan>
field_gt;
202 EventEmitter<NullifierTreeCheckEvent> nullifier_tree_check_event_emitter;
203 NullifierTreeCheck nullifier_tree_check(
poseidon2, merkle_check,
field_gt, nullifier_tree_check_event_emitter);
207 FF siloed_nullifier = 66;
208 FF low_leaf_hash = 77;
209 FF pre_write_root = 27;
211 AppendOnlyTreeSnapshot prev_snapshot = AppendOnlyTreeSnapshot{
212 .root = pre_write_root,
213 .nextAvailableLeafIndex = 128,
215 uint32_t prev_num_nullifiers_emitted = 2;
218 EXPECT_CALL(
poseidon2,
hash).WillOnce(Return(siloed_nullifier)).WillOnce(Return(low_leaf_hash));
220 EXPECT_CALL(merkle_check, assert_membership).WillOnce(Return());
225 AppendOnlyTreeSnapshot next_snapshot = nullifier_tree_check.write(
nullifier,
227 prev_num_nullifiers_emitted,
234 TestTraceContainer
trace({ {
235 { C::execution_sel_execute_emit_nullifier, 1 },
237 { C::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(
MemoryTag::FF) },
239 { C::execution_sel_write_nullifier, 1 },
240 { C::execution_sel_opcode_error, 1 },
242 { C::execution_prev_num_nullifiers_emitted, prev_num_nullifiers_emitted },
243 { C::execution_num_nullifiers_emitted, prev_num_nullifiers_emitted },
244 { C::execution_prev_nullifier_tree_root, prev_snapshot.root },
245 { C::execution_nullifier_tree_root, next_snapshot.root },
246 { C::execution_prev_nullifier_tree_size, prev_snapshot.nextAvailableLeafIndex },
247 { C::execution_nullifier_tree_size, next_snapshot.nextAvailableLeafIndex },
251 NullifierTreeCheckTraceBuilder nullifier_tree_check_trace_builder;
252 nullifier_tree_check_trace_builder.process(nullifier_tree_check_event_emitter.dump_events(),
trace);
253 check_relation<emit_nullifier>(
trace);
255 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::merkle_tree::IndexedLeaf< crypto::merkle_tree::NullifierLeafValue > NullifierTreeLeafPreimage
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
::bb::crypto::merkle_tree::NullifierLeafValue NullifierLeafValue
std::variant< NullifierTreeReadWriteEvent, CheckPointEventType > NullifierTreeCheckEvent
void write(std::vector< uint8_t > &buf, ClientIVC::VerificationKey const &vk)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
FieldGreaterThan field_gt