Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
merkle_check_trace.test.cpp
Go to the documentation of this file.
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <cstdint>
5#include <vector>
6
14
15namespace bb::avm2::tracegen {
16namespace {
17
18using testing::ElementsAre;
19using testing::Field;
20
22using Poseidon2 = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>;
23using simulation::MerkleCheckEvent;
24
25TEST(MerkleCheckTraceGenTest, MerkleRead)
26{
27 TestTraceContainer trace;
28 MerkleCheckTraceBuilder builder;
29
30 FF leaf_value = FF(123);
31 uint64_t leaf_index = 1; // Odd index
32
33 // Level 1 sibling
34 FF sibling_value_1 = FF(456);
35
36 // Compute hash for level 1
37 FF left_node_1 = sibling_value_1; // For odd index, sibling is left
38 FF right_node_1 = leaf_value; // For odd index, leaf is right
39 FF output_hash_1 = Poseidon2::hash({ left_node_1, right_node_1 });
40
41 // Level 2 sibling
42 FF sibling_value_2 = FF(789);
43
44 // Compute hash for level 2
45 FF left_node_2 = output_hash_1; // For odd index 1 in level 1, parent is at index 0 (even) in level 2
46 FF right_node_2 = sibling_value_2;
47 FF output_hash_2 = Poseidon2::hash({ left_node_2, right_node_2 });
48
49 std::vector<FF> sibling_path = { sibling_value_1, sibling_value_2 };
50 FF root = output_hash_2; // Root is the final output hash
51
52 MerkleCheckEvent event = {
53 .leaf_value = leaf_value, .leaf_index = leaf_index, .sibling_path = sibling_path, .root = root
54 };
55
56 builder.process({ event }, trace);
57
58 EXPECT_THAT(trace.as_rows(),
59 ElementsAre(
60 // First row is empty
61 AllOf(ROW_FIELD_EQ(merkle_check_sel, 0)),
62 // First real row
63 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
64 ROW_FIELD_EQ(merkle_check_write, 0),
65 ROW_FIELD_EQ(merkle_check_read_node, leaf_value),
66 ROW_FIELD_EQ(merkle_check_index, leaf_index),
67 ROW_FIELD_EQ(merkle_check_path_len, 2), // path length starts at 2
68 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, FF(2 - 1).invert()),
69 ROW_FIELD_EQ(merkle_check_read_root, root),
70 ROW_FIELD_EQ(merkle_check_sibling, sibling_value_1),
71 ROW_FIELD_EQ(merkle_check_start, 1),
72 ROW_FIELD_EQ(merkle_check_end, 0), // Not done yet
73 ROW_FIELD_EQ(merkle_check_index_is_even, 0), // Odd index
74 ROW_FIELD_EQ(merkle_check_read_left_node, left_node_1),
75 ROW_FIELD_EQ(merkle_check_read_right_node, right_node_1),
76 ROW_FIELD_EQ(merkle_check_read_output_hash, output_hash_1)),
77 // Second real row
78 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
79 ROW_FIELD_EQ(merkle_check_write, 0),
80 ROW_FIELD_EQ(merkle_check_read_node, output_hash_1), // Previous output becomes new leaf
81 ROW_FIELD_EQ(merkle_check_index, 0), // Index should be 0 at level 2
82 ROW_FIELD_EQ(merkle_check_path_len, 1), // Remaining path length is 0
83 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, 0),
84 ROW_FIELD_EQ(merkle_check_read_root, root),
85 ROW_FIELD_EQ(merkle_check_sibling, sibling_value_2),
86 ROW_FIELD_EQ(merkle_check_start, 0),
87 ROW_FIELD_EQ(merkle_check_end, 1), // Done after two layers
88 ROW_FIELD_EQ(merkle_check_index_is_even, 1),
89 ROW_FIELD_EQ(merkle_check_read_left_node, left_node_2),
90 ROW_FIELD_EQ(merkle_check_read_right_node, right_node_2),
91 ROW_FIELD_EQ(merkle_check_read_output_hash, output_hash_2))));
92}
93
94TEST(MerkleCheckTraceGenTest, MerkleWrite)
95{
96 TestTraceContainer trace;
97 MerkleCheckTraceBuilder builder;
98
99 FF leaf_value = FF(123);
100 FF new_leaf_value = FF(456);
101 uint64_t leaf_index = 1; // Odd index
102
103 // Level 1 sibling
104 FF sibling_value_1 = FF(456);
105
106 // Compute hash for level 1
107 // For odd index, sibling is left, leaf is right
108 FF read_output_hash_1 = Poseidon2::hash({ sibling_value_1, leaf_value });
109 FF write_output_hash_1 = Poseidon2::hash({ sibling_value_1, new_leaf_value });
110
111 // Level 2 sibling
112 FF sibling_value_2 = FF(789);
113
114 // Compute hash for level 2
115 // For odd index 1 in level 1, parent is at index 0 (even) in level 2
116 FF read_output_hash_2 = Poseidon2::hash({ read_output_hash_1, sibling_value_2 });
117 FF write_output_hash_2 = Poseidon2::hash({ write_output_hash_1, sibling_value_2 });
118
119 std::vector<FF> sibling_path = { sibling_value_1, sibling_value_2 };
120 FF read_root = read_output_hash_2;
121 FF write_root = write_output_hash_2;
122
123 MerkleCheckEvent event = { .leaf_value = leaf_value,
124 .new_leaf_value = new_leaf_value,
125 .leaf_index = leaf_index,
126 .sibling_path = sibling_path,
127 .root = read_root,
128 .new_root = write_root };
129
130 builder.process({ event }, trace);
131
132 EXPECT_THAT(trace.as_rows(),
133 ElementsAre(
134 // First row is empty
135 AllOf(ROW_FIELD_EQ(merkle_check_sel, 0)),
136 // First real row
137 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
138 ROW_FIELD_EQ(merkle_check_write, 1),
139 ROW_FIELD_EQ(merkle_check_read_node, leaf_value),
140 ROW_FIELD_EQ(merkle_check_write_node, new_leaf_value),
141 ROW_FIELD_EQ(merkle_check_index, leaf_index),
142 ROW_FIELD_EQ(merkle_check_path_len, 2), // path length starts at 2
143 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, FF(2 - 1).invert()),
144 ROW_FIELD_EQ(merkle_check_read_root, read_root),
145 ROW_FIELD_EQ(merkle_check_write_root, write_root),
146 ROW_FIELD_EQ(merkle_check_sibling, sibling_value_1),
147 ROW_FIELD_EQ(merkle_check_start, 1),
148 ROW_FIELD_EQ(merkle_check_end, 0), // Not done yet
149 ROW_FIELD_EQ(merkle_check_index_is_even, 0), // Odd index
150 ROW_FIELD_EQ(merkle_check_read_left_node, sibling_value_1),
151 ROW_FIELD_EQ(merkle_check_read_right_node, leaf_value),
152 ROW_FIELD_EQ(merkle_check_write_left_node, sibling_value_1),
153 ROW_FIELD_EQ(merkle_check_write_right_node, new_leaf_value),
154 ROW_FIELD_EQ(merkle_check_read_output_hash, read_output_hash_1),
155 ROW_FIELD_EQ(merkle_check_write_output_hash, write_output_hash_1)),
156 // Second real row
157 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
158 ROW_FIELD_EQ(merkle_check_write, 1),
159 ROW_FIELD_EQ(merkle_check_read_node, read_output_hash_1), // Previous output becomes new leaf
160 ROW_FIELD_EQ(merkle_check_write_node, write_output_hash_1),
161 ROW_FIELD_EQ(merkle_check_index, 0), // Index should be 0 at level 2
162 ROW_FIELD_EQ(merkle_check_path_len, 1), // Remaining path length is 0
163 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, 0),
164 ROW_FIELD_EQ(merkle_check_read_root, read_root),
165 ROW_FIELD_EQ(merkle_check_write_root, write_root),
166 ROW_FIELD_EQ(merkle_check_sibling, sibling_value_2),
167 ROW_FIELD_EQ(merkle_check_start, 0),
168 ROW_FIELD_EQ(merkle_check_end, 1), // Done after two layers
169 ROW_FIELD_EQ(merkle_check_index_is_even, 1),
170 ROW_FIELD_EQ(merkle_check_read_left_node, read_output_hash_1),
171 ROW_FIELD_EQ(merkle_check_read_right_node, sibling_value_2),
172 ROW_FIELD_EQ(merkle_check_write_left_node, write_output_hash_1),
173 ROW_FIELD_EQ(merkle_check_write_right_node, sibling_value_2),
174 ROW_FIELD_EQ(merkle_check_read_output_hash, read_output_hash_2),
175 ROW_FIELD_EQ(merkle_check_write_output_hash, write_output_hash_2))));
176}
177
178TEST(MerkleCheckTraceGenTest, MixedEvents)
179{
180 TestTraceContainer trace;
181 MerkleCheckTraceBuilder builder;
182
183 // First event - leaf_index 6 needs path_len 3 to reach root
184 // Binary 110: 6 -> 3 -> 1 -> 0
185 FF leaf_value_1 = FF(111);
186 uint64_t leaf_index_1 = 6;
187 FF sibling_1_level_0 = FF(222);
188 FF sibling_1_level_1 = FF(333);
189 FF sibling_1_level_2 = FF(444);
190
191 // Level 0: index 6 (even), so leaf is left, sibling is right
192 FF hash_1_level_0 = Poseidon2::hash({ leaf_value_1, sibling_1_level_0 });
193 // Level 1: index 3 (odd), so hash is right, sibling is left
194 FF hash_1_level_1 = Poseidon2::hash({ sibling_1_level_1, hash_1_level_0 });
195 // Level 2: index 1 (odd), so hash is right, sibling is left
196 FF root_1 = Poseidon2::hash({ sibling_1_level_2, hash_1_level_1 });
197
198 MerkleCheckEvent event1 = { .leaf_value = leaf_value_1,
199 .leaf_index = leaf_index_1,
200 .sibling_path = { sibling_1_level_0, sibling_1_level_1, sibling_1_level_2 },
201 .root = root_1 };
202
203 // Second event - leaf_index 11 needs path_len 4 to reach root
204 // Binary 1011: 11 -> 5 -> 2 -> 1 -> 0
205 FF leaf_value_2 = FF(555);
206 FF new_leaf_value_2 = FF(666);
207 uint64_t leaf_index_2 = 11;
208 FF sibling_2_level_0 = FF(777);
209 FF sibling_2_level_1 = FF(888);
210 FF sibling_2_level_2 = FF(999);
211 FF sibling_2_level_3 = FF(1010);
212
213 // Read path
214 // Level 0: index 11 (odd), so sibling is left, leaf is right
215 FF read_hash_2_level_0 = Poseidon2::hash({ sibling_2_level_0, leaf_value_2 });
216 // Level 1: index 5 (odd), so sibling is left, hash is right
217 FF read_hash_2_level_1 = Poseidon2::hash({ sibling_2_level_1, read_hash_2_level_0 });
218 // Level 2: index 2 (even), so hash is left, sibling is right
219 FF read_hash_2_level_2 = Poseidon2::hash({ read_hash_2_level_1, sibling_2_level_2 });
220 // Level 3: index 1 (odd), so sibling is left, hash is right
221 FF read_root_2 = Poseidon2::hash({ sibling_2_level_3, read_hash_2_level_2 });
222
223 // Write path
224 FF write_hash_2_level_0 = Poseidon2::hash({ sibling_2_level_0, new_leaf_value_2 });
225 FF write_hash_2_level_1 = Poseidon2::hash({ sibling_2_level_1, write_hash_2_level_0 });
226 FF write_hash_2_level_2 = Poseidon2::hash({ write_hash_2_level_1, sibling_2_level_2 });
227 FF write_root_2 = Poseidon2::hash({ sibling_2_level_3, write_hash_2_level_2 });
228
229 MerkleCheckEvent event2 = {
230 .leaf_value = leaf_value_2,
231 .new_leaf_value = new_leaf_value_2,
232 .leaf_index = leaf_index_2,
233 .sibling_path = { sibling_2_level_0, sibling_2_level_1, sibling_2_level_2, sibling_2_level_3 },
234 .root = read_root_2,
235 .new_root = write_root_2
236 };
237
238 builder.process({ event1, event2 }, trace);
239
240 EXPECT_THAT(trace.as_rows(),
241 ElementsAre(
242 // First row is empty
243 AllOf(ROW_FIELD_EQ(merkle_check_sel, 0)),
244 // Event 1 - Row 1: Level 0 (leaf_index 6)
245 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
246 ROW_FIELD_EQ(merkle_check_write, 0),
247 ROW_FIELD_EQ(merkle_check_read_node, leaf_value_1),
248 ROW_FIELD_EQ(merkle_check_index, 6),
249 ROW_FIELD_EQ(merkle_check_path_len, 3),
250 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, FF(2).invert()),
251 ROW_FIELD_EQ(merkle_check_read_root, root_1),
252 ROW_FIELD_EQ(merkle_check_sibling, sibling_1_level_0),
253 ROW_FIELD_EQ(merkle_check_start, 1),
254 ROW_FIELD_EQ(merkle_check_end, 0),
255 ROW_FIELD_EQ(merkle_check_index_is_even, 1),
256 ROW_FIELD_EQ(merkle_check_read_left_node, leaf_value_1),
257 ROW_FIELD_EQ(merkle_check_read_right_node, sibling_1_level_0),
258 ROW_FIELD_EQ(merkle_check_read_output_hash, hash_1_level_0)),
259 // Event 1 - Row 2: Level 1 (index 3)
260 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
261 ROW_FIELD_EQ(merkle_check_write, 0),
262 ROW_FIELD_EQ(merkle_check_read_node, hash_1_level_0),
263 ROW_FIELD_EQ(merkle_check_index, 3),
264 ROW_FIELD_EQ(merkle_check_path_len, 2),
265 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, FF(1).invert()),
266 ROW_FIELD_EQ(merkle_check_read_root, root_1),
267 ROW_FIELD_EQ(merkle_check_sibling, sibling_1_level_1),
268 ROW_FIELD_EQ(merkle_check_start, 0),
269 ROW_FIELD_EQ(merkle_check_end, 0),
270 ROW_FIELD_EQ(merkle_check_index_is_even, 0),
271 ROW_FIELD_EQ(merkle_check_read_left_node, sibling_1_level_1),
272 ROW_FIELD_EQ(merkle_check_read_right_node, hash_1_level_0),
273 ROW_FIELD_EQ(merkle_check_read_output_hash, hash_1_level_1)),
274 // Event 1 - Row 3: Level 2 (index 1, final)
275 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
276 ROW_FIELD_EQ(merkle_check_write, 0),
277 ROW_FIELD_EQ(merkle_check_read_node, hash_1_level_1),
278 ROW_FIELD_EQ(merkle_check_index, 1),
279 ROW_FIELD_EQ(merkle_check_path_len, 1),
280 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, 0),
281 ROW_FIELD_EQ(merkle_check_read_root, root_1),
282 ROW_FIELD_EQ(merkle_check_sibling, sibling_1_level_2),
283 ROW_FIELD_EQ(merkle_check_start, 0),
284 ROW_FIELD_EQ(merkle_check_end, 1),
285 ROW_FIELD_EQ(merkle_check_index_is_even, 0),
286 ROW_FIELD_EQ(merkle_check_read_left_node, sibling_1_level_2),
287 ROW_FIELD_EQ(merkle_check_read_right_node, hash_1_level_1),
288 ROW_FIELD_EQ(merkle_check_read_output_hash, root_1)),
289 // Event 2 - Row 1: Level 0 (leaf_index 11)
290 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
291 ROW_FIELD_EQ(merkle_check_write, 1),
292 ROW_FIELD_EQ(merkle_check_read_node, leaf_value_2),
293 ROW_FIELD_EQ(merkle_check_write_node, new_leaf_value_2),
294 ROW_FIELD_EQ(merkle_check_index, 11),
295 ROW_FIELD_EQ(merkle_check_path_len, 4),
296 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, FF(3).invert()),
297 ROW_FIELD_EQ(merkle_check_read_root, read_root_2),
298 ROW_FIELD_EQ(merkle_check_write_root, write_root_2),
299 ROW_FIELD_EQ(merkle_check_sibling, sibling_2_level_0),
300 ROW_FIELD_EQ(merkle_check_start, 1),
301 ROW_FIELD_EQ(merkle_check_end, 0),
302 ROW_FIELD_EQ(merkle_check_index_is_even, 0),
303 ROW_FIELD_EQ(merkle_check_read_left_node, sibling_2_level_0),
304 ROW_FIELD_EQ(merkle_check_read_right_node, leaf_value_2),
305 ROW_FIELD_EQ(merkle_check_write_left_node, sibling_2_level_0),
306 ROW_FIELD_EQ(merkle_check_write_right_node, new_leaf_value_2),
307 ROW_FIELD_EQ(merkle_check_read_output_hash, read_hash_2_level_0),
308 ROW_FIELD_EQ(merkle_check_write_output_hash, write_hash_2_level_0)),
309 // Event 2 - Row 2: Level 1 (index 5)
310 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
311 ROW_FIELD_EQ(merkle_check_write, 1),
312 ROW_FIELD_EQ(merkle_check_read_node, read_hash_2_level_0),
313 ROW_FIELD_EQ(merkle_check_write_node, write_hash_2_level_0),
314 ROW_FIELD_EQ(merkle_check_index, 5),
315 ROW_FIELD_EQ(merkle_check_path_len, 3),
316 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, FF(2).invert()),
317 ROW_FIELD_EQ(merkle_check_read_root, read_root_2),
318 ROW_FIELD_EQ(merkle_check_write_root, write_root_2),
319 ROW_FIELD_EQ(merkle_check_sibling, sibling_2_level_1),
320 ROW_FIELD_EQ(merkle_check_start, 0),
321 ROW_FIELD_EQ(merkle_check_end, 0),
322 ROW_FIELD_EQ(merkle_check_index_is_even, 0),
323 ROW_FIELD_EQ(merkle_check_read_left_node, sibling_2_level_1),
324 ROW_FIELD_EQ(merkle_check_read_right_node, read_hash_2_level_0),
325 ROW_FIELD_EQ(merkle_check_write_left_node, sibling_2_level_1),
326 ROW_FIELD_EQ(merkle_check_write_right_node, write_hash_2_level_0),
327 ROW_FIELD_EQ(merkle_check_read_output_hash, read_hash_2_level_1),
328 ROW_FIELD_EQ(merkle_check_write_output_hash, write_hash_2_level_1)),
329 // Event 2 - Row 3: Level 2 (index 2)
330 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
331 ROW_FIELD_EQ(merkle_check_write, 1),
332 ROW_FIELD_EQ(merkle_check_read_node, read_hash_2_level_1),
333 ROW_FIELD_EQ(merkle_check_write_node, write_hash_2_level_1),
334 ROW_FIELD_EQ(merkle_check_index, 2),
335 ROW_FIELD_EQ(merkle_check_path_len, 2),
336 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, FF(1).invert()),
337 ROW_FIELD_EQ(merkle_check_read_root, read_root_2),
338 ROW_FIELD_EQ(merkle_check_write_root, write_root_2),
339 ROW_FIELD_EQ(merkle_check_sibling, sibling_2_level_2),
340 ROW_FIELD_EQ(merkle_check_start, 0),
341 ROW_FIELD_EQ(merkle_check_end, 0),
342 ROW_FIELD_EQ(merkle_check_index_is_even, 1),
343 ROW_FIELD_EQ(merkle_check_read_left_node, read_hash_2_level_1),
344 ROW_FIELD_EQ(merkle_check_read_right_node, sibling_2_level_2),
345 ROW_FIELD_EQ(merkle_check_write_left_node, write_hash_2_level_1),
346 ROW_FIELD_EQ(merkle_check_write_right_node, sibling_2_level_2),
347 ROW_FIELD_EQ(merkle_check_read_output_hash, read_hash_2_level_2),
348 ROW_FIELD_EQ(merkle_check_write_output_hash, write_hash_2_level_2)),
349 // Event 2 - Row 4: Level 3 (index 1, final)
350 AllOf(ROW_FIELD_EQ(merkle_check_sel, 1),
351 ROW_FIELD_EQ(merkle_check_write, 1),
352 ROW_FIELD_EQ(merkle_check_read_node, read_hash_2_level_2),
353 ROW_FIELD_EQ(merkle_check_write_node, write_hash_2_level_2),
354 ROW_FIELD_EQ(merkle_check_index, 1),
355 ROW_FIELD_EQ(merkle_check_path_len, 1),
356 ROW_FIELD_EQ(merkle_check_path_len_min_one_inv, 0),
357 ROW_FIELD_EQ(merkle_check_read_root, read_root_2),
358 ROW_FIELD_EQ(merkle_check_write_root, write_root_2),
359 ROW_FIELD_EQ(merkle_check_sibling, sibling_2_level_3),
360 ROW_FIELD_EQ(merkle_check_start, 0),
361 ROW_FIELD_EQ(merkle_check_end, 1),
362 ROW_FIELD_EQ(merkle_check_index_is_even, 0),
363 ROW_FIELD_EQ(merkle_check_read_left_node, sibling_2_level_3),
364 ROW_FIELD_EQ(merkle_check_read_right_node, read_hash_2_level_2),
365 ROW_FIELD_EQ(merkle_check_write_left_node, sibling_2_level_3),
366 ROW_FIELD_EQ(merkle_check_write_right_node, write_hash_2_level_2),
367 ROW_FIELD_EQ(merkle_check_read_output_hash, read_root_2),
368 ROW_FIELD_EQ(merkle_check_write_output_hash, write_root_2))));
369}
370
371} // namespace
372} // namespace bb::avm2::tracegen
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
std::vector< AvmFullRowConstRef > as_rows() const
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
Implements a parallelized batch insertion indexed tree Accepts template argument of the type of store...
AluTraceBuilder builder
Definition alu.test.cpp:124
TestTraceContainer trace
#define ROW_FIELD_EQ(field_name, expression)
Definition macros.hpp:15
AvmFlavorSettings::FF FF
Definition field.hpp:10
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)