Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
world_state.test.cpp
Go to the documentation of this file.
10#include <array>
11#include <cstdint>
12#include <filesystem>
13#include <gtest/gtest.h>
14#include <optional>
15#include <stdexcept>
16#include <sys/types.h>
17#include <unordered_map>
18
19using namespace bb::world_state;
20using namespace bb::crypto::merkle_tree;
21
22class WorldStateTest : public testing::Test {
23 protected:
24 void SetUp() override
25 {
27 std::filesystem::create_directories(data_dir);
28 }
29
30 void TearDown() override { std::filesystem::remove_all(data_dir); }
31
32 static std::string data_dir;
33 uint64_t map_size = 10240;
34 uint64_t thread_pool_size = 1;
35
36 // TODO(): https://github.com/AztecProtocol/aztec-packages/issues/8084
37 std::unordered_map<MerkleTreeId, uint32_t> tree_heights{
38 { MerkleTreeId::NULLIFIER_TREE, NULLIFIER_TREE_HEIGHT },
39 { MerkleTreeId::NOTE_HASH_TREE, NOTE_HASH_TREE_HEIGHT },
40 { MerkleTreeId::PUBLIC_DATA_TREE, PUBLIC_DATA_TREE_HEIGHT },
41 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_TREE_HEIGHT },
42 { MerkleTreeId::ARCHIVE, ARCHIVE_HEIGHT },
43 };
44 std::unordered_map<MerkleTreeId, index_t> tree_prefill{
45 { MerkleTreeId::NULLIFIER_TREE, 128 },
46 { MerkleTreeId::PUBLIC_DATA_TREE, 128 },
47 };
49};
50
51std::string WorldStateTest::data_dir;
52
53template <typename Leaf>
55 const WorldState& ws, WorldStateRevision revision, MerkleTreeId tree_id, index_t leaf_index, bool exists)
56{
57 std::optional<Leaf> leaf = ws.get_leaf<Leaf>(revision, tree_id, leaf_index);
58 // TODO(#17755): Unwritten leaves at valid indices (index <= max_index) now return 0-value leaves with a message in
59 // the response from the tree, so leaf.has_value() is always true:
60 EXPECT_EQ(leaf.has_value(), true);
61 if (exists) {
62 EXPECT_NE(leaf.value(), fr::zero());
63 } else {
64 EXPECT_EQ(leaf.value(), fr::zero());
65 }
66}
67
68template <typename Leaf>
70 WorldStateRevision revision,
71 MerkleTreeId tree_id,
72 index_t leaf_index,
73 const Leaf& expected_value)
74{
75 std::optional<Leaf> leaf = ws.get_leaf<Leaf>(revision, tree_id, leaf_index);
76 EXPECT_EQ(leaf.has_value(), true);
77 EXPECT_EQ(leaf.value(), expected_value);
78}
79
80template <typename Leaf>
82 const WorldState& ws, WorldStateRevision revision, MerkleTreeId tree_id, const Leaf& expected_value, bool exists)
83{
85 ws.find_leaf_indices<Leaf>(revision, tree_id, { expected_value }, indices);
86 EXPECT_EQ(indices.size(), 1);
87 EXPECT_EQ(indices[0].has_value(), exists);
88}
89
90template <typename Leaf>
92 const WorldState& ws, WorldStateRevision revision, MerkleTreeId tree_id, const Leaf& value, index_t expected_index)
93{
95 ws.find_leaf_indices<Leaf>(revision, tree_id, { value }, indices);
96 EXPECT_EQ(indices.size(), 1);
97 EXPECT_TRUE(indices[0].has_value());
98 if (!indices[0].has_value()) {
99 return;
100 }
101 EXPECT_EQ(indices[0].value(), expected_index);
102}
103
104void assert_tree_size(const WorldState& ws, WorldStateRevision revision, MerkleTreeId tree_id, size_t expected_size)
105{
106 auto info = ws.get_tree_info(revision, tree_id);
107 EXPECT_EQ(info.meta.size, expected_size);
108}
109
111 const WorldState& ws, WorldStateRevision revision, MerkleTreeId tree_id, fr root, fr leaf, index_t index)
112{
113 auto sibling_path = ws.get_sibling_path(revision, tree_id, index);
114 fr left;
115 fr right;
116 fr hash = leaf;
117 for (const auto& node : sibling_path) {
118 if (index % 2 == 0) {
119 left = hash;
120 right = node;
121 } else {
122 left = node;
123 right = hash;
124 }
125
126 hash = HashPolicy::hash_pair(left, right);
127 index >>= 1;
128 }
129
130 EXPECT_EQ(hash, root);
131}
132
134 Fork::Id forkId,
135 bool includeUncommitted,
136 const std::vector<MerkleTreeId>& trees = { MerkleTreeId::NULLIFIER_TREE,
137 MerkleTreeId::NOTE_HASH_TREE,
138 MerkleTreeId::PUBLIC_DATA_TREE,
139 MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
140 MerkleTreeId::ARCHIVE })
141{
142
143 for (auto tree_id : trees) {
144 auto canonical_tree_info =
145 ws.get_tree_info(WorldStateRevision{ .includeUncommitted = includeUncommitted }, tree_id);
146 auto fork_tree_info = ws.get_tree_info(
148 .forkId = forkId,
149 .includeUncommitted = includeUncommitted,
150 },
151 tree_id);
152
153 EXPECT_EQ(canonical_tree_info.meta, fork_tree_info.meta);
154 }
155}
156
157TEST_F(WorldStateTest, GetInitialTreeInfoForAllTrees)
158{
159 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
160
161 {
162 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE);
163 EXPECT_EQ(info.meta.size, 128);
164 EXPECT_EQ(info.meta.depth, tree_heights.at(MerkleTreeId::NULLIFIER_TREE));
165 EXPECT_EQ(info.meta.root, bb::fr("0x1ec3788cd1c32e54d889d67fe29e481114f9d4afe9b44b229aa29d8ad528dd31"));
166 }
167
168 {
169 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE);
170 EXPECT_EQ(info.meta.size, 0);
171 EXPECT_EQ(info.meta.depth, tree_heights.at(MerkleTreeId::NOTE_HASH_TREE));
172 EXPECT_EQ(info.meta.root, bb::fr("0x2ac5dda169f6bb3b9ca09bbac34e14c94d1654597db740153a1288d859a8a30a"));
173 }
174
175 {
176 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::PUBLIC_DATA_TREE);
177 EXPECT_EQ(info.meta.size, 128);
178 EXPECT_EQ(info.meta.depth, tree_heights.at(MerkleTreeId::PUBLIC_DATA_TREE));
179 EXPECT_EQ(info.meta.root, bb::fr("0x23c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9"));
180 }
181
182 {
183 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::L1_TO_L2_MESSAGE_TREE);
184 EXPECT_EQ(info.meta.size, 0);
185 EXPECT_EQ(info.meta.depth, tree_heights.at(MerkleTreeId::L1_TO_L2_MESSAGE_TREE));
186 EXPECT_EQ(info.meta.root, bb::fr("0x0d582c10ff8115413aa5b70564fdd2f3cefe1f33a1e43a47bc495081e91e73e5"));
187 }
188
189 {
190 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::ARCHIVE);
191 EXPECT_EQ(info.meta.size, 1);
192 EXPECT_EQ(info.meta.depth, tree_heights.at(MerkleTreeId::ARCHIVE));
193 // this is the expected archive tree root at genesis
194 EXPECT_EQ(info.meta.root, bb::fr(GENESIS_ARCHIVE_ROOT));
195
196 // The leaf at index 0 is the genesis block hash.
198 ws, WorldStateRevision::committed(), MerkleTreeId::ARCHIVE, 0, bb::fr(GENESIS_BLOCK_HEADER_HASH));
199 }
200}
201
202TEST_F(WorldStateTest, GetInitialTreeInfoWithPrefilledPublicData)
203{
204 std::string data_dir_prefilled = random_temp_directory();
205 std::filesystem::create_directories(data_dir_prefilled);
206
207 std::vector<PublicDataLeafValue> prefilled_values = { PublicDataLeafValue(1000, 2000),
208 PublicDataLeafValue(3000, 4000) };
209
210 WorldState ws_prefilled(thread_pool_size,
211 data_dir_prefilled,
212 map_size,
213 tree_heights,
214 tree_prefill,
215 prefilled_values,
216 initial_header_generator_point);
217
218 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
219
220 {
221 auto prefilled = ws_prefilled.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE);
222 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE);
223 EXPECT_EQ(prefilled.meta.size, info.meta.size);
224 EXPECT_EQ(prefilled.meta.depth, info.meta.depth);
225 EXPECT_EQ(prefilled.meta.root, info.meta.root);
226 }
227
228 {
229 auto prefilled = ws_prefilled.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE);
230 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE);
231 EXPECT_EQ(prefilled.meta.size, info.meta.size);
232 EXPECT_EQ(prefilled.meta.depth, info.meta.depth);
233 EXPECT_EQ(prefilled.meta.root, info.meta.root);
234 }
235
236 {
237 auto prefilled = ws_prefilled.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::PUBLIC_DATA_TREE);
238 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::PUBLIC_DATA_TREE);
239 EXPECT_EQ(prefilled.meta.size, info.meta.size);
240 EXPECT_EQ(prefilled.meta.depth, info.meta.depth);
241 // Public data tree roots are different.
242 EXPECT_NE(prefilled.meta.root, info.meta.root);
243
244 // Prefilled values are appended at the end.
245 {
246 auto leaf = ws_prefilled.get_indexed_leaf<PublicDataLeafValue>(
247 WorldStateRevision::uncommitted(), MerkleTreeId::PUBLIC_DATA_TREE, prefilled.meta.size - 2);
248 EXPECT_EQ(leaf.value().leaf, prefilled_values[0]);
249 }
250 {
251 auto leaf = ws_prefilled.get_indexed_leaf<PublicDataLeafValue>(
252 WorldStateRevision::uncommitted(), MerkleTreeId::PUBLIC_DATA_TREE, prefilled.meta.size - 1);
253 EXPECT_EQ(leaf.value().leaf, prefilled_values[1]);
254 }
255 }
256
257 {
258 auto prefilled = ws_prefilled.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::ARCHIVE);
259 auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::ARCHIVE);
260 EXPECT_EQ(prefilled.meta.size, info.meta.size);
261 EXPECT_EQ(prefilled.meta.depth, info.meta.depth);
262 // Archive tree roots are different.
263 EXPECT_NE(prefilled.meta.root, info.meta.root);
264 }
265}
266
267TEST_F(WorldStateTest, GetStateReference)
268{
269 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
270
271 {
273 {
274 auto snapshot = state_ref.at(MerkleTreeId::NULLIFIER_TREE);
275 EXPECT_EQ(
276 snapshot,
277 std::make_pair(bb::fr("0x1ec3788cd1c32e54d889d67fe29e481114f9d4afe9b44b229aa29d8ad528dd31"), 128UL));
278 }
279
280 {
281 auto snapshot = state_ref.at(MerkleTreeId::NOTE_HASH_TREE);
282 EXPECT_EQ(
283 snapshot,
284 std::make_pair(bb::fr("0x2ac5dda169f6bb3b9ca09bbac34e14c94d1654597db740153a1288d859a8a30a"), 0UL));
285 }
286
287 {
288 auto snapshot = state_ref.at(MerkleTreeId::PUBLIC_DATA_TREE);
289 EXPECT_EQ(
290 snapshot,
291 std::make_pair(bb::fr("0x23c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9"), 128UL));
292 }
293
294 {
295 auto snapshot = state_ref.at(MerkleTreeId::L1_TO_L2_MESSAGE_TREE);
296 EXPECT_EQ(
297 snapshot,
298 std::make_pair(bb::fr("0x0d582c10ff8115413aa5b70564fdd2f3cefe1f33a1e43a47bc495081e91e73e5"), 0UL));
299 }
300 }
301
302 {
303 ws.append_leaves<bb::fr>(MerkleTreeId::NOTE_HASH_TREE, { 1 });
304
306 {
307 auto snapshot = state_ref.at(MerkleTreeId::NULLIFIER_TREE);
308 EXPECT_EQ(
309 snapshot,
310 std::make_pair(bb::fr("0x1ec3788cd1c32e54d889d67fe29e481114f9d4afe9b44b229aa29d8ad528dd31"), 128UL));
311 }
312
313 {
314 auto snapshot = state_ref.at(MerkleTreeId::NOTE_HASH_TREE);
315 EXPECT_EQ(
316 snapshot,
317 std::make_pair(bb::fr("0x19581629b6133a7e6fb7b472992ed85cf2b33ee6a74109fd5323ffd2f12e4550"), 1UL));
318 }
319
320 {
321 auto snapshot = state_ref.at(MerkleTreeId::PUBLIC_DATA_TREE);
322 EXPECT_EQ(
323 snapshot,
324 std::make_pair(bb::fr("0x23c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9"), 128UL));
325 }
326
327 {
328 auto snapshot = state_ref.at(MerkleTreeId::L1_TO_L2_MESSAGE_TREE);
329 EXPECT_EQ(
330 snapshot,
331 std::make_pair(bb::fr("0x0d582c10ff8115413aa5b70564fdd2f3cefe1f33a1e43a47bc495081e91e73e5"), 0UL));
332 }
333 }
334}
335
336TEST_F(WorldStateTest, GetInitialStateReference)
337{
338 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
339
340 auto before_commit = ws.get_initial_state_reference();
341 ws.append_leaves<bb::fr>(MerkleTreeId::NOTE_HASH_TREE, { 1 });
343 ws.commit(status);
344
345 auto after_commit = ws.get_initial_state_reference();
346
347 EXPECT_EQ(before_commit, after_commit);
348}
349
350TEST_F(WorldStateTest, AppendOnlyTrees)
351{
352 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
353
354 // the trees that start out empty
355 std::vector tree_ids{ MerkleTreeId::NOTE_HASH_TREE, MerkleTreeId::L1_TO_L2_MESSAGE_TREE };
356
357 for (auto tree_id : tree_ids) {
358 auto initial = ws.get_tree_info(WorldStateRevision::committed(), tree_id);
359 assert_leaf_status<fr>(ws, WorldStateRevision::committed(), tree_id, 0, false);
360
361 ws.append_leaves<fr>(tree_id, { fr(42) });
363 assert_leaf_status<fr>(ws, WorldStateRevision::committed(), tree_id, 0, false);
365
366 auto uncommitted = ws.get_tree_info(WorldStateRevision::uncommitted(), tree_id);
367 // uncommitted state diverges from committed state
368 EXPECT_EQ(uncommitted.meta.size, initial.meta.size + 1);
369 EXPECT_NE(uncommitted.meta.root, initial.meta.root);
370
371 assert_sibling_path(ws, WorldStateRevision::uncommitted(), tree_id, uncommitted.meta.root, fr(42), 0);
372
373 auto committed = ws.get_tree_info(WorldStateRevision::committed(), tree_id);
374 EXPECT_EQ(committed.meta.size, initial.meta.size);
375 EXPECT_EQ(committed.meta.root, initial.meta.root);
376
378 ws.commit(status);
379 assert_leaf_value(ws, WorldStateRevision::committed(), tree_id, 0, fr(42));
380 assert_leaf_index(ws, WorldStateRevision::committed(), tree_id, fr(42), 0);
381
382 auto after_commit = ws.get_tree_info(WorldStateRevision::committed(), tree_id);
383 // commiting updates the committed state
384 EXPECT_EQ(after_commit.meta.size, uncommitted.meta.size);
385 EXPECT_EQ(after_commit.meta.root, uncommitted.meta.root);
386
387 assert_sibling_path(ws, WorldStateRevision::committed(), tree_id, after_commit.meta.root, fr(42), 0);
388
389 ws.append_leaves<fr>(tree_id, { fr(43) });
391 assert_leaf_status<fr>(ws, WorldStateRevision::committed(), tree_id, 1, false);
393
394 auto before_rollback = ws.get_tree_info(WorldStateRevision::uncommitted(), tree_id);
395 EXPECT_EQ(before_rollback.meta.size, after_commit.meta.size + 1);
396 EXPECT_NE(before_rollback.meta.root, after_commit.meta.root);
397
398 ws.rollback();
399 assert_leaf_status<fr>(ws, WorldStateRevision::uncommitted(), tree_id, 1, false);
400 assert_leaf_status<fr>(ws, WorldStateRevision::committed(), tree_id, 1, false);
401
402 auto after_rollback = ws.get_tree_info(WorldStateRevision::committed(), tree_id);
403 // rollback restores the committed state
404 EXPECT_EQ(after_rollback.meta.size, after_commit.meta.size);
405 EXPECT_EQ(after_rollback.meta.root, after_commit.meta.root);
406 }
407}
408
409TEST_F(WorldStateTest, AppendOnlyAllowDuplicates)
410{
411 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
412
413 // the trees that start out empty
414 std::vector tree_ids{
415 MerkleTreeId::NOTE_HASH_TREE,
416 MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
417 };
418
419 for (auto tree_id : tree_ids) {
420 ws.append_leaves<fr>(tree_id, { fr(42), fr(42) });
421 ws.append_leaves<fr>(tree_id, { fr(42) });
422
426
428 ws.commit(status);
429
430 assert_leaf_value(ws, WorldStateRevision::committed(), tree_id, 0, fr(42));
431 assert_leaf_value(ws, WorldStateRevision::committed(), tree_id, 1, fr(42));
432 assert_leaf_value(ws, WorldStateRevision::committed(), tree_id, 2, fr(42));
433 }
434}
435
437{
438 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
439 auto tree_id = MerkleTreeId::NULLIFIER_TREE;
440 NullifierLeafValue test_nullifier(142);
441
442 auto predecessor_of_142 =
443 ws.find_low_leaf_index(WorldStateRevision::committed(), tree_id, test_nullifier.get_key());
444 EXPECT_EQ(predecessor_of_142, GetLowIndexedLeafResponse(false, 127UL));
445
446 ws.append_leaves<NullifierLeafValue>(tree_id, { test_nullifier });
447 assert_leaf_value(ws, WorldStateRevision::uncommitted(), tree_id, 128, test_nullifier);
448
450 ws.commit(status);
451
452 auto test_leaf = ws.get_indexed_leaf<NullifierLeafValue>(WorldStateRevision::committed(), tree_id, 128);
453 // at this point 142 should be the biggest leaf so it wraps back to 0
454 EXPECT_TRUE(test_leaf.has_value());
455 EXPECT_EQ(test_leaf.value(), IndexedLeaf(test_nullifier, 0, 0));
456
457 auto predecessor_of_142_again =
458 ws.find_low_leaf_index(WorldStateRevision::committed(), tree_id, test_nullifier.get_key());
459 EXPECT_EQ(predecessor_of_142_again, GetLowIndexedLeafResponse(true, 128UL));
460
461 auto predecessor_of_143 = ws.find_low_leaf_index(WorldStateRevision::committed(), tree_id, 143);
462 EXPECT_EQ(predecessor_of_143,
463 GetLowIndexedLeafResponse(false, 128UL)); // predecessor is going to be nullifier 142 on slot 127
464
468 tree_id,
469 info.meta.root,
470 HashPolicy::hash(test_leaf.value().get_hash_inputs()),
471 128);
472}
473
474TEST_F(WorldStateTest, NullifierTreeDuplicates)
475{
476 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
477 auto tree_id = MerkleTreeId::NULLIFIER_TREE;
478 NullifierLeafValue test_nullifier(142);
479
480 ws.append_leaves<NullifierLeafValue>(tree_id, { test_nullifier });
482 ws.commit(status);
483
485 EXPECT_THROW(ws.append_leaves<NullifierLeafValue>(tree_id, { test_nullifier }), std::runtime_error);
487}
488
489TEST_F(WorldStateTest, NullifierBatchInsert)
490{
491 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
493 MerkleTreeId::NULLIFIER_TREE, { NullifierLeafValue(150), NullifierLeafValue(142), NullifierLeafValue(180) }, 2);
494
495 std::vector<std::pair<NullifierLeafValue, size_t>> expected_sorted_leaves = { { NullifierLeafValue(180), 2 },
496 { NullifierLeafValue(150), 0 },
497 { NullifierLeafValue(142), 1 } };
498 EXPECT_EQ(response.sorted_leaves, expected_sorted_leaves);
499
500 {
501 // insertion happens in descending order, but keeping original indices
502 // first insert leaf 180, at index 130 (tree had size 127, 180 is the third item => 127 + 3)
503 // predecessor will be 127, currently linked to head of the list (0)
504 auto low_leaf = response.low_leaf_witness_data[0];
505 auto expected_low_leaf = IndexedLeaf(NullifierLeafValue(127), 0, fr(0));
506 EXPECT_EQ(low_leaf.index, 127);
507 EXPECT_EQ(low_leaf.leaf, expected_low_leaf);
508 }
509
510 {
511 // insert 150 on position 128 (127 + 1)
512 // predecessor will be 127 linked to 180
513 auto low_leaf = response.low_leaf_witness_data[1];
514 auto expected_low_leaf = IndexedLeaf(NullifierLeafValue(127), 130, fr(180));
515 EXPECT_EQ(low_leaf.index, 127);
516 EXPECT_EQ(low_leaf.leaf, expected_low_leaf);
517 }
518
519 {
520 // finally, insert 142 on position 129(127 + 2)
521 // prededecessor will be 127 linked to 150
522 auto low_leaf = response.low_leaf_witness_data[2];
523 auto expected_low_leaf = IndexedLeaf(NullifierLeafValue(127), 128, fr(150));
524 EXPECT_EQ(low_leaf.index, 127);
525 EXPECT_EQ(low_leaf.leaf, expected_low_leaf);
526 }
527}
528
530{
531 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
532
533 ws.append_leaves(MerkleTreeId::PUBLIC_DATA_TREE, std::vector{ PublicDataLeafValue(142, 0) });
534 assert_tree_size(ws, WorldStateRevision::uncommitted(), MerkleTreeId::PUBLIC_DATA_TREE, 129);
535
537 WorldStateRevision::uncommitted(), MerkleTreeId::PUBLIC_DATA_TREE, 128);
538 EXPECT_EQ(leaf.value().leaf, PublicDataLeafValue(142, 0));
539
541 // updating insert a dummy leaf
542 assert_tree_size(ws, WorldStateRevision::uncommitted(), MerkleTreeId::PUBLIC_DATA_TREE, 130);
543
545 WorldStateRevision::uncommitted(), MerkleTreeId::PUBLIC_DATA_TREE, 128);
546 EXPECT_EQ(leaf.value().leaf, PublicDataLeafValue(142, 1));
547}
548
549TEST_F(WorldStateTest, CommitsAndRollsBackAllTrees)
550{
551 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
552
553 ws.append_leaves<fr>(MerkleTreeId::NOTE_HASH_TREE, { fr(42) });
554 ws.append_leaves<fr>(MerkleTreeId::L1_TO_L2_MESSAGE_TREE, { fr(42) });
555 ws.append_leaves<fr>(MerkleTreeId::ARCHIVE, { fr(42) });
556 ws.append_leaves<NullifierLeafValue>(MerkleTreeId::NULLIFIER_TREE, { NullifierLeafValue(142) });
557 ws.append_leaves<PublicDataLeafValue>(MerkleTreeId::PUBLIC_DATA_TREE, { PublicDataLeafValue(142, 1) });
558
560 ws.commit(status);
561
562 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE, 0, fr(42));
563 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::L1_TO_L2_MESSAGE_TREE, 0, fr(42));
564 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::ARCHIVE, 1, fr(42));
565 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE, 128, NullifierLeafValue(142));
567 ws, WorldStateRevision::committed(), MerkleTreeId::PUBLIC_DATA_TREE, 128, PublicDataLeafValue(142, 1));
568
569 ws.append_leaves<fr>(MerkleTreeId::NOTE_HASH_TREE, { fr(43) });
570 ws.append_leaves<fr>(MerkleTreeId::L1_TO_L2_MESSAGE_TREE, { fr(43) });
571 ws.append_leaves<fr>(MerkleTreeId::ARCHIVE, { fr(43) });
572 ws.append_leaves<NullifierLeafValue>(MerkleTreeId::NULLIFIER_TREE, { NullifierLeafValue(143) });
573 ws.append_leaves<PublicDataLeafValue>(MerkleTreeId::PUBLIC_DATA_TREE, { PublicDataLeafValue(143, 1) });
574
575 ws.rollback();
576
577 assert_leaf_exists(ws, WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE, fr(43), false);
578 assert_leaf_exists(ws, WorldStateRevision::committed(), MerkleTreeId::L1_TO_L2_MESSAGE_TREE, fr(43), false);
579 assert_leaf_exists(ws, WorldStateRevision::committed(), MerkleTreeId::ARCHIVE, fr(43), false);
581 ws, WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE, NullifierLeafValue(143), false);
583 ws, WorldStateRevision::committed(), MerkleTreeId::PUBLIC_DATA_TREE, PublicDataLeafValue(143, 1), false);
584}
585
586TEST_F(WorldStateTest, SyncExternalBlockFromEmpty)
587{
588 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
589 StateReference block_state_ref = {
590 { MerkleTreeId::NULLIFIER_TREE,
591 { fr("0x1a8a3172ecd372de7d144459831cfabf0496159a5defd0f2ecb8f5124f1717af"), 129 } },
592 { MerkleTreeId::NOTE_HASH_TREE,
593 { fr("0x2496ae3983b59733967ef32aecb041134d5f17bd2b040def30e699432dcc8967"), 1 } },
594 { MerkleTreeId::PUBLIC_DATA_TREE,
595 { fr("0x0278dcf9ff541da255ee722aecfad849b66af0d42c2924d949b5a509f2e1aec9"), 129 } },
596 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
597 { fr("0x149be5d1559bbefa0006c5e55ed982c43a1db53848e2f59385523d0c40d74a94"), 1 } },
598 };
599
601 block_state_ref, fr(1), { 42 }, { 43 }, { NullifierLeafValue(144) }, { { PublicDataLeafValue(145, 1) } });
602 WorldStateStatusSummary expected(1, 0, 1, true);
603 EXPECT_EQ(status.summary, expected);
604
605 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE, 0, fr(42));
606 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::L1_TO_L2_MESSAGE_TREE, 0, fr(43));
607 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE, 128, NullifierLeafValue(144));
609 ws, WorldStateRevision::committed(), MerkleTreeId::PUBLIC_DATA_TREE, 128, PublicDataLeafValue(145, 1));
610 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::ARCHIVE, 1, fr(1));
611
613 for (const auto& [tree_id, snapshot] : block_state_ref) {
614 EXPECT_EQ(state_ref.at(tree_id), snapshot);
615 }
616
619 WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE, { 0 }, blockNumbers);
620 EXPECT_EQ(blockNumbers.size(), 1);
621 EXPECT_EQ(blockNumbers[0], 1);
622
624 WorldStateRevision{ .forkId = CANONICAL_FORK_ID, .blockNumber = 2, .includeUncommitted = false },
625 MerkleTreeId::NOTE_HASH_TREE,
626 { 0 },
627 blockNumbers),
628 std::runtime_error);
629}
630
631TEST_F(WorldStateTest, SyncBlockFromDirtyState)
632{
633 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
634 StateReference block_state_ref = {
635 { MerkleTreeId::NULLIFIER_TREE,
636 { fr("0x1a8a3172ecd372de7d144459831cfabf0496159a5defd0f2ecb8f5124f1717af"), 129 } },
637 { MerkleTreeId::NOTE_HASH_TREE,
638 { fr("0x2496ae3983b59733967ef32aecb041134d5f17bd2b040def30e699432dcc8967"), 1 } },
639 { MerkleTreeId::PUBLIC_DATA_TREE,
640 { fr("0x0278dcf9ff541da255ee722aecfad849b66af0d42c2924d949b5a509f2e1aec9"), 129 } },
641 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
642 { fr("0x149be5d1559bbefa0006c5e55ed982c43a1db53848e2f59385523d0c40d74a94"), 1 } },
643 };
644
645 ws.append_leaves<fr>(MerkleTreeId::NOTE_HASH_TREE, { fr(142) });
646 ws.append_leaves<fr>(MerkleTreeId::L1_TO_L2_MESSAGE_TREE, { fr(143) });
647 ws.append_leaves<NullifierLeafValue>(MerkleTreeId::NULLIFIER_TREE, { NullifierLeafValue(142) });
648 ws.append_leaves<PublicDataLeafValue>(MerkleTreeId::PUBLIC_DATA_TREE, { PublicDataLeafValue(142, 1) });
649
650 auto uncommitted_state_ref = ws.get_state_reference(WorldStateRevision::uncommitted());
651 for (const auto& [tree_id, snapshot] : block_state_ref) {
652 EXPECT_NE(uncommitted_state_ref.at(tree_id), snapshot);
653 }
654
656 block_state_ref, fr(1), { 42 }, { 43 }, { NullifierLeafValue(144) }, { { PublicDataLeafValue(145, 1) } });
657 WorldStateStatusSummary expected{ 1, 0, 1, true };
658 EXPECT_EQ(status.summary, expected);
659
660 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::NOTE_HASH_TREE, 0, fr(42));
661 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::L1_TO_L2_MESSAGE_TREE, 0, fr(43));
662 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE, 128, NullifierLeafValue(144));
664 ws, WorldStateRevision::committed(), MerkleTreeId::PUBLIC_DATA_TREE, 128, PublicDataLeafValue(145, 1));
665 assert_leaf_value(ws, WorldStateRevision::committed(), MerkleTreeId::ARCHIVE, 1, fr(1));
666
668 for (const auto& [tree_id, snapshot] : block_state_ref) {
669 EXPECT_EQ(state_ref.at(tree_id), snapshot);
670 }
671}
672
673TEST_F(WorldStateTest, SyncCurrentBlock)
674{
675 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
676 bb::fr block_hash(1);
677 StateReference block_state_ref = {
678 { MerkleTreeId::NULLIFIER_TREE,
679 { fr("0x1a8a3172ecd372de7d144459831cfabf0496159a5defd0f2ecb8f5124f1717af"), 129 } },
680 { MerkleTreeId::NOTE_HASH_TREE,
681 { fr("0x2496ae3983b59733967ef32aecb041134d5f17bd2b040def30e699432dcc8967"), 1 } },
682 { MerkleTreeId::PUBLIC_DATA_TREE,
683 { fr("0x0278dcf9ff541da255ee722aecfad849b66af0d42c2924d949b5a509f2e1aec9"), 129 } },
684 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
685 { fr("0x149be5d1559bbefa0006c5e55ed982c43a1db53848e2f59385523d0c40d74a94"), 1 } },
686 };
687
688 ws.append_leaves<fr>(MerkleTreeId::NOTE_HASH_TREE, { 42 });
689 ws.append_leaves<fr>(MerkleTreeId::L1_TO_L2_MESSAGE_TREE, { 43 });
690 ws.append_leaves<NullifierLeafValue>(MerkleTreeId::NULLIFIER_TREE, { NullifierLeafValue(144) });
691 ws.append_leaves<PublicDataLeafValue>(MerkleTreeId::PUBLIC_DATA_TREE, { PublicDataLeafValue(145, 1) });
692 ws.append_leaves<fr>(MerkleTreeId::ARCHIVE, { block_hash });
693
694 auto uncommitted_state_ref = ws.get_state_reference(WorldStateRevision::uncommitted());
695 for (const auto& [tree_id, snapshot] : block_state_ref) {
696 EXPECT_EQ(uncommitted_state_ref.at(tree_id), snapshot);
697 }
698
700 block_state_ref, fr(1), { 42 }, { 43 }, { NullifierLeafValue(144) }, { { PublicDataLeafValue(145, 1) } });
701 WorldStateStatusSummary expected{ 1, 0, 1, true };
702 EXPECT_EQ(status.summary, expected);
703
704 assert_leaf_value(ws, WorldStateRevision::uncommitted(), MerkleTreeId::ARCHIVE, 1, fr(1));
705
707 for (const auto& [tree_id, snapshot] : block_state_ref) {
708 EXPECT_EQ(state_ref.at(tree_id), snapshot);
709 }
710}
711
712TEST_F(WorldStateTest, RejectSyncBlockWithBadPublicWriteBatches)
713{
714 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
715 StateReference block_state_ref = {
716 { MerkleTreeId::NULLIFIER_TREE,
717 { fr("0x1a8a3172ecd372de7d144459831cfabf0496159a5defd0f2ecb8f5124f1717af"), 129 } },
718 { MerkleTreeId::NOTE_HASH_TREE,
719 { fr("0x2496ae3983b59733967ef32aecb041134d5f17bd2b040def30e699432dcc8967"), 1 } },
720 { MerkleTreeId::PUBLIC_DATA_TREE,
721 { fr("0x0278dcf9ff541da255ee722aecfad849b66af0d42c2924d949b5a509f2e1aec9"), 129 } },
722 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
723 { fr("0x149be5d1559bbefa0006c5e55ed982c43a1db53848e2f59385523d0c40d74a94"), 1 } },
724 };
725
726 auto sync = [&]() {
727 return ws.sync_block(block_state_ref,
728 fr(1),
729 { 42 },
730 { 43 },
731 { NullifierLeafValue(144) },
732 // this should be rejected because we can't have duplicate slots in the same batch
733 { { PublicDataLeafValue(145, 1), PublicDataLeafValue(145, 2) } });
734 };
735
736 EXPECT_THROW(sync(), std::runtime_error);
737}
738
739TEST_F(WorldStateTest, RejectSyncBlockWithInvalidStateRef)
740{
741 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
742 StateReference block_state_ref = {
743 { MerkleTreeId::NULLIFIER_TREE,
744 { fr("0x1a8a3172ecd372de7d144459831cfabf0496159a5defd0f2ecb8f5124f1717af"), 129 } },
745 { MerkleTreeId::NOTE_HASH_TREE,
746 { fr("0x2496ae3983b59733967ef32aecb041134d5f17bd2b040def30e699432dcc8967"), 1 } },
747 { MerkleTreeId::PUBLIC_DATA_TREE,
748 { fr("0x0278dcf9ff541da255ee722aecfad849b66af0d42c2924d949b5a509f2e1aec9"), 129 } },
749 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
750 { fr("0x149be5d1559bbefa0006c5e55ed982c43a1db53848e2f59385523d0c40d74a94"), 1 } },
751 };
752
753 auto sync = [&]() {
754 return ws.sync_block(block_state_ref,
755 fr(1),
756 { 42 },
757 { 43 },
758 { NullifierLeafValue(144) },
759 // this should be rejected because public data tree root will not match the state ref above
760 // (state ref above is for slot[145]=1, not slot[145]=2)
761 { { PublicDataLeafValue(145, 2) } });
762 };
763
764 EXPECT_THROW(sync(), std::runtime_error);
765}
766
767TEST_F(WorldStateTest, SyncEmptyBlock)
768{
769 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
771 ws.sync_block(block_state_ref, fr(1), {}, {}, {}, {});
773 EXPECT_EQ(block_state_ref, after_sync);
774
776 ws.find_leaf_indices<fr>(WorldStateRevision::committed(), MerkleTreeId::ARCHIVE, { fr(1) }, indices);
778 EXPECT_EQ(indices, expected);
779}
780
781TEST_F(WorldStateTest, ForkingAtBlock0SameState)
782{
783 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
784 auto fork_id = ws.create_fork(0);
785
786 assert_fork_state_unchanged(ws, fork_id, false);
787 assert_fork_state_unchanged(ws, fork_id, true);
788}
789
790TEST_F(WorldStateTest, ForkingAtBlock0AndAdvancingFork)
791{
792 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
793 auto fork_id = ws.create_fork(0);
794
795 auto canonical_archive_state_before = ws.get_tree_info(WorldStateRevision::uncommitted(), MerkleTreeId::ARCHIVE);
796 auto fork_archive_state_before = ws.get_tree_info(
798 .forkId = fork_id,
799 .includeUncommitted = true,
800 },
801 MerkleTreeId::ARCHIVE);
802
803 ws.append_leaves<bb::fr>(MerkleTreeId::ARCHIVE, { fr(1) }, fork_id);
804
805 auto canonical_archive_state_after = ws.get_tree_info(WorldStateRevision::uncommitted(), MerkleTreeId::ARCHIVE);
806 auto fork_archive_state_after = ws.get_tree_info(
808 .forkId = fork_id,
809 .includeUncommitted = true,
810 },
811 MerkleTreeId::ARCHIVE);
812
813 EXPECT_EQ(canonical_archive_state_after.meta, canonical_archive_state_before.meta);
814 EXPECT_EQ(fork_archive_state_before.meta, canonical_archive_state_before.meta);
815 EXPECT_NE(fork_archive_state_after.meta, fork_archive_state_before.meta);
816}
817
818TEST_F(WorldStateTest, ForkingAtBlock0AndAdvancingCanonicalState)
819{
820 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
821 auto fork_id = ws.create_fork(0);
822
823 auto canonical_archive_state_before = ws.get_tree_info(WorldStateRevision::uncommitted(), MerkleTreeId::ARCHIVE);
824 auto fork_archive_state_before_insert = ws.get_tree_info(
826 .forkId = fork_id,
827 .includeUncommitted = true,
828 },
829 MerkleTreeId::ARCHIVE);
830
831 // fork the state
832 ws.append_leaves<bb::fr>(MerkleTreeId::ARCHIVE, { fr(1) });
833 ws.append_leaves<bb::fr>(MerkleTreeId::ARCHIVE, { fr(2) }, fork_id);
834
835 auto canonical_archive_state_after_insert =
836 ws.get_tree_info(WorldStateRevision::uncommitted(), MerkleTreeId::ARCHIVE);
837 auto fork_archive_state_after_insert = ws.get_tree_info(
839 .forkId = fork_id,
840 .includeUncommitted = true,
841 },
842 MerkleTreeId::ARCHIVE);
843
844 EXPECT_EQ(fork_archive_state_before_insert.meta, canonical_archive_state_before.meta);
845
846 EXPECT_NE(canonical_archive_state_after_insert.meta, canonical_archive_state_before.meta);
847 EXPECT_NE(fork_archive_state_after_insert.meta, fork_archive_state_before_insert.meta);
848 EXPECT_NE(fork_archive_state_after_insert.meta, canonical_archive_state_after_insert.meta);
849
851 ws.commit(status);
852 auto canonical_archive_state_after_commit =
853 ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::ARCHIVE);
854 auto fork_archive_state_after_commit = ws.get_tree_info(
856 .forkId = fork_id,
857 .includeUncommitted = false,
858 },
859 MerkleTreeId::ARCHIVE);
860
861 // committed fork state should match the state before fork had been modified
862 EXPECT_EQ(fork_archive_state_after_commit.meta.size, fork_archive_state_before_insert.meta.size);
863 EXPECT_EQ(fork_archive_state_after_commit.meta.root, fork_archive_state_before_insert.meta.root);
864 // canonical state before commit should match state after commit
865 // EXPECT_EQ(canonical_archive_state_after_commit.meta, canonical_archive_state_after_insert.meta);
866 EXPECT_EQ(canonical_archive_state_after_commit.meta.root, canonical_archive_state_after_insert.meta.root);
867 EXPECT_EQ(canonical_archive_state_after_commit.meta.size, canonical_archive_state_after_insert.meta.size);
868
869 // canonical should have value 1 as the first leaf (committed state)
870 assert_leaf_value<bb::fr>(ws, WorldStateRevision{ .includeUncommitted = false }, MerkleTreeId::ARCHIVE, 1, 1);
871 // fork should still have value 2 as the first leaf (uncommitted)
872 assert_leaf_value<bb::fr>(
873 ws, WorldStateRevision{ .forkId = fork_id, .includeUncommitted = true }, MerkleTreeId::ARCHIVE, 1, 2);
874}
875
876TEST_F(WorldStateTest, BuildsABlockInAFork)
877{
878 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
879 auto fork_id = ws.create_fork(0);
880
881 ws.append_leaves<bb::fr>(MerkleTreeId::NOTE_HASH_TREE, { 42 }, fork_id);
882 ws.append_leaves<bb::fr>(MerkleTreeId::L1_TO_L2_MESSAGE_TREE, { 43 }, fork_id);
883 ws.batch_insert_indexed_leaves<NullifierLeafValue>(MerkleTreeId::NULLIFIER_TREE, { { 129 } }, 0, fork_id);
884 ws.batch_insert_indexed_leaves<PublicDataLeafValue>(MerkleTreeId::PUBLIC_DATA_TREE, { { 129, 1 } }, 0, fork_id);
885
886 auto fork_state_ref = ws.get_state_reference(WorldStateRevision{ .forkId = fork_id, .includeUncommitted = true });
887
888 ws.update_archive(fork_state_ref, { 1 }, fork_id);
889 auto fork_archive =
890 ws.get_tree_info(WorldStateRevision{ .forkId = fork_id, .includeUncommitted = true }, MerkleTreeId::ARCHIVE);
891
892 ws.delete_fork(fork_id);
893
894 ws.sync_block(fork_state_ref, { 1 }, { 42 }, { 43 }, { { 129 } }, { { { 129, 1 } } });
895
896 EXPECT_EQ(fork_state_ref, ws.get_state_reference(WorldStateRevision::committed()));
897}
898
899TEST_F(WorldStateTest, GetBlockForIndex)
900{
901 WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
902 // bb::fr block_hash(1);
903 StateReference block_state_ref = {
904 { MerkleTreeId::NULLIFIER_TREE,
905 { fr("0x1a8a3172ecd372de7d144459831cfabf0496159a5defd0f2ecb8f5124f1717af"), 129 } },
906 { MerkleTreeId::NOTE_HASH_TREE,
907 { fr("0x2496ae3983b59733967ef32aecb041134d5f17bd2b040def30e699432dcc8967"), 1 } },
908 { MerkleTreeId::PUBLIC_DATA_TREE,
909 { fr("0x0278dcf9ff541da255ee722aecfad849b66af0d42c2924d949b5a509f2e1aec9"), 129 } },
910 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
911 { fr("0x149be5d1559bbefa0006c5e55ed982c43a1db53848e2f59385523d0c40d74a94"), 1 } },
912 };
913
915 block_state_ref, fr(1), { 42 }, { 43 }, { NullifierLeafValue(144) }, { { PublicDataLeafValue(145, 1) } });
916 WorldStateStatusSummary expected{ 1, 0, 1, true };
917 EXPECT_EQ(status.summary, expected);
918
920
922 MerkleTreeId::NULLIFIER_TREE,
923 MerkleTreeId::NOTE_HASH_TREE,
924 MerkleTreeId::PUBLIC_DATA_TREE,
925 MerkleTreeId::L1_TO_L2_MESSAGE_TREE,
926 };
927
928 for (const auto& id : tree_ids) {
931 WorldStateRevision::committed(), id, { state_ref[id].second - 1 }, blockNumbers);
932
933 EXPECT_EQ(blockNumbers.size(), 1);
934 EXPECT_TRUE(blockNumbers[0].has_value());
935 EXPECT_EQ(blockNumbers[0].value(), 1);
936 }
937}
#define ARCHIVE_HEIGHT
#define L1_TO_L2_MSG_TREE_HEIGHT
#define GENESIS_ARCHIVE_ROOT
#define NULLIFIER_TREE_HEIGHT
#define GENESIS_BLOCK_HEADER_HASH
#define NOTE_HASH_TREE_HEIGHT
#define PUBLIC_DATA_TREE_HEIGHT
void TearDown() override
void SetUp() override
static std::string data_dir
uint32_t initial_header_generator_point
std::unordered_map< MerkleTreeId, index_t > tree_prefill
std::unordered_map< MerkleTreeId, uint32_t > tree_heights
Implements a parallelized batch insertion indexed tree Accepts template argument of the type of store...
Holds the Merkle trees responsible for storing the state of the Aztec protocol.
BatchInsertionResult< T > batch_insert_indexed_leaves(MerkleTreeId tree_id, const std::vector< T > &leaves, uint32_t subtree_depth, Fork::Id fork_id=CANONICAL_FORK_ID)
Batch inserts a set of leaves into an indexed Merkle Tree.
void append_leaves(MerkleTreeId tree_id, const std::vector< T > &leaves, Fork::Id fork_id=CANONICAL_FORK_ID)
Appends a set of leaves to an existing Merkle Tree.
StateReference get_initial_state_reference() const
Gets the initial state reference for all the trees in the world state.
std::optional< crypto::merkle_tree::IndexedLeaf< T > > get_indexed_leaf(const WorldStateRevision &revision, MerkleTreeId tree_id, index_t leaf_index) const
Get the leaf preimage object.
crypto::merkle_tree::TreeMetaResponse get_tree_info(const WorldStateRevision &revision, MerkleTreeId tree_id) const
Get tree metadata for a particular tree.
std::pair< bool, std::string > commit(WorldStateStatusFull &status)
Commits the current state of the world state.
void get_block_numbers_for_leaf_indices(const WorldStateRevision &revision, MerkleTreeId tree_id, const std::vector< index_t > &leafIndices, std::vector< std::optional< block_number_t > > &blockNumbers) const
StateReference get_state_reference(const WorldStateRevision &revision) const
Gets the state reference for all the trees in the world state.
void update_public_data(const crypto::merkle_tree::PublicDataLeafValue &new_value, Fork::Id fork_id=CANONICAL_FORK_ID)
Updates a leaf in an existing Merkle Tree.
void rollback()
Rolls back any uncommitted changes made to the world state.
WorldStateStatusFull sync_block(const StateReference &block_state_ref, const bb::fr &block_header_hash, const std::vector< bb::fr > &notes, const std::vector< bb::fr > &l1_to_l2_messages, const std::vector< crypto::merkle_tree::NullifierLeafValue > &nullifiers, const std::vector< crypto::merkle_tree::PublicDataLeafValue > &public_writes)
void delete_fork(const uint64_t &forkId)
uint64_t create_fork(const std::optional< block_number_t > &blockNumber)
crypto::merkle_tree::fr_sibling_path get_sibling_path(const WorldStateRevision &revision, MerkleTreeId tree_id, index_t leaf_index) const
Get the sibling path object for a leaf in a tree.
void find_leaf_indices(const WorldStateRevision &revision, MerkleTreeId tree_id, const std::vector< T > &leaves, std::vector< std::optional< index_t > > &indices, index_t start_index=0) const
Finds the index of a leaf in a tree.
std::optional< T > get_leaf(const WorldStateRevision &revision, MerkleTreeId tree_id, index_t leaf_index) const
Gets the value of a leaf in a tree.
crypto::merkle_tree::GetLowIndexedLeafResponse find_low_leaf_index(const WorldStateRevision &revision, MerkleTreeId tree_id, const bb::fr &leaf_key) const
Finds the leaf that would have its nextIdx/nextValue fields modified if the target leaf were to be in...
void update_archive(const StateReference &block_state_ref, const bb::fr &block_header_hash, Fork::Id fork_id=CANONICAL_FORK_ID)
Updates the archive tree with a new block.
void info(Args... args)
Definition log.hpp:75
NullifierTreeLeafPreimage low_leaf
void hash(State &state) noexcept
std::string random_temp_directory()
Definition fixtures.hpp:43
std::unordered_map< MerkleTreeId, TreeStateReference > StateReference
Definition types.hpp:32
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static fr hash_pair(const fr &lhs, const fr &rhs)
Definition hash.hpp:33
static fr hash(const std::vector< fr > &inputs)
Definition hash.hpp:28
static constexpr field zero()
static WorldStateRevision committed()
Definition types.hpp:41
static WorldStateRevision uncommitted()
Definition types.hpp:42
WorldStateStatusSummary summary
Definition types.hpp:209
void assert_fork_state_unchanged(const WorldState &ws, Fork::Id forkId, bool includeUncommitted, const std::vector< MerkleTreeId > &trees={ MerkleTreeId::NULLIFIER_TREE, MerkleTreeId::NOTE_HASH_TREE, MerkleTreeId::PUBLIC_DATA_TREE, MerkleTreeId::L1_TO_L2_MESSAGE_TREE, MerkleTreeId::ARCHIVE })
void assert_leaf_value(const WorldState &ws, WorldStateRevision revision, MerkleTreeId tree_id, index_t leaf_index, const Leaf &expected_value)
void assert_leaf_index(const WorldState &ws, WorldStateRevision revision, MerkleTreeId tree_id, const Leaf &value, index_t expected_index)
void assert_tree_size(const WorldState &ws, WorldStateRevision revision, MerkleTreeId tree_id, size_t expected_size)
void assert_sibling_path(const WorldState &ws, WorldStateRevision revision, MerkleTreeId tree_id, fr root, fr leaf, index_t index)
void assert_leaf_exists(const WorldState &ws, WorldStateRevision revision, MerkleTreeId tree_id, const Leaf &expected_value, bool exists)
void assert_leaf_status(const WorldState &ws, WorldStateRevision revision, MerkleTreeId tree_id, index_t leaf_index, bool exists)