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.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5
12
13namespace bb::avm2::simulation {
14
15using ::testing::_;
16using ::testing::AllOf;
17using ::testing::ElementsAre;
18using ::testing::Field;
19using ::testing::Return;
20using ::testing::StrictMock;
21
23
24namespace {
25
26TEST(AvmSimulationNoteHashTree, Exists)
27{
28 StrictMock<MockPoseidon2> poseidon2;
29 StrictMock<MockMerkleCheck> merkle_check;
30
31 EventEmitter<NoteHashTreeCheckEvent> event_emitter;
32 NoteHashTreeCheck note_hash_tree_check(1, poseidon2, merkle_check, event_emitter);
33
34 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
35 AppendOnlyTreeSnapshot snapshot = {
36 .root = 123456,
37 .nextAvailableLeafIndex = 128,
38 };
39
40 FF note_hash = 42;
41 uint64_t leaf_index = 30;
42
43 EXPECT_CALL(merkle_check, assert_membership(note_hash, leaf_index, _, snapshot.root)).WillRepeatedly(Return());
44
45 EXPECT_TRUE(note_hash_tree_check.note_hash_exists(note_hash, note_hash, leaf_index, sibling_path, snapshot));
46 EXPECT_FALSE(note_hash_tree_check.note_hash_exists(27, note_hash, leaf_index, sibling_path, snapshot));
47 EXPECT_THAT(event_emitter.dump_events(),
48 ElementsAre(
49 NoteHashTreeReadWriteEvent{
50 .note_hash = note_hash,
51 .existing_leaf_value = note_hash,
52 .leaf_index = leaf_index,
53 .prev_snapshot = snapshot,
54 },
55 NoteHashTreeReadWriteEvent{
56 .note_hash = 27,
57 .existing_leaf_value = note_hash,
58 .leaf_index = leaf_index,
59 .prev_snapshot = snapshot,
60 }));
61}
62
63TEST(AvmSimulationNoteHashTree, WriteUnique)
64{
65 StrictMock<MockPoseidon2> poseidon2;
66 StrictMock<MockMerkleCheck> merkle_check;
67
68 EventEmitter<NoteHashTreeCheckEvent> event_emitter;
69 NoteHashTreeCheck note_hash_tree_check(1, poseidon2, merkle_check, event_emitter);
70
71 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
72 AppendOnlyTreeSnapshot snapshot = {
73 .root = 123456,
74 .nextAvailableLeafIndex = 128,
75 };
76 FF note_hash = 42;
77 uint64_t note_hash_counter = 10;
78 FF next_root = 234567;
79
80 EXPECT_CALL(merkle_check, write(FF(0), note_hash, snapshot.nextAvailableLeafIndex, _, snapshot.root))
81 .WillOnce(Return(next_root));
82
83 AppendOnlyTreeSnapshot next_snapshot =
84 note_hash_tree_check.append_unique_note_hash(note_hash, note_hash_counter, sibling_path, snapshot);
85
86 EXPECT_EQ(next_snapshot.nextAvailableLeafIndex, snapshot.nextAvailableLeafIndex + 1);
87 NoteHashTreeReadWriteEvent expect_event = { .note_hash = note_hash,
88 .leaf_index = snapshot.nextAvailableLeafIndex,
89 .prev_snapshot = snapshot,
90 .append_data = NoteHashAppendData{
91 .note_hash_counter = note_hash_counter,
92 .next_snapshot = next_snapshot,
93 } };
94 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
95}
96
97TEST(AvmSimulationNoteHashTree, WriteSiloed)
98{
99 StrictMock<MockPoseidon2> poseidon2;
100 StrictMock<MockMerkleCheck> merkle_check;
101
102 EventEmitter<NoteHashTreeCheckEvent> event_emitter;
103 FF first_nullifier = 1;
104 NoteHashTreeCheck note_hash_tree_check(first_nullifier, poseidon2, merkle_check, event_emitter);
105
106 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
107 AppendOnlyTreeSnapshot snapshot = {
108 .root = 123456,
109 .nextAvailableLeafIndex = 128,
110 };
111 FF siloed_note_hash = 42;
112 uint64_t note_hash_counter = 10;
113 FF nonce = 43;
114 FF unique_note_hash = 44;
115
116 FF next_root = 234567;
117
118 std::vector<FF> nonce_hash_inputs = { GENERATOR_INDEX__NOTE_HASH_NONCE, first_nullifier, note_hash_counter };
119 EXPECT_CALL(poseidon2, hash(nonce_hash_inputs)).WillOnce(Return(nonce));
120
121 std::vector<FF> unique_note_hash_inputs = { GENERATOR_INDEX__UNIQUE_NOTE_HASH, nonce, siloed_note_hash };
122 EXPECT_CALL(poseidon2, hash(unique_note_hash_inputs)).WillOnce(Return(unique_note_hash));
123
124 EXPECT_CALL(merkle_check, write(FF(0), unique_note_hash, snapshot.nextAvailableLeafIndex, _, snapshot.root))
125 .WillOnce(Return(next_root));
126
127 AppendOnlyTreeSnapshot next_snapshot =
128 note_hash_tree_check.append_siloed_note_hash(siloed_note_hash, note_hash_counter, sibling_path, snapshot);
129
130 EXPECT_EQ(next_snapshot.nextAvailableLeafIndex, snapshot.nextAvailableLeafIndex + 1);
131 NoteHashTreeReadWriteEvent expect_event = { .note_hash = siloed_note_hash,
132 .leaf_index = snapshot.nextAvailableLeafIndex,
133 .prev_snapshot = snapshot,
134 .append_data = NoteHashAppendData{
135 .uniqueness_data =
136 NoteHashUniquenessData{
137 .nonce = nonce,
138 .unique_note_hash = unique_note_hash,
139 .first_nullifier = first_nullifier,
140 },
141 .note_hash_counter = note_hash_counter,
142 .next_snapshot = next_snapshot,
143 } };
144 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
145}
146
147TEST(AvmSimulationNoteHashTree, WriteRaw)
148{
149 StrictMock<MockPoseidon2> poseidon2;
150 StrictMock<MockMerkleCheck> merkle_check;
151
152 EventEmitter<NoteHashTreeCheckEvent> event_emitter;
153 FF first_nullifier = 1;
154 NoteHashTreeCheck note_hash_tree_check(first_nullifier, poseidon2, merkle_check, event_emitter);
155
156 std::vector<FF> sibling_path = { 1, 2, 3, 4, 5 };
157 AppendOnlyTreeSnapshot snapshot = {
158 .root = 123456,
159 .nextAvailableLeafIndex = 128,
160 };
161
162 FF raw_note_hash = 37;
163
165 FF siloed_note_hash = 42;
166
167 uint64_t note_hash_counter = 10;
168 FF nonce = 43;
169 FF unique_note_hash = 44;
170
171 FF next_root = 234567;
172
173 std::vector<FF> siloed_note_hash_inputs = { GENERATOR_INDEX__SILOED_NOTE_HASH, contract_address, raw_note_hash };
174 EXPECT_CALL(poseidon2, hash(siloed_note_hash_inputs)).WillOnce(Return(siloed_note_hash));
175
176 std::vector<FF> nonce_hash_inputs = { GENERATOR_INDEX__NOTE_HASH_NONCE, first_nullifier, note_hash_counter };
177 EXPECT_CALL(poseidon2, hash(nonce_hash_inputs)).WillOnce(Return(nonce));
178
179 std::vector<FF> unique_note_hash_inputs = { GENERATOR_INDEX__UNIQUE_NOTE_HASH, nonce, siloed_note_hash };
180 EXPECT_CALL(poseidon2, hash(unique_note_hash_inputs)).WillOnce(Return(unique_note_hash));
181
182 EXPECT_CALL(merkle_check, write(FF(0), unique_note_hash, snapshot.nextAvailableLeafIndex, _, snapshot.root))
183 .WillOnce(Return(next_root));
184
185 AppendOnlyTreeSnapshot next_snapshot = note_hash_tree_check.append_note_hash(
186 raw_note_hash, contract_address, note_hash_counter, sibling_path, snapshot);
187
188 EXPECT_EQ(next_snapshot.nextAvailableLeafIndex, snapshot.nextAvailableLeafIndex + 1);
189 NoteHashTreeReadWriteEvent expect_event = { .note_hash = raw_note_hash,
190 .leaf_index = snapshot.nextAvailableLeafIndex,
191 .prev_snapshot = snapshot,
192 .append_data = NoteHashAppendData{
193 .siloing_data =
194 NoteHashSiloingData{
195 .siloed_note_hash = siloed_note_hash,
196 .address = contract_address,
197 },
198 .uniqueness_data =
199 NoteHashUniquenessData{
200 .nonce = nonce,
201 .unique_note_hash = unique_note_hash,
202 .first_nullifier = first_nullifier,
203 },
204 .note_hash_counter = note_hash_counter,
205 .next_snapshot = next_snapshot,
206 } };
207 EXPECT_THAT(event_emitter.dump_events(), ElementsAre(expect_event));
208}
209
210TEST(AvmSimulationNoteHashTree, CheckpointListener)
211{
212 StrictMock<MockPoseidon2> poseidon2;
213 StrictMock<MockMerkleCheck> merkle_check;
214
215 EventEmitter<NoteHashTreeCheckEvent> event_emitter;
216 NoteHashTreeCheck note_hash_tree_check(1, poseidon2, merkle_check, event_emitter);
217
218 note_hash_tree_check.on_checkpoint_created();
219 note_hash_tree_check.on_checkpoint_committed();
220 note_hash_tree_check.on_checkpoint_reverted();
221 EXPECT_THAT(event_emitter.get_events().size(), 3);
222 EXPECT_THAT(event_emitter.dump_events(),
226}
227
228} // namespace
229
230} // namespace bb::avm2::simulation
#define GENERATOR_INDEX__NOTE_HASH_NONCE
#define GENERATOR_INDEX__SILOED_NOTE_HASH
#define GENERATOR_INDEX__UNIQUE_NOTE_HASH
EventEmitter< DataCopyEvent > event_emitter
void hash(State &state) noexcept
crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > poseidon2
TEST(EmitUnencryptedLogTest, Basic)
typename Flavor::FF FF
void write(B &buf, field2< base_field, Params > const &value)