Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
note_hash_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
32
33namespace bb::avm2::constraining {
34namespace {
35
36using ::testing::NiceMock;
37
38using simulation::EventEmitter;
39using simulation::MerkleCheck;
40using simulation::MerkleCheckEvent;
41using simulation::MockExecutionIdManager;
42using simulation::MockGreaterThan;
43using simulation::NoopEventEmitter;
44using simulation::NoteHashTreeCheck;
45using simulation::Poseidon2;
46using simulation::Poseidon2HashEvent;
47using simulation::Poseidon2PermutationEvent;
48using simulation::Poseidon2PermutationMemoryEvent;
50
51using tracegen::MerkleCheckTraceBuilder;
52using tracegen::NoteHashTreeCheckTraceBuilder;
53using tracegen::Poseidon2TraceBuilder;
54using tracegen::PrecomputedTraceBuilder;
55using tracegen::PublicInputsTraceBuilder;
56using tracegen::TestTraceContainer;
57
59using C = Column;
60using note_hash_tree_check = bb::avm2::note_hash_tree_check<FF>;
62
63TEST(NoteHashTreeCheckConstrainingTests, PositiveExists)
64{
65 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
66 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
67 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
68 NiceMock<MockGreaterThan> mock_gt;
69 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
72
73 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
74 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
75
76 EventEmitter<simulation::NoteHashTreeCheckEvent> note_hash_tree_check_event_emitter;
77 NoteHashTreeCheck note_hash_tree_check_simulator(0, poseidon2, merkle_check, note_hash_tree_check_event_emitter);
78
79 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
80 MerkleCheckTraceBuilder merkle_check_builder;
81 NoteHashTreeCheckTraceBuilder note_hash_tree_check_builder;
82
83 FF note_hash = 42;
84
85 uint64_t leaf_index = 30;
86 std::vector<FF> sibling_path;
87 sibling_path.reserve(NOTE_HASH_TREE_HEIGHT);
88 for (size_t i = 0; i < NOTE_HASH_TREE_HEIGHT; ++i) {
89 sibling_path.emplace_back(i);
90 }
91 FF root = unconstrained_root_from_path(DOM_SEP__MERKLE_HASH, note_hash, leaf_index, sibling_path);
92
93 EXPECT_TRUE(note_hash_tree_check_simulator.note_hash_exists(
96 leaf_index,
97 sibling_path,
98 AppendOnlyTreeSnapshot{ .root = root, .next_available_leaf_index = 128 }));
99
100 note_hash_tree_check_builder.process(note_hash_tree_check_event_emitter.dump_events(), trace);
101 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
102
103 check_relation<note_hash_tree_check>(trace);
104 // Not checking all interactions due to the public inputs interaction, which needs to be checked in an e2e test
105 check_interaction<NoteHashTreeCheckTraceBuilder,
111}
112
113TEST(NoteHashTreeCheckConstrainingTests, PositiveNotExists)
114{
115 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
116 EventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
117 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
118
119 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
120 NiceMock<MockGreaterThan> mock_gt;
122
123 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
124 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
125
126 EventEmitter<simulation::NoteHashTreeCheckEvent> note_hash_tree_check_event_emitter;
127 NoteHashTreeCheck note_hash_tree_check_simulator(0, poseidon2, merkle_check, note_hash_tree_check_event_emitter);
128
129 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
130 MerkleCheckTraceBuilder merkle_check_builder;
131 NoteHashTreeCheckTraceBuilder note_hash_tree_check_builder;
132
133 FF requested_note_hash = 42;
134 FF actual_leaf_value = 43;
135
136 uint64_t leaf_index = 30;
137 std::vector<FF> sibling_path;
138 sibling_path.reserve(NOTE_HASH_TREE_HEIGHT);
139 for (size_t i = 0; i < NOTE_HASH_TREE_HEIGHT; ++i) {
140 sibling_path.emplace_back(i);
141 }
142 FF root = unconstrained_root_from_path(DOM_SEP__MERKLE_HASH, actual_leaf_value, leaf_index, sibling_path);
143
144 EXPECT_FALSE(note_hash_tree_check_simulator.note_hash_exists(
145 requested_note_hash,
146 actual_leaf_value,
147 leaf_index,
148 sibling_path,
149 AppendOnlyTreeSnapshot{ .root = root, .next_available_leaf_index = 128 }));
150
151 note_hash_tree_check_builder.process(note_hash_tree_check_event_emitter.dump_events(), trace);
152 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
153
154 check_relation<note_hash_tree_check>(trace);
155 // Not checking all interactions due to the public inputs interaction, which needs to be checked in an e2e test
156 check_interaction<NoteHashTreeCheckTraceBuilder,
162}
163
164TEST(NoteHashTreeCheckConstrainingTests, PositiveWrite)
165{
166 auto test_public_inputs = testing::PublicInputsBuilder().rand_previous_non_revertible_accumulated_data(1).build();
167 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
168 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
169 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
170 NiceMock<MockGreaterThan> mock_gt;
171 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
174
175 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
176 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
177
178 EventEmitter<simulation::NoteHashTreeCheckEvent> note_hash_tree_check_event_emitter;
179 NoteHashTreeCheck note_hash_tree_check_simulator(
180 test_public_inputs.previous_non_revertible_accumulated_data.nullifiers[0],
181 poseidon2,
182 merkle_check,
183 note_hash_tree_check_event_emitter);
184
185 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
186
187 FF raw_note_hash = 42;
188
189 std::vector<FF> sibling_path;
190 sibling_path.reserve(NOTE_HASH_TREE_HEIGHT);
191 for (size_t i = 0; i < NOTE_HASH_TREE_HEIGHT; ++i) {
192 sibling_path.emplace_back(i);
193 }
194
195 AppendOnlyTreeSnapshot prev_snapshot{ .root =
197 .next_available_leaf_index = 128 };
198
199 note_hash_tree_check_simulator.append_note_hash(raw_note_hash, AztecAddress(7), 10, sibling_path, prev_snapshot);
200
201 NoteHashTreeCheckTraceBuilder note_hash_tree_check_builder;
202 note_hash_tree_check_builder.process(note_hash_tree_check_event_emitter.dump_events(), trace);
203 Poseidon2TraceBuilder poseidon2_builder;
205 MerkleCheckTraceBuilder merkle_check_builder;
206 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
207
208 PublicInputsTraceBuilder public_inputs_builder;
209 public_inputs_builder.process_public_inputs(trace, test_public_inputs);
210 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
211
212 PrecomputedTraceBuilder precomputed_builder;
215
216 check_relation<note_hash_tree_check>(trace);
217 // Not checking all interactions due to the public inputs interaction, which needs to be checked in an e2e test
218 check_interaction<NoteHashTreeCheckTraceBuilder,
224}
225
226TEST(NoteHashTreeCheckConstrainingTests, NegativeSiloingOnRead)
227{
228 TestTraceContainer trace({ {
229 { C::note_hash_tree_check_sel, 1 },
230 { C::note_hash_tree_check_write, 0 },
231 { C::note_hash_tree_check_sel_silo, 1 },
232 { C::note_hash_tree_check_note_hash, 27 },
233 } });
234
236 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_DISABLE_SILOING_ON_READ),
237 "DISABLE_SILOING_ON_READ");
238}
239
240TEST(NoteHashTreeCheckConstrainingTests, NegativePassthroughSiloing)
241{
242 TestTraceContainer trace({ {
243 { C::note_hash_tree_check_sel, 1 },
244 { C::note_hash_tree_check_write, 0 },
245 { C::note_hash_tree_check_sel_silo, 0 },
246 { C::note_hash_tree_check_note_hash, 27 },
247 { C::note_hash_tree_check_siloed_note_hash, 27 },
248 } });
249
250 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_SILOING);
251
252 trace.set(C::note_hash_tree_check_siloed_note_hash, 0, 28);
253
254 EXPECT_THROW_WITH_MESSAGE(check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_SILOING),
255 "PASSTHROUGH_SILOING");
256}
257
258TEST(NoteHashTreeCheckConstrainingTests, NegativeUniquenessOnRead)
259{
260 TestTraceContainer trace({ {
261 { C::note_hash_tree_check_sel, 1 },
262 { C::note_hash_tree_check_write, 0 },
263 { C::note_hash_tree_check_sel_unique, 1 },
264 { C::note_hash_tree_check_note_hash, 27 },
265 } });
266
268 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_DISABLE_UNIQUENESS_ON_READ),
269 "DISABLE_UNIQUENESS_ON_READ");
270}
271
272TEST(NoteHashTreeCheckConstrainingTests, NegativePassthroughUniqueness)
273{
274 TestTraceContainer trace({ {
275 { C::note_hash_tree_check_sel, 1 },
276 { C::note_hash_tree_check_write, 0 },
277 { C::note_hash_tree_check_sel_unique, 0 },
278 { C::note_hash_tree_check_note_hash, 27 },
279 { C::note_hash_tree_check_siloed_note_hash, 27 },
280 { C::note_hash_tree_check_unique_note_hash, 27 },
281 } });
282
283 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_UNIQUENESS);
284
285 trace.set(C::note_hash_tree_check_unique_note_hash, 0, 28);
286
288 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_UNIQUENESS),
289 "PASSTHROUGH_UNIQUENESS");
290}
291
292TEST(NoteHashTreeCheckConstrainingTests, NegativeWrongMerkleHashSeparator)
293{
294 TestTraceContainer trace({ {
295 { C::note_hash_tree_check_sel, 1 },
296 { C::note_hash_tree_check_merkle_hash_separator, DOM_SEP__MERKLE_HASH },
297 } });
298
299 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_MERKLE_HASH_SEPARATOR_CONSTANT);
300
301 // A malicious prover picking any other value must be rejected.
302 trace.set(C::note_hash_tree_check_merkle_hash_separator, 0, DOM_SEP__NULLIFIER_MERKLE);
303
305 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_MERKLE_HASH_SEPARATOR_CONSTANT),
306 "MERKLE_HASH_SEPARATOR_CONSTANT");
307}
308
309} // namespace
310} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
#define DOM_SEP__MERKLE_HASH
#define DOM_SEP__NULLIFIER_MERKLE
#define NOTE_HASH_TREE_HEIGHT
#define AVM_PUBLIC_INPUTS_COLUMNS_MAX_LENGTH
StrictMock< MockGreaterThan > mock_gt
EventEmitter< Poseidon2PermutationMemoryEvent > perm_mem_event_emitter
EventEmitter< Poseidon2PermutationEvent > perm_event_emitter
EventEmitter< Poseidon2HashEvent > hash_event_emitter
Poseidon2TraceBuilder poseidon2_builder
MerkleCheck merkle_check
static constexpr size_t SR_DISABLE_SILOING_ON_READ
static constexpr size_t SR_PASSTHROUGH_SILOING
static constexpr size_t SR_PASSTHROUGH_UNIQUENESS
static constexpr size_t SR_MERKLE_HASH_SEPARATOR_CONSTANT
static constexpr size_t SR_DISABLE_UNIQUENESS_ON_READ
void process_hash(const simulation::EventEmitterInterface< simulation::Poseidon2HashEvent >::Container &hash_events, TraceContainer &trace)
Processes the hash events for the Poseidon2 hash function. It populates the columns for the poseidon2...
void process_misc(TraceContainer &trace, const uint32_t num_rows=PRECOMPUTED_TRACE_SIZE)
Populate miscellaneous precomputed columns: first_row selector and idx (row index).
void process_phase_table(TraceContainer &trace)
Populate the transaction phase specification table.
void set(Column col, uint32_t row, const FF &value)
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:120
TestTraceContainer trace
void check_interaction(tracegen::TestTraceContainer &trace)
TEST(AvmFixedVKTests, FixedVKCommitments)
Test that the fixed VK commitments agree with the ones computed from precomputed columns.
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
FF unconstrained_root_from_path(uint64_t domain_separator, const FF &leaf_value, const uint64_t leaf_index, std::span< const FF > path)
Definition merkle.cpp:12
lookup_settings< lookup_note_hash_tree_check_merkle_check_settings_ > lookup_note_hash_tree_check_merkle_check_settings
lookup_settings< lookup_note_hash_tree_check_read_first_nullifier_settings_ > lookup_note_hash_tree_check_read_first_nullifier_settings
lookup_settings< lookup_note_hash_tree_check_nonce_computation_poseidon2_settings_ > lookup_note_hash_tree_check_nonce_computation_poseidon2_settings
lookup_settings< lookup_note_hash_tree_check_unique_note_hash_poseidon2_settings_ > lookup_note_hash_tree_check_unique_note_hash_poseidon2_settings
lookup_settings< lookup_note_hash_tree_check_silo_poseidon2_settings_ > lookup_note_hash_tree_check_silo_poseidon2_settings
tracegen::PublicInputsTraceBuilder public_inputs_builder
Definition tx.test.cpp:81