Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
world_state.cpp
Go to the documentation of this file.
2#include "barretenberg/aztec/aztec_constants.hpp"
17#include <array>
18#include <atomic>
19#include <cstddef>
20#include <cstdint>
21#include <filesystem>
22#include <memory>
23#include <mutex>
24#include <optional>
25#include <ostream>
26#include <stdexcept>
27#include <tuple>
28#include <unordered_map>
29#include <utility>
30#include <variant>
31
32namespace bb::world_state {
33
34using namespace bb::crypto::merkle_tree;
35
36WorldState::WorldState(uint64_t thread_pool_size,
37 const std::string& data_dir,
39 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
40 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
41 const std::vector<PublicDataLeafValue>& prefilled_public_data,
42 const std::vector<bb::fr>& prefilled_nullifiers,
43 uint32_t initial_header_generator_point,
44 uint64_t genesis_timestamp,
45 bool ephemeral)
46 : _workers(std::make_shared<ThreadPool>(thread_pool_size))
47 , _tree_heights(tree_heights)
48 , _initial_tree_size(tree_prefill)
49 , _forkId(CANONICAL_FORK_ID)
50 , _initial_header_generator_point(initial_header_generator_point)
51 , _genesis_timestamp(genesis_timestamp)
52{
53 // We set the max readers to be high, at least the number of given threads or the default if higher
54 uint64_t maxReaders = std::max(thread_pool_size, DEFAULT_MIN_NUMBER_OF_READERS);
55 create_canonical_fork(data_dir, map_size, prefilled_public_data, prefilled_nullifiers, maxReaders, ephemeral);
56 try {
58 } catch (std::exception& e) {
59 // We don't do anything with this. If any attept to re-sync failed it will be picked up later in TS land
60 }
61}
62
63WorldState::WorldState(uint64_t thread_pool_size,
64 const std::string& data_dir,
66 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
67 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
68 uint32_t initial_header_generator_point,
69 uint64_t genesis_timestamp,
70 bool ephemeral)
71 : WorldState::WorldState(thread_pool_size,
72 data_dir,
73 map_size,
74 tree_heights,
75 tree_prefill,
76 std::vector<PublicDataLeafValue>(),
77 std::vector<bb::fr>(),
78 initial_header_generator_point,
79 genesis_timestamp,
80 ephemeral)
81{}
82
83WorldState::WorldState(uint64_t thread_pool_size,
84 const std::string& data_dir,
85 uint64_t map_size,
86 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
87 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
88 const std::vector<PublicDataLeafValue>& prefilled_public_data,
89 const std::vector<bb::fr>& prefilled_nullifiers,
90 uint32_t initial_header_generator_point,
91 uint64_t genesis_timestamp,
92 bool ephemeral)
93 : WorldState(thread_pool_size,
94 data_dir,
95 {
96 { MerkleTreeId::NULLIFIER_TREE, map_size },
98 { MerkleTreeId::ARCHIVE, map_size },
99 { MerkleTreeId::NOTE_HASH_TREE, map_size },
101 },
102 tree_heights,
103 tree_prefill,
104 prefilled_public_data,
105 prefilled_nullifiers,
106 initial_header_generator_point,
107 genesis_timestamp,
108 ephemeral)
109{}
110
111WorldState::WorldState(uint64_t thread_pool_size,
112 const std::string& data_dir,
113 uint64_t map_size,
114 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
115 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
116 uint32_t initial_header_generator_point,
117 uint64_t genesis_timestamp,
118 bool ephemeral)
119 : WorldState(thread_pool_size,
120 data_dir,
121 map_size,
122 tree_heights,
123 tree_prefill,
124 std::vector<PublicDataLeafValue>(),
125 std::vector<bb::fr>(),
126 initial_header_generator_point,
127 genesis_timestamp,
128 ephemeral)
129{}
130
131void WorldState::create_canonical_fork(const std::string& dataDir,
133 const std::vector<PublicDataLeafValue>& prefilled_public_data,
134 const std::vector<bb::fr>& prefilled_nullifiers,
135 uint64_t maxReaders,
136 bool ephemeral)
137{
138 // create the underlying stores
139 auto createStore = [&](MerkleTreeId id) {
140 auto name = getMerkleTreeName(id);
141 std::filesystem::path directory = dataDir;
142 directory /= name;
143 std::filesystem::create_directories(directory);
144 return std::make_shared<LMDBTreeStore>(directory, name, dbSize.at(id), maxReaders, ephemeral);
145 };
148 createStore(MerkleTreeId::ARCHIVE),
149 createStore(MerkleTreeId::NOTE_HASH_TREE),
151
153 fork->_forkId = _forkId++;
154 {
155 uint32_t levels = _tree_heights.at(MerkleTreeId::NULLIFIER_TREE);
157 std::vector<NullifierLeafValue> prefilled_nullifier_leaves;
158 prefilled_nullifier_leaves.reserve(prefilled_nullifiers.size());
159 for (const auto& nullifier : prefilled_nullifiers) {
160 prefilled_nullifier_leaves.emplace_back(nullifier);
161 }
164 auto tree =
165 std::make_unique<NullifierTree>(std::move(store), _workers, initial_size, prefilled_nullifier_leaves);
166 fork->_trees.insert({ MerkleTreeId::NULLIFIER_TREE, TreeWithStore(std::move(tree)) });
167 }
168 {
169 uint32_t levels = _tree_heights.at(MerkleTreeId::NOTE_HASH_TREE);
170 auto store = std::make_unique<FrStore>(
172 auto tree = std::make_unique<FrTree>(std::move(store), _workers);
173 fork->_trees.insert({ MerkleTreeId::NOTE_HASH_TREE, TreeWithStore(std::move(tree)) });
174 }
175 {
176 uint32_t levels = _tree_heights.at(MerkleTreeId::PUBLIC_DATA_TREE);
180 auto tree = std::make_unique<PublicDataTree>(std::move(store), _workers, initial_size, prefilled_public_data);
181 fork->_trees.insert({ MerkleTreeId::PUBLIC_DATA_TREE, TreeWithStore(std::move(tree)) });
182 }
183 {
185 auto store = std::make_unique<FrStore>(
187 auto tree = std::make_unique<FrTree>(std::move(store), _workers);
188 fork->_trees.insert({ MerkleTreeId::L1_TO_L2_MESSAGE_TREE, TreeWithStore(std::move(tree)) });
189 }
190 {
191 uint32_t levels = _tree_heights.at(MerkleTreeId::ARCHIVE);
192 std::vector<bb::fr> initial_values{ compute_initial_block_header_hash(
196 auto store = std::make_unique<FrStore>(
198 auto tree = std::make_unique<FrTree>(std::move(store), _workers, initial_values);
199 fork->_trees.insert({ MerkleTreeId::ARCHIVE, TreeWithStore(std::move(tree)) });
200 }
201 _forks[fork->_forkId] = fork;
202}
203
204void WorldState::copy_stores(const std::string& dstPath, bool compact) const
205{
206 auto copyStore = [&](const LMDBTreeStore::SharedPtr& store) {
207 std::filesystem::path directory = dstPath;
208 directory /= store->get_name();
209 std::filesystem::create_directories(directory);
210 store->copy_store(directory, compact);
211 };
212
213 std::for_each(_persistentStores->begin(), _persistentStores->end(), copyStore);
214}
215
216Fork::SharedPtr WorldState::retrieve_fork(const uint64_t& forkId) const
217{
218 std::unique_lock lock(mtx);
219 auto it = _forks.find(forkId);
220 if (it == _forks.end()) {
221 throw std::runtime_error("Fork not found");
222 }
223 return it->second;
224}
226{
227 block_number_t blockNumberForFork = 0;
228 if (!blockNumber.has_value()) {
229 // we are forking at latest
230 WorldStateRevision revision{ .forkId = CANONICAL_FORK_ID, .includeUncommitted = false };
232 blockNumberForFork = archiveMeta.meta.unfinalizedBlockHeight;
233 } else {
234 blockNumberForFork = blockNumber.value();
235 }
236 Fork::SharedPtr fork = create_new_fork(blockNumberForFork);
237 std::unique_lock lock(mtx);
238 uint64_t forkId = _forkId++;
239 fork->_forkId = forkId;
240 _forks[forkId] = fork;
241 return forkId;
242}
243
245{
246 // capture the shared pointers outside of the lock scope so we are not under the lock when the objects are destroyed
248 {
249 std::unique_lock lock(mtx);
250 for (auto it = _forks.begin(); it != _forks.end();) {
251 if (it->second->_blockNumber == blockNumber) {
252 forks.push_back(it->second);
253 it = _forks.erase(it);
254
255 } else {
256 it++;
257 }
258 }
259 }
260}
261
262void WorldState::delete_fork(const uint64_t& forkId)
263{
264 if (forkId == 0) {
265 throw std::runtime_error("Unable to delete canonical fork");
266 }
267 // Retrieving the shared pointer here means we throw if the fork is not available, it also means we are not under a
268 // lock when we destroy the object
269 Fork::SharedPtr fork = retrieve_fork(forkId);
270 {
271 std::unique_lock lock(mtx);
272 _forks.erase(forkId);
273 }
274}
275
277{
279 fork->_blockNumber = blockNumber;
280 {
281 uint32_t levels = _tree_heights.at(MerkleTreeId::NULLIFIER_TREE);
284 getMerkleTreeName(MerkleTreeId::NULLIFIER_TREE), levels, blockNumber, _persistentStores->nullifierStore);
285 auto tree = std::make_unique<NullifierTree>(std::move(store), _workers, initial_size);
286 fork->_trees.insert({ MerkleTreeId::NULLIFIER_TREE, TreeWithStore(std::move(tree)) });
287 }
288 {
289 uint32_t levels = _tree_heights.at(MerkleTreeId::NOTE_HASH_TREE);
290 auto store = std::make_unique<FrStore>(
291 getMerkleTreeName(MerkleTreeId::NOTE_HASH_TREE), levels, blockNumber, _persistentStores->noteHashStore);
292 auto tree = std::make_unique<FrTree>(std::move(store), _workers);
293 fork->_trees.insert({ MerkleTreeId::NOTE_HASH_TREE, TreeWithStore(std::move(tree)) });
294 }
295 {
296 uint32_t levels = _tree_heights.at(MerkleTreeId::PUBLIC_DATA_TREE);
299 getMerkleTreeName(MerkleTreeId::PUBLIC_DATA_TREE), levels, blockNumber, _persistentStores->publicDataStore);
300 auto tree = std::make_unique<PublicDataTree>(std::move(store), _workers, initial_size);
301 fork->_trees.insert({ MerkleTreeId::PUBLIC_DATA_TREE, TreeWithStore(std::move(tree)) });
302 }
303 {
306 levels,
307 blockNumber,
308 _persistentStores->messageStore);
309 auto tree = std::make_unique<FrTree>(std::move(store), _workers);
310 fork->_trees.insert({ MerkleTreeId::L1_TO_L2_MESSAGE_TREE, TreeWithStore(std::move(tree)) });
311 }
312 {
313 uint32_t levels = _tree_heights.at(MerkleTreeId::ARCHIVE);
314 auto store = std::make_unique<FrStore>(
315 getMerkleTreeName(MerkleTreeId::ARCHIVE), levels, blockNumber, _persistentStores->archiveStore);
316 auto tree = std::make_unique<FrTree>(std::move(store), _workers);
317 fork->_trees.insert({ MerkleTreeId::ARCHIVE, TreeWithStore(std::move(tree)) });
318 }
319 return fork;
320}
321
323{
324 Fork::SharedPtr fork = retrieve_fork(revision.forkId);
325 return std::visit(
326 [=](auto&& wrapper) {
327 Signal signal(1);
329
330 auto callback = [&](TypedResponse<TreeMetaResponse>& meta) {
331 local = std::move(meta);
332 signal.signal_level(0);
333 };
334
335 if (revision.is_historical()) {
336 wrapper.tree->get_meta_data(revision.blockNumber, revision.includeUncommitted, callback);
337 } else {
338 wrapper.tree->get_meta_data(revision.includeUncommitted, callback);
339 }
340 signal.wait_for_level(0);
341
342 if (!local.success) {
343 throw std::runtime_error(local.message);
344 }
345 return local.inner;
346 },
347 fork->_trees.at(tree_id));
348}
349
351{
352 Fork::SharedPtr fork = retrieve_fork(revision.forkId);
353
357 };
358
359 Signal signal(static_cast<uint32_t>(tree_ids.size()));
360 std::mutex mutex;
362
363 for (auto id : tree_ids) {
364 const auto& tree = fork->_trees.at(id);
365 auto callback = [&signal, &local, &mutex, id](TypedResponse<TreeMetaResponse>& meta) {
366 {
367 std::lock_guard<std::mutex> lock(mutex);
368 local[id] = std::move(meta);
369 }
370 signal.signal_decrement();
371 };
372 std::visit(
373 [&callback, &revision](auto&& wrapper) {
374 if (revision.is_historical()) {
375 wrapper.tree->get_meta_data(revision.blockNumber, revision.includeUncommitted, callback);
376 } else {
377 wrapper.tree->get_meta_data(revision.includeUncommitted, callback);
378 }
379 },
380 tree);
381 }
382
383 signal.wait_for_level(0);
384
385 for (auto tree_id : tree_ids) {
386 auto& m = local[tree_id];
387 if (!m.success) {
388 throw std::runtime_error(m.message);
389 }
390 responses[tree_id] = std::move(m.inner.meta);
391 }
392}
393
395{
396 return get_state_reference(revision, retrieve_fork(revision.forkId));
397}
398
405
407 Fork::SharedPtr fork,
408 bool initial_state)
409{
410 if (fork->_forkId != revision.forkId) {
411 throw std::runtime_error("Fork does not match revision");
412 }
413
419 };
420
421 Signal signal(static_cast<uint32_t>(tree_ids.size()));
422 StateReference state_reference;
424 std::mutex state_ref_mutex;
425
426 for (auto id : tree_ids) {
427 const auto& tree = fork->_trees.at(id);
428 auto callback = [&signal, &local, &state_ref_mutex, id](TypedResponse<TreeMetaResponse>& meta) {
429 {
430 std::lock_guard<std::mutex> lock(state_ref_mutex);
431 local[id] = std::move(meta);
432 }
433 signal.signal_decrement();
434 };
435 std::visit(
436 [&callback, &revision](auto&& wrapper) {
437 if (revision.is_historical()) {
438 wrapper.tree->get_meta_data(revision.blockNumber, revision.includeUncommitted, callback);
439 } else {
440 wrapper.tree->get_meta_data(revision.includeUncommitted, callback);
441 }
442 },
443 tree);
444 }
445
446 signal.wait_for_level(0);
447
448 for (auto tree_id : tree_ids) {
449 auto& m = local[tree_id];
450 if (!m.success) {
451 throw std::runtime_error(m.message);
452 }
453 if (initial_state) {
454 state_reference[tree_id] = std::make_pair(m.inner.meta.initialRoot, m.inner.meta.initialSize);
455 continue;
456 }
457 state_reference[tree_id] = std::make_pair(m.inner.meta.root, m.inner.meta.size);
458 }
459
460 return state_reference;
461}
462
464 MerkleTreeId tree_id,
465 index_t leaf_index) const
466{
467 Fork::SharedPtr fork = retrieve_fork(revision.forkId);
468
469 return std::visit(
470 [leaf_index, revision](auto&& wrapper) {
471 Signal signal(1);
473
474 auto callback = [&signal, &local](TypedResponse<GetSiblingPathResponse>& response) {
475 local = std::move(response);
476 signal.signal_level(0);
477 };
478
479 if (revision.is_historical()) {
480 wrapper.tree->get_sibling_path(leaf_index, revision.blockNumber, callback, revision.includeUncommitted);
481 } else {
482 wrapper.tree->get_sibling_path(leaf_index, callback, revision.includeUncommitted);
483 }
484 signal.wait_for_level(0);
485
486 if (!local.success) {
487 throw std::runtime_error(local.message);
488 }
489 return local.inner.path;
490 },
491 fork->_trees.at(tree_id));
492}
493
495 MerkleTreeId tree_id,
496 const std::vector<index_t>& leafIndices,
497 std::vector<std::optional<block_number_t>>& blockNumbers) const
498{
499 Fork::SharedPtr fork = retrieve_fork(revision.forkId);
500
501 std::visit(
502 [&leafIndices, revision, &blockNumbers](auto&& wrapper) {
503 Signal signal(1);
505
506 auto callback = [&signal, &local](TypedResponse<BlockForIndexResponse>& response) {
507 local = std::move(response);
508 signal.signal_level();
509 };
510
511 if (revision.is_historical()) {
512 wrapper.tree->find_block_numbers(leafIndices, revision.blockNumber, callback);
513 } else {
514 wrapper.tree->find_block_numbers(leafIndices, callback);
515 }
516 signal.wait_for_level(0);
517
518 if (!local.success) {
519 throw std::runtime_error(local.message);
520 }
521 blockNumbers = std::move(local.inner.blockNumbers);
522 },
523 fork->_trees.at(tree_id));
524}
525
527{
528 Fork::SharedPtr fork = retrieve_fork(fork_id);
529 if (const auto* wrapper =
531 Signal signal;
532 wrapper->tree->add_or_update_value(
533 new_value,
535 signal.wait_for_level();
536 } else {
537 throw std::runtime_error("Invalid tree type for PublicDataTree");
538 }
539}
540
541void WorldState::update_archive(const StateReference& block_state_ref,
542 const bb::fr& block_header_hash,
543 Fork::Id fork_id)
544{
545 if (is_same_state_reference(WorldStateRevision{ .forkId = fork_id, .includeUncommitted = true }, block_state_ref)) {
546 append_leaves<fr>(MerkleTreeId::ARCHIVE, { block_header_hash }, fork_id);
547 } else {
548 throw std::runtime_error("Can't update archive tree: Block state does not match world state");
549 }
550}
551
553{
554 // NOTE: the calling code is expected to ensure no other reads or writes happen during commit
556 std::atomic_bool success = true;
557 std::string message;
558 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
559
560 {
563 status.dbStats.nullifierTreeStats, signal, *wrapper.tree, success, message, status.meta.nullifierTreeMeta);
564 }
565 {
568 signal,
569 *wrapper.tree,
570 success,
571 message,
572 status.meta.publicDataTreeMeta);
573 }
574
575 {
576 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::NOTE_HASH_TREE));
578 status.dbStats.noteHashTreeStats, signal, *wrapper.tree, success, message, status.meta.noteHashTreeMeta);
579 }
580
581 {
584 status.dbStats.messageTreeStats, signal, *wrapper.tree, success, message, status.meta.messageTreeMeta);
585 }
586
587 {
588 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::ARCHIVE));
590 status.dbStats.archiveTreeStats, signal, *wrapper.tree, success, message, status.meta.archiveTreeMeta);
591 }
592
593 signal.wait_for_level(0);
594 return std::make_pair(success.load(), message);
595}
596
598{
599 // NOTE: the calling code is expected to ensure no other reads or writes happen during rollback
601 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
602 for (auto& [id, tree] : fork->_trees) {
603 std::visit(
604 [&signal](auto&& wrapper) {
605 wrapper.tree->rollback([&signal](const Response&) { signal.signal_decrement(); });
606 },
607 tree);
608 }
609 signal.wait_for_level();
610}
611
613 const bb::fr& block_header_hash,
614 const std::vector<bb::fr>& notes,
615 const std::vector<bb::fr>& l1_to_l2_messages,
618 const std::optional<bb::fr>& expected_archive_root,
619 const std::optional<bb::fr>& expected_previous_archive_root)
620{
622 rollback();
623
624 // The archive tree is an append-only accumulator of block header hashes, so a single bad leaf (e.g. from a
625 // mishandled reorg) is never self-corrected: every later root stays noncanonical while the other state trees
626 // can re-converge from block effects. The checks further down only verify the appended leaf is the tip and
627 // that the four non-archive trees match the block state reference — neither catches a divergent archive root.
628 // So verify the local archive root against canonical both before appending (the parent root must equal the
629 // block's lastArchive) and after (the resulting root must equal the block's archive), failing before commit
630 // so the divergence is never persisted.
631 if (expected_previous_archive_root.has_value()) {
632 const bb::fr actual_previous_archive_root =
634 if (actual_previous_archive_root != expected_previous_archive_root.value()) {
635 throw std::runtime_error(
636 format("Can't sync block: local archive root ",
637 actual_previous_archive_root,
638 " does not match the block's previous archive root ",
639 expected_previous_archive_root.value(),
640 "; world state has diverged from the canonical chain and must be resynced"));
641 }
642 }
643
645 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
646 std::atomic_bool success = true;
647 std::string err_message;
648 auto decr = [&signal, &success, &err_message](const auto& resp) {
649 // take the first error
650 bool expected = true;
651 if (!resp.success && success.compare_exchange_strong(expected, false)) {
652 err_message = resp.message;
653 }
654
655 signal.signal_decrement();
656 };
657
658 {
660 NullifierTree::AddCompletionCallback completion = [&](const auto& resp) -> void {
661 // take the first error
662 bool expected = true;
663 if (!resp.success && success.compare_exchange_strong(expected, false)) {
664 err_message = resp.message;
665 }
666
667 signal.signal_decrement();
668 };
669 wrapper.tree->add_or_update_values(nullifiers, 0, completion);
670 }
671
672 {
673 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::NOTE_HASH_TREE));
674 wrapper.tree->add_values(notes, decr);
675 }
676
677 {
679 wrapper.tree->add_values(l1_to_l2_messages, decr);
680 }
681
682 {
683 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::ARCHIVE));
684 wrapper.tree->add_value(block_header_hash, decr);
685 }
686
687 {
689 PublicDataTree::AddCompletionCallback completion = [&](const auto& resp) -> void {
690 // take the first error
691 bool expected = true;
692 if (!resp.success && success.compare_exchange_strong(expected, false)) {
693 err_message = resp.message;
694 }
695
696 signal.signal_decrement();
697 };
698 wrapper.tree->add_or_update_values_sequentially(public_writes, completion);
699 }
700
701 signal.wait_for_level();
702
703 // Check resulting state and commit if successful
705 try {
706 if (!success) {
707 throw std::runtime_error("Failed to sync block: " + err_message);
708 }
709
710 if (!is_archive_tip(WorldStateRevision::uncommitted(), block_header_hash)) {
711 throw std::runtime_error("Can't synch block: block header hash is not the tip of the archive tree");
712 }
713
715 throw std::runtime_error("Can't synch block: block state does not match world state");
716 }
717
718 // The archive tree is not part of the block state reference (see is_same_state_reference), so verify the
719 // resulting archive root against the canonical block's archive root explicitly.
720 if (expected_archive_root.has_value()) {
721 const bb::fr actual_archive_root =
723 if (actual_archive_root != expected_archive_root.value()) {
724 throw std::runtime_error(
725 format("Can't sync block: resulting archive root ",
726 actual_archive_root,
727 " does not match the block's archive root ",
728 expected_archive_root.value(),
729 "; world state has diverged from the canonical chain and must be resynced"));
730 }
731 }
732
734 if (!result.first) {
735 throw std::runtime_error(result.second);
736 }
737 } catch (const std::exception& e) {
738 // We failed, rollback any uncommitted state before leaving
739 rollback();
740 throw;
741 }
742
743 // Success return the status
745 return status;
746}
747
749 MerkleTreeId tree_id,
750 const bb::fr& leaf_key) const
751{
752 Fork::SharedPtr fork = retrieve_fork(revision.forkId);
753 Signal signal;
755 auto callback = [&signal, &low_leaf_info](TypedResponse<GetLowIndexedLeafResponse>& response) {
756 low_leaf_info = std::move(response);
757 signal.signal_level();
758 };
759
760 if (const auto* wrapper = std::get_if<TreeWithStore<NullifierTree>>(&fork->_trees.at(tree_id))) {
761 if (revision.is_historical()) {
762 wrapper->tree->find_low_leaf(leaf_key, revision.blockNumber, revision.includeUncommitted, callback);
763 } else {
764 wrapper->tree->find_low_leaf(leaf_key, revision.includeUncommitted, callback);
765 }
766
767 } else if (const auto* wrapper = std::get_if<TreeWithStore<PublicDataTree>>(&fork->_trees.at(tree_id))) {
768 if (revision.is_historical()) {
769 wrapper->tree->find_low_leaf(leaf_key, revision.blockNumber, revision.includeUncommitted, callback);
770 } else {
771 wrapper->tree->find_low_leaf(leaf_key, revision.includeUncommitted, callback);
772 }
773
774 } else {
775 throw std::runtime_error("Invalid tree type for find_low_leaf");
776 }
777
778 signal.wait_for_level();
779
780 if (!low_leaf_info.success) {
781 throw std::runtime_error(low_leaf_info.message);
782 }
783 return low_leaf_info.inner;
784}
785
787{
788 // This will throw if it fails
789 set_finalized_block(toBlockNumber);
791 get_status_summary(status);
792 return status;
793}
795{
796 // Ensure no uncommitted state
797 rollback();
798
799 WorldStateRevision revision{ .forkId = CANONICAL_FORK_ID, .includeUncommitted = false };
801 get_all_tree_info(revision, responses);
802
803 // Get the set of unfinalized block numbers and unwind to the target block
804 std::array<block_number_t, NUM_TREES> unfinalizedBlockNumbers{
805 responses[NULLIFIER_TREE].unfinalizedBlockHeight,
806 responses[NOTE_HASH_TREE].unfinalizedBlockHeight,
807 responses[PUBLIC_DATA_TREE].unfinalizedBlockHeight,
808 responses[L1_TO_L2_MESSAGE_TREE].unfinalizedBlockHeight,
809 responses[ARCHIVE].unfinalizedBlockHeight
810 };
811
812 auto* const it = std::max_element(std::begin(unfinalizedBlockNumbers), std::end(unfinalizedBlockNumbers));
813 block_number_t highestUnfinalizedBlock = *it;
814
815 if (toBlockNumber >= highestUnfinalizedBlock) {
816 throw std::runtime_error(format("Unable to unwind blocks to block number ",
817 toBlockNumber,
818 ", current pending block ",
819 highestUnfinalizedBlock));
820 }
821
823 for (block_number_t blockNumber = highestUnfinalizedBlock; blockNumber > toBlockNumber; blockNumber--) {
824 // This will throw if it fails
825 unwind_block(blockNumber, status);
826 }
828 return status;
829}
830
832{
833 WorldStateRevision revision{ .forkId = CANONICAL_FORK_ID, .includeUncommitted = false };
835 get_all_tree_info(revision, responses);
836
837 // Get the set of historic block numbers and remove to the target block
838 std::array<block_number_t, NUM_TREES> historicalBlockNumbers{ responses[NULLIFIER_TREE].oldestHistoricBlock,
839 responses[NOTE_HASH_TREE].oldestHistoricBlock,
840 responses[PUBLIC_DATA_TREE].oldestHistoricBlock,
841 responses[L1_TO_L2_MESSAGE_TREE].oldestHistoricBlock,
842 responses[ARCHIVE].oldestHistoricBlock };
843 auto* const it = std::min_element(std::begin(historicalBlockNumbers), std::end(historicalBlockNumbers));
844 block_number_t oldestHistoricBlock = *it;
845 if (toBlockNumber <= oldestHistoricBlock) {
846 throw std::runtime_error(format("Unable to remove historical blocks to block number ",
847 toBlockNumber,
848 ", blocks not found. Current oldest block: ",
849 oldestHistoricBlock));
850 }
852 for (block_number_t blockNumber = oldestHistoricBlock; blockNumber < toBlockNumber; blockNumber++) {
853 // This will throw if it fails
854 remove_historical_block(blockNumber, status);
855 }
857 return status;
858}
859
861{
863 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
865 std::mutex mtx;
866 for (auto& [id, tree] : fork->_trees) {
867 std::visit(
868 [&signal, &local, blockNumber, id, &mtx](auto&& wrapper) {
869 wrapper.tree->finalize_block(blockNumber, [&signal, &local, &mtx, id](Response& resp) {
870 {
872 local[id] = std::move(resp);
873 }
874 signal.signal_decrement();
875 });
876 },
877 tree);
878 }
879 signal.wait_for_level();
880 for (auto& m : local) {
881 if (!m.success) {
882 throw std::runtime_error(m.message);
883 }
884 }
885 return true;
886}
888{
889 std::atomic_bool success = true;
890 std::string message;
892 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
893 {
896 signal,
897 *wrapper.tree,
898 success,
899 message,
900 status.meta.nullifierTreeMeta,
901 blockNumber);
902 }
903 {
906 signal,
907 *wrapper.tree,
908 success,
909 message,
911 blockNumber);
912 }
913
914 {
915 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::NOTE_HASH_TREE));
917 signal,
918 *wrapper.tree,
919 success,
920 message,
921 status.meta.noteHashTreeMeta,
922 blockNumber);
923 }
924
925 {
928 signal,
929 *wrapper.tree,
930 success,
931 message,
932 status.meta.messageTreeMeta,
933 blockNumber);
934 }
935
936 {
937 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::ARCHIVE));
939 signal,
940 *wrapper.tree,
941 success,
942 message,
943 status.meta.archiveTreeMeta,
944 blockNumber);
945 }
946 signal.wait_for_level();
947 if (!success) {
948 throw std::runtime_error(message);
949 }
950 remove_forks_for_block(blockNumber);
951 return true;
952}
954{
955 std::atomic_bool success = true;
956 std::string message;
958 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
959 {
962 signal,
963 *wrapper.tree,
964 success,
965 message,
966 status.meta.nullifierTreeMeta,
967 blockNumber);
968 }
969 {
972 signal,
973 *wrapper.tree,
974 success,
975 message,
977 blockNumber);
978 }
979
980 {
981 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::NOTE_HASH_TREE));
983 signal,
984 *wrapper.tree,
985 success,
986 message,
987 status.meta.noteHashTreeMeta,
988 blockNumber);
989 }
990
991 {
994 signal,
995 *wrapper.tree,
996 success,
997 message,
998 status.meta.messageTreeMeta,
999 blockNumber);
1000 }
1001
1002 {
1003 auto& wrapper = std::get<TreeWithStore<FrTree>>(fork->_trees.at(MerkleTreeId::ARCHIVE));
1005 signal,
1006 *wrapper.tree,
1007 success,
1008 message,
1009 status.meta.archiveTreeMeta,
1010 blockNumber);
1011 }
1012 signal.wait_for_level();
1013 if (!success) {
1014 throw std::runtime_error(message);
1015 }
1016 remove_forks_for_block(blockNumber);
1017 return true;
1018}
1019
1021 uint32_t generator_point,
1022 uint64_t genesis_timestamp)
1023{
1024 // NOTE: this hash operations needs to match the one in
1025 // noir-project/noir-protocol-circuits/crates/types/src/abis/block_header.nr
1027 { generator_point,
1028 // last archive - which, at genesis, is all 0s
1029 0, // root
1030 0, // next_available_leaf_index
1031 // state reference - the initial state for all the trees (accept the archive tree)
1032 initial_state_ref.at(MerkleTreeId::L1_TO_L2_MESSAGE_TREE).first,
1033 initial_state_ref.at(MerkleTreeId::L1_TO_L2_MESSAGE_TREE).second,
1034 initial_state_ref.at(MerkleTreeId::NOTE_HASH_TREE).first,
1035 initial_state_ref.at(MerkleTreeId::NOTE_HASH_TREE).second,
1036 initial_state_ref.at(MerkleTreeId::NULLIFIER_TREE).first,
1037 initial_state_ref.at(MerkleTreeId::NULLIFIER_TREE).second,
1038 initial_state_ref.at(MerkleTreeId::PUBLIC_DATA_TREE).first,
1039 initial_state_ref.at(MerkleTreeId::PUBLIC_DATA_TREE).second,
1040 0, // sponge_blob_hash
1041 0, // tx_effects_tree_root
1042 // global variables
1043 0, // chain_id
1044 0, // version
1045 0, // block_number
1046 0, // slot_number
1047 bb::fr(genesis_timestamp), // timestamp
1048 0, // coinbase
1049 0, // fee_recipient
1050 0, // gas_fee.fee_per_da_gas
1051 0, // gas_fee.fee_per_l2_gas
1052 // total fees
1053 0,
1054 // total mana used
1055 0 });
1056}
1057
1058bool WorldState::is_archive_tip(const WorldStateRevision& revision, const bb::fr& block_header_hash) const
1059{
1061
1062 try {
1063 find_leaf_indices<fr>(revision, MerkleTreeId::ARCHIVE, { block_header_hash }, indices);
1064 } catch (std::runtime_error&) {
1065 }
1066
1067 if (indices.empty() || !indices[0].has_value()) {
1068 return false;
1069 }
1070
1071 TreeMetaResponse archive_state = get_tree_info(revision, MerkleTreeId::ARCHIVE);
1072 return archive_state.meta.size == indices[0].value() + 1;
1073}
1074
1082
1084 std::array<TreeMeta, NUM_TREES>& metaResponses)
1085{
1086 TreeMeta& archive_state = metaResponses[MerkleTreeId::ARCHIVE];
1087 status.unfinalizedBlockNumber = archive_state.unfinalizedBlockHeight;
1088 status.finalizedBlockNumber = archive_state.finalizedBlockHeight;
1089 status.oldestHistoricalBlock = archive_state.oldestHistoricBlock;
1090 status.treesAreSynched = determine_if_synched(metaResponses);
1091}
1092
1104
1105bool WorldState::is_same_state_reference(const WorldStateRevision& revision, const StateReference& state_ref) const
1106{
1107 return state_ref == get_state_reference(revision);
1108}
1109
1111{
1112 WorldStateRevision revision{ .forkId = CANONICAL_FORK_ID, .includeUncommitted = false };
1114 get_all_tree_info(revision, responses);
1115
1117 throw std::runtime_error("World state trees are out of sync");
1118 }
1119}
1120
1122{
1123 block_number_t blockNumber = metaResponses[0].unfinalizedBlockHeight;
1124 block_number_t finalizedBlockNumber = metaResponses[0].finalizedBlockHeight;
1125 for (size_t i = 1; i < metaResponses.size(); i++) {
1126 if (blockNumber != metaResponses[i].unfinalizedBlockHeight) {
1127 return false;
1128 }
1129 if (finalizedBlockNumber != metaResponses[i].finalizedBlockHeight) {
1130 return false;
1131 }
1132 }
1133 return true;
1134}
1135
1136uint32_t WorldState::checkpoint(const uint64_t& forkId)
1137{
1138 Fork::SharedPtr fork = retrieve_fork(forkId);
1139 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
1141 std::mutex mtx;
1142 for (auto& [id, tree] : fork->_trees) {
1143 std::visit(
1144 [&signal, &local, id, &mtx](auto&& wrapper) {
1145 wrapper.tree->checkpoint([&signal, &local, &mtx, id](TypedResponse<CheckpointResponse>& resp) {
1146 {
1148 local[id] = std::move(resp);
1149 }
1150 signal.signal_decrement();
1151 });
1152 },
1153 tree);
1154 }
1155 signal.wait_for_level();
1156 for (auto& m : local) {
1157 if (!m.success) {
1158 throw std::runtime_error(m.message);
1159 }
1160 }
1161 // All trees have the same checkpoint depth; return it from the first tree's response
1162 return local[0].inner.depth;
1163}
1164
1165void WorldState::commit_checkpoint(const uint64_t& forkId)
1166{
1167 Fork::SharedPtr fork = retrieve_fork(forkId);
1168 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
1170 std::mutex mtx;
1171 for (auto& [id, tree] : fork->_trees) {
1172 std::visit(
1173 [&signal, &local, id, &mtx](auto&& wrapper) {
1174 wrapper.tree->commit_checkpoint([&signal, &local, &mtx, id](Response& resp) {
1175 {
1177 local[id] = std::move(resp);
1178 }
1179 signal.signal_decrement();
1180 });
1181 },
1182 tree);
1183 }
1184 signal.wait_for_level();
1185 for (auto& m : local) {
1186 if (!m.success) {
1187 throw std::runtime_error(m.message);
1188 }
1189 }
1190}
1191
1192void WorldState::revert_checkpoint(const uint64_t& forkId)
1193{
1194 Fork::SharedPtr fork = retrieve_fork(forkId);
1195 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
1197 std::mutex mtx;
1198 for (auto& [id, tree] : fork->_trees) {
1199 std::visit(
1200 [&signal, &local, id, &mtx](auto&& wrapper) {
1201 wrapper.tree->revert_checkpoint([&signal, &local, &mtx, id](Response& resp) {
1202 {
1204 local[id] = std::move(resp);
1205 }
1206 signal.signal_decrement();
1207 });
1208 },
1209 tree);
1210 }
1211 signal.wait_for_level();
1212 for (auto& m : local) {
1213 if (!m.success) {
1214 throw std::runtime_error(m.message);
1215 }
1216 }
1217}
1218
1219void WorldState::commit_all_checkpoints_to(const uint64_t& forkId, uint32_t depth)
1220{
1221 Fork::SharedPtr fork = retrieve_fork(forkId);
1222 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
1224 std::mutex mtx;
1225 for (auto& [id, tree] : fork->_trees) {
1226 std::visit(
1227 [&signal, &local, id, &mtx, depth](auto&& wrapper) {
1228 auto callback = [&signal, &local, &mtx, id](Response& resp) {
1229 {
1231 local[id] = std::move(resp);
1232 }
1233 signal.signal_decrement();
1234 };
1235 wrapper.tree->commit_to_depth(depth, callback);
1236 },
1237 tree);
1238 }
1239 signal.wait_for_level();
1240 for (auto& m : local) {
1241 if (!m.success) {
1242 throw std::runtime_error(m.message);
1243 }
1244 }
1245}
1246
1247void WorldState::revert_all_checkpoints_to(const uint64_t& forkId, uint32_t depth)
1248{
1249 Fork::SharedPtr fork = retrieve_fork(forkId);
1250 Signal signal(static_cast<uint32_t>(fork->_trees.size()));
1252 std::mutex mtx;
1253 for (auto& [id, tree] : fork->_trees) {
1254 std::visit(
1255 [&signal, &local, id, &mtx, depth](auto&& wrapper) {
1256 auto callback = [&signal, &local, &mtx, id](Response& resp) {
1257 {
1259 local[id] = std::move(resp);
1260 }
1261 signal.signal_decrement();
1262 };
1263 wrapper.tree->revert_to_depth(depth, callback);
1264 },
1265 tree);
1266 }
1267 signal.wait_for_level();
1268 for (auto& m : local) {
1269 if (!m.success) {
1270 throw std::runtime_error(m.message);
1271 }
1272 }
1273}
1274
1276{
1277 WorldStateRevision revision{ .forkId = CANONICAL_FORK_ID, .includeUncommitted = false };
1279 get_all_tree_info(revision, responses);
1280
1281 // Get all historic block numbers
1282 std::array<block_number_t, NUM_TREES> historicalBlockNumbers{ responses[NULLIFIER_TREE].oldestHistoricBlock,
1283 responses[NOTE_HASH_TREE].oldestHistoricBlock,
1284 responses[PUBLIC_DATA_TREE].oldestHistoricBlock,
1285 responses[L1_TO_L2_MESSAGE_TREE].oldestHistoricBlock,
1286 responses[ARCHIVE].oldestHistoricBlock };
1287
1288 // Get all unfinalized block numbers
1289 std::array<block_number_t, NUM_TREES> unfinalizedBlockNumbers{
1290 responses[NULLIFIER_TREE].unfinalizedBlockHeight,
1291 responses[NOTE_HASH_TREE].unfinalizedBlockHeight,
1292 responses[PUBLIC_DATA_TREE].unfinalizedBlockHeight,
1293 responses[L1_TO_L2_MESSAGE_TREE].unfinalizedBlockHeight,
1294 responses[ARCHIVE].unfinalizedBlockHeight
1295 };
1296
1297 // Get all finalized block numbers
1298 std::array<block_number_t, NUM_TREES> finalizedBlockNumbers{ responses[NULLIFIER_TREE].finalizedBlockHeight,
1299 responses[NOTE_HASH_TREE].finalizedBlockHeight,
1300 responses[PUBLIC_DATA_TREE].finalizedBlockHeight,
1301 responses[L1_TO_L2_MESSAGE_TREE].finalizedBlockHeight,
1302 responses[ARCHIVE].finalizedBlockHeight };
1303
1304 // Get the min and max of each set of block numbers
1305 auto historicBlockRange = std::minmax_element(std::begin(historicalBlockNumbers), std::end(historicalBlockNumbers));
1306
1307 auto unfinalizedBlockRange =
1308 std::minmax_element(std::begin(unfinalizedBlockNumbers), std::end(unfinalizedBlockNumbers));
1309
1310 auto finalizedBlockRange = std::minmax_element(std::begin(finalizedBlockNumbers), std::end(finalizedBlockNumbers));
1311
1312 // We re-sync by
1313 // 1. Unwinding any blocks that are ahread of the lowest unfinalized block number
1314 // 2. Increasing finalized block numbers to the highest finalized block number
1315 // 3. Removing any historical blocks that are lower then the highest historic block number
1316
1317 WorldStateStatusFull status;
1318 block_number_t blockToUnwind = *unfinalizedBlockRange.second;
1319 while (blockToUnwind > *unfinalizedBlockRange.first) {
1320 unwind_block(blockToUnwind, status);
1321 blockToUnwind--;
1322 }
1323
1324 if (*finalizedBlockRange.first != *finalizedBlockRange.second) {
1325 set_finalized_block(*finalizedBlockRange.second);
1326 }
1327
1328 block_number_t blockToRemove = *historicBlockRange.first;
1329 while (blockToRemove < *historicBlockRange.second) {
1330 remove_historical_block(blockToRemove, status);
1331 blockToRemove++;
1332 }
1333
1335 return status;
1336}
1337
1338} // namespace bb::world_state
bb::bbapi::CommandResponse responses
std::function< void(TypedResponse< AddDataResponse > &)> AddCompletionCallback
std::shared_ptr< LMDBTreeStore > SharedPtr
Used in parallel insertions in the the IndexedTree. Workers signal to other following workes as they ...
Definition signal.hpp:17
void signal_level(uint32_t level=0)
Signals that the given level has been passed.
Definition signal.hpp:54
void signal_decrement(uint32_t delta=1)
Definition signal.hpp:60
void wait_for_level(uint32_t level=0)
Causes the thread to wait until the required level has been signalled.
Definition signal.hpp:40
Holds the Merkle trees responsible for storing the state of the Aztec protocol.
WorldStateStatusFull remove_historical_blocks(const block_number_t &toBlockNumber)
std::shared_ptr< bb::ThreadPool > _workers
void remove_forks_for_block(const block_number_t &blockNumber)
bool unwind_block(const block_number_t &blockNumber, WorldStateStatusFull &status)
static void get_status_summary_from_meta_responses(WorldStateStatusSummary &status, std::array< TreeMeta, NUM_TREES > &metaResponses)
void commit_tree(TreeDBStats &dbStats, Signal &signal, TreeType &tree, std::atomic_bool &success, std::string &message, TreeMeta &meta)
StateReference get_initial_state_reference() const
Gets the initial state reference for all the trees in the world state.
uint32_t checkpoint(const uint64_t &forkId)
void revert_checkpoint(const uint64_t &forkId)
WorldStateStatusFull attempt_tree_resync()
crypto::merkle_tree::TreeMetaResponse get_tree_info(const WorldStateRevision &revision, MerkleTreeId tree_id) const
Get tree metadata for a particular tree.
static void populate_status_summary(WorldStateStatusFull &status)
void commit_all_checkpoints_to(const uint64_t &forkId, uint32_t depth)
void unwind_tree(TreeDBStats &dbStats, Signal &signal, TreeType &tree, std::atomic_bool &success, std::string &message, TreeMeta &meta, const block_number_t &blockNumber)
std::unordered_map< uint64_t, Fork::SharedPtr > _forks
std::pair< bool, std::string > commit(WorldStateStatusFull &status)
Commits the current state of the world state.
void remove_historic_block_for_tree(TreeDBStats &dbStats, Signal &signal, TreeType &tree, std::atomic_bool &success, std::string &message, TreeMeta &meta, const block_number_t &blockNumber)
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.
WorldStateStatusFull unwind_blocks(const block_number_t &toBlockNumber)
WorldState(uint64_t thread_pool_size, const std::string &data_dir, uint64_t map_size, const std::unordered_map< MerkleTreeId, uint32_t > &tree_heights, const std::unordered_map< MerkleTreeId, index_t > &tree_prefill, uint32_t initial_header_generator_point, uint64_t genesis_timestamp=0, bool ephemeral=false)
bool is_archive_tip(const WorldStateRevision &revision, const bb::fr &block_header_hash) const
static bool determine_if_synched(std::array< TreeMeta, NUM_TREES > &metaResponses)
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 commit_checkpoint(const uint64_t &forkId)
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, const std::optional< bb::fr > &expected_archive_root=std::nullopt, const std::optional< bb::fr > &expected_previous_archive_root=std::nullopt)
Fork::SharedPtr create_new_fork(const block_number_t &blockNumber)
void get_status_summary(WorldStateStatusSummary &status) const
void rollback()
Rolls back any uncommitted changes made to the world state.
WorldStateStatusSummary set_finalized_blocks(const block_number_t &toBlockNumber)
void create_canonical_fork(const std::string &dataDir, const std::unordered_map< MerkleTreeId, uint64_t > &dbSize, const std::vector< PublicDataLeafValue > &prefilled_public_data, const std::vector< bb::fr > &prefilled_nullifiers, uint64_t maxReaders, bool ephemeral)
std::unordered_map< MerkleTreeId, index_t > _initial_tree_size
void delete_fork(const uint64_t &forkId)
bool remove_historical_block(const block_number_t &blockNumber, WorldStateStatusFull &status)
std::unordered_map< MerkleTreeId, uint32_t > _tree_heights
static bb::fr compute_initial_block_header_hash(const StateReference &initial_state_ref, uint32_t generator_point, uint64_t genesis_timestamp=0)
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 revert_all_checkpoints_to(const uint64_t &forkId, uint32_t depth)
bool is_same_state_reference(const WorldStateRevision &revision, const StateReference &state_ref) const
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 copy_stores(const std::string &dstPath, bool compact) const
Copies all underlying LMDB stores to the target directory while acquiring a write lock.
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.
bool set_finalized_block(const block_number_t &blockNumber)
WorldStateStores::Ptr _persistentStores
Fork::SharedPtr retrieve_fork(const uint64_t &forkId) const
void get_all_tree_info(const WorldStateRevision &revision, std::array< TreeMeta, NUM_TREES > &responses) const
std::string format(Args... args)
Definition log.hpp:23
uint32_t block_number_t
Definition types.hpp:19
std::vector< fr > fr_sibling_path
Definition hash_path.hpp:14
@ L1_TO_L2_MESSAGE_TREE
Definition types.hpp:23
const uint64_t DEFAULT_MIN_NUMBER_OF_READERS
const uint64_t CANONICAL_FORK_ID
Definition types.hpp:27
std::string getMerkleTreeName(MerkleTreeId id)
Definition types.cpp:6
std::unordered_map< MerkleTreeId, TreeStateReference > StateReference
Definition types.hpp:33
const uint64_t NUM_TREES
Definition types.hpp:28
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string name
static fr hash(const std::vector< fr > &inputs)
Definition hash.hpp:14
std::shared_ptr< Fork > SharedPtr
Definition fork.hpp:32
static WorldStateRevision committed()
Definition types.hpp:50
static WorldStateRevision uncommitted()
Definition types.hpp:51
WorldStateStatusSummary summary
Definition types.hpp:222
VectorField result