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
31
32namespace bb::avm2::constraining {
33namespace {
34
35using ::testing::NiceMock;
36
37using simulation::EventEmitter;
38using simulation::MerkleCheck;
39using simulation::MerkleCheckEvent;
40using simulation::MockExecutionIdManager;
41using simulation::MockGreaterThan;
42using simulation::NoopEventEmitter;
43using simulation::NoteHashTreeCheck;
44using simulation::Poseidon2;
45using simulation::Poseidon2HashEvent;
46using simulation::Poseidon2PermutationEvent;
47using simulation::Poseidon2PermutationMemoryEvent;
49
50using tracegen::MerkleCheckTraceBuilder;
51using tracegen::NoteHashTreeCheckTraceBuilder;
52using tracegen::Poseidon2TraceBuilder;
53using tracegen::PrecomputedTraceBuilder;
54using tracegen::PublicInputsTraceBuilder;
55using tracegen::TestTraceContainer;
56
58using C = Column;
59using note_hash_tree_check = bb::avm2::note_hash_tree_check<FF>;
61
62TEST(NoteHashTreeCheckConstrainingTests, PositiveExists)
63{
64 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
65 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
66 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
67 NiceMock<MockGreaterThan> mock_gt;
68 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
71
72 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
73 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
74
75 EventEmitter<simulation::NoteHashTreeCheckEvent> note_hash_tree_check_event_emitter;
76 NoteHashTreeCheck note_hash_tree_check_simulator(0, poseidon2, merkle_check, note_hash_tree_check_event_emitter);
77
78 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
79 MerkleCheckTraceBuilder merkle_check_builder;
80 NoteHashTreeCheckTraceBuilder note_hash_tree_check_builder;
81
82 FF note_hash = 42;
83
84 uint64_t leaf_index = 30;
85 std::vector<FF> sibling_path;
86 sibling_path.reserve(NOTE_HASH_TREE_HEIGHT);
87 for (size_t i = 0; i < NOTE_HASH_TREE_HEIGHT; ++i) {
88 sibling_path.emplace_back(i);
89 }
90 FF root = unconstrained_root_from_path(note_hash, leaf_index, sibling_path);
91
92 EXPECT_TRUE(note_hash_tree_check_simulator.note_hash_exists(
95 leaf_index,
96 sibling_path,
97 AppendOnlyTreeSnapshot{ .root = root, .next_available_leaf_index = 128 }));
98
99 note_hash_tree_check_builder.process(note_hash_tree_check_event_emitter.dump_events(), trace);
100 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
101
102 check_relation<note_hash_tree_check>(trace);
103 // Not checking all interactions due to the public inputs interaction, which needs to be checked in an e2e test
104 check_interaction<NoteHashTreeCheckTraceBuilder,
110}
111
112TEST(NoteHashTreeCheckConstrainingTests, PositiveNotExists)
113{
114 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
115 EventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
116 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
117
118 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
119 NiceMock<MockGreaterThan> mock_gt;
121
122 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
123 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
124
125 EventEmitter<simulation::NoteHashTreeCheckEvent> note_hash_tree_check_event_emitter;
126 NoteHashTreeCheck note_hash_tree_check_simulator(0, poseidon2, merkle_check, note_hash_tree_check_event_emitter);
127
128 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
129 MerkleCheckTraceBuilder merkle_check_builder;
130 NoteHashTreeCheckTraceBuilder note_hash_tree_check_builder;
131
132 FF requested_note_hash = 42;
133 FF actual_leaf_value = 43;
134
135 uint64_t leaf_index = 30;
136 std::vector<FF> sibling_path;
137 sibling_path.reserve(NOTE_HASH_TREE_HEIGHT);
138 for (size_t i = 0; i < NOTE_HASH_TREE_HEIGHT; ++i) {
139 sibling_path.emplace_back(i);
140 }
141 FF root = unconstrained_root_from_path(actual_leaf_value, leaf_index, sibling_path);
142
143 EXPECT_FALSE(note_hash_tree_check_simulator.note_hash_exists(
144 requested_note_hash,
145 actual_leaf_value,
146 leaf_index,
147 sibling_path,
148 AppendOnlyTreeSnapshot{ .root = root, .next_available_leaf_index = 128 }));
149
150 note_hash_tree_check_builder.process(note_hash_tree_check_event_emitter.dump_events(), trace);
151 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
152
153 check_relation<note_hash_tree_check>(trace);
154 // Not checking all interactions due to the public inputs interaction, which needs to be checked in an e2e test
155 check_interaction<NoteHashTreeCheckTraceBuilder,
161}
162
163TEST(NoteHashTreeCheckConstrainingTests, PositiveWrite)
164{
165 auto test_public_inputs = testing::PublicInputsBuilder().rand_previous_non_revertible_accumulated_data(1).build();
166 EventEmitter<Poseidon2HashEvent> hash_event_emitter;
167 NoopEventEmitter<Poseidon2PermutationEvent> perm_event_emitter;
168 NoopEventEmitter<Poseidon2PermutationMemoryEvent> perm_mem_event_emitter;
169 NiceMock<MockGreaterThan> mock_gt;
170 NiceMock<MockExecutionIdManager> mock_exec_id_manager;
173
174 EventEmitter<MerkleCheckEvent> merkle_event_emitter;
175 MerkleCheck merkle_check(poseidon2, merkle_event_emitter);
176
177 EventEmitter<simulation::NoteHashTreeCheckEvent> note_hash_tree_check_event_emitter;
178 NoteHashTreeCheck note_hash_tree_check_simulator(
179 test_public_inputs.previous_non_revertible_accumulated_data.nullifiers[0],
180 poseidon2,
181 merkle_check,
182 note_hash_tree_check_event_emitter);
183
184 TestTraceContainer trace({ { { C::precomputed_first_row, 1 } } });
185
186 FF raw_note_hash = 42;
187
188 std::vector<FF> sibling_path;
189 sibling_path.reserve(NOTE_HASH_TREE_HEIGHT);
190 for (size_t i = 0; i < NOTE_HASH_TREE_HEIGHT; ++i) {
191 sibling_path.emplace_back(i);
192 }
193
194 AppendOnlyTreeSnapshot prev_snapshot{ .root = unconstrained_root_from_path(0, 128, sibling_path),
195 .next_available_leaf_index = 128 };
196
197 note_hash_tree_check_simulator.append_note_hash(raw_note_hash, AztecAddress(7), 10, sibling_path, prev_snapshot);
198
199 NoteHashTreeCheckTraceBuilder note_hash_tree_check_builder;
200 note_hash_tree_check_builder.process(note_hash_tree_check_event_emitter.dump_events(), trace);
201 Poseidon2TraceBuilder poseidon2_builder;
203 MerkleCheckTraceBuilder merkle_check_builder;
204 merkle_check_builder.process(merkle_event_emitter.dump_events(), trace);
205
206 PublicInputsTraceBuilder public_inputs_builder;
207 public_inputs_builder.process_public_inputs(trace, test_public_inputs);
208 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
209
210 PrecomputedTraceBuilder precomputed_builder;
213
214 check_relation<note_hash_tree_check>(trace);
215 // Not checking all interactions due to the public inputs interaction, which needs to be checked in an e2e test
216 check_interaction<NoteHashTreeCheckTraceBuilder,
222}
223
224TEST(NoteHashTreeCheckConstrainingTests, NegativeSiloingOnRead)
225{
226 TestTraceContainer trace({ {
227 { C::note_hash_tree_check_sel, 1 },
228 { C::note_hash_tree_check_write, 0 },
229 { C::note_hash_tree_check_sel_silo, 1 },
230 { C::note_hash_tree_check_note_hash, 27 },
231 } });
232
234 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_DISABLE_SILOING_ON_READ),
235 "DISABLE_SILOING_ON_READ");
236}
237
238TEST(NoteHashTreeCheckConstrainingTests, NegativePassthroughSiloing)
239{
240 TestTraceContainer trace({ {
241 { C::note_hash_tree_check_sel, 1 },
242 { C::note_hash_tree_check_write, 0 },
243 { C::note_hash_tree_check_sel_silo, 0 },
244 { C::note_hash_tree_check_note_hash, 27 },
245 { C::note_hash_tree_check_siloed_note_hash, 27 },
246 } });
247
248 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_SILOING);
249
250 trace.set(C::note_hash_tree_check_siloed_note_hash, 0, 28);
251
252 EXPECT_THROW_WITH_MESSAGE(check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_SILOING),
253 "PASSTHROUGH_SILOING");
254}
255
256TEST(NoteHashTreeCheckConstrainingTests, NegativeUniquenessOnRead)
257{
258 TestTraceContainer trace({ {
259 { C::note_hash_tree_check_sel, 1 },
260 { C::note_hash_tree_check_write, 0 },
261 { C::note_hash_tree_check_sel_unique, 1 },
262 { C::note_hash_tree_check_note_hash, 27 },
263 } });
264
266 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_DISABLE_UNIQUENESS_ON_READ),
267 "DISABLE_UNIQUENESS_ON_READ");
268}
269
270TEST(NoteHashTreeCheckConstrainingTests, NegativePassthroughUniqueness)
271{
272 TestTraceContainer trace({ {
273 { C::note_hash_tree_check_sel, 1 },
274 { C::note_hash_tree_check_write, 0 },
275 { C::note_hash_tree_check_sel_unique, 0 },
276 { C::note_hash_tree_check_note_hash, 27 },
277 { C::note_hash_tree_check_siloed_note_hash, 27 },
278 { C::note_hash_tree_check_unique_note_hash, 27 },
279 } });
280
281 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_UNIQUENESS);
282
283 trace.set(C::note_hash_tree_check_unique_note_hash, 0, 28);
284
286 check_relation<note_hash_tree_check>(trace, note_hash_tree_check::SR_PASSTHROUGH_UNIQUENESS),
287 "PASSTHROUGH_UNIQUENESS");
288}
289
290} // namespace
291} // namespace bb::avm2::constraining
#define EXPECT_THROW_WITH_MESSAGE(code, expectedMessageRegex)
Definition assert.hpp:193
#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_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)
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(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