28#include <unordered_map>
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,
42 uint32_t initial_header_generator_point,
43 uint64_t genesis_timestamp,
46 , _tree_heights(tree_heights)
47 , _initial_tree_size(tree_prefill)
49 , _initial_header_generator_point(initial_header_generator_point)
50 , _genesis_timestamp(genesis_timestamp)
57 }
catch (std::exception& e) {
63 const std::string& data_dir,
65 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
66 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
67 uint32_t initial_header_generator_point,
68 uint64_t genesis_timestamp,
76 initial_header_generator_point,
82 const std::string& data_dir,
84 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
85 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
87 uint32_t initial_header_generator_point,
88 uint64_t genesis_timestamp,
101 prefilled_public_data,
102 initial_header_generator_point,
108 const std::string& data_dir,
110 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
111 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
112 uint32_t initial_header_generator_point,
113 uint64_t genesis_timestamp,
121 initial_header_generator_point,
135 std::filesystem::path directory = dataDir;
137 std::filesystem::create_directories(directory);
189 _forks[fork->_forkId] = fork;
195 std::filesystem::path directory = dstPath;
196 directory /= store->get_name();
197 std::filesystem::create_directories(directory);
198 store->copy_store(directory, compact);
206 std::unique_lock lock(
mtx);
207 auto it =
_forks.find(forkId);
209 throw std::runtime_error(
"Fork not found");
216 if (!blockNumber.has_value()) {
222 blockNumberForFork = blockNumber.value();
225 std::unique_lock lock(
mtx);
227 fork->_forkId = forkId;
237 std::unique_lock lock(
mtx);
239 if (it->second->_blockNumber == blockNumber) {
240 forks.push_back(it->second);
253 throw std::runtime_error(
"Unable to delete canonical fork");
259 std::unique_lock lock(
mtx);
267 fork->_blockNumber = blockNumber;
314 [=](
auto&& wrapper) {
331 throw std::runtime_error(local.
message);
335 fork->_trees.at(tree_id));
347 Signal signal(
static_cast<uint32_t
>(tree_ids.size()));
351 for (
auto id : tree_ids) {
352 const auto& tree = fork->_trees.at(
id);
361 [&callback, &revision](
auto&& wrapper) {
363 wrapper.tree->get_meta_data(revision.blockNumber, revision.includeUncommitted, callback);
365 wrapper.tree->get_meta_data(revision.includeUncommitted, callback);
373 for (
auto tree_id : tree_ids) {
374 auto& m = local[tree_id];
376 throw std::runtime_error(m.message);
398 if (fork->_forkId != revision.
forkId) {
399 throw std::runtime_error(
"Fork does not match revision");
409 Signal signal(
static_cast<uint32_t
>(tree_ids.size()));
412 std::mutex state_ref_mutex;
414 for (
auto id : tree_ids) {
415 const auto& tree = fork->_trees.at(
id);
424 [&callback, &revision](
auto&& wrapper) {
426 wrapper.tree->get_meta_data(revision.blockNumber, revision.includeUncommitted, callback);
428 wrapper.tree->get_meta_data(revision.includeUncommitted, callback);
436 for (
auto tree_id : tree_ids) {
437 auto& m = local[tree_id];
439 throw std::runtime_error(m.message);
442 state_reference[tree_id] =
std::make_pair(m.inner.meta.initialRoot, m.inner.meta.initialSize);
445 state_reference[tree_id] =
std::make_pair(m.inner.meta.root, m.inner.meta.size);
448 return state_reference;
458 [leaf_index, revision](
auto&& wrapper) {
475 throw std::runtime_error(local.
message);
477 return local.
inner.path;
479 fork->_trees.at(tree_id));
484 const std::vector<index_t>& leafIndices,
490 [&leafIndices, revision, &blockNumbers](
auto&& wrapper) {
500 wrapper.tree->find_block_numbers(leafIndices, revision.
blockNumber, callback);
502 wrapper.tree->find_block_numbers(leafIndices, callback);
507 throw std::runtime_error(local.
message);
511 fork->_trees.at(tree_id));
517 if (
const auto* wrapper =
520 wrapper->tree->add_or_update_value(
525 throw std::runtime_error(
"Invalid tree type for PublicDataTree");
530 const bb::fr& block_header_hash,
536 throw std::runtime_error(
"Can't update archive tree: Block state does not match world state");
546 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
589 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
590 for (
auto& [
id, tree] : fork->_trees) {
592 [&signal](
auto&& wrapper) {
601 const bb::fr& block_header_hash,
602 const std::vector<bb::fr>& notes,
603 const std::vector<bb::fr>& l1_to_l2_messages,
611 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
613 std::string err_message;
614 auto decr = [&signal, &success, &err_message](
const auto& resp) {
616 bool expected =
true;
617 if (!resp.success && success.compare_exchange_strong(expected,
false)) {
618 err_message = resp.message;
628 bool expected =
true;
629 if (!resp.success && success.compare_exchange_strong(expected,
false)) {
630 err_message = resp.message;
635 wrapper.tree->add_or_update_values(nullifiers, 0, completion);
640 wrapper.tree->add_values(notes, decr);
645 wrapper.tree->add_values(l1_to_l2_messages, decr);
650 wrapper.tree->add_value(block_header_hash, decr);
657 bool expected =
true;
658 if (!resp.success && success.compare_exchange_strong(expected,
false)) {
659 err_message = resp.message;
664 wrapper.tree->add_or_update_values_sequentially(public_writes, completion);
673 throw std::runtime_error(
"Failed to sync block: " + err_message);
677 throw std::runtime_error(
"Can't synch block: block header hash is not the tip of the archive tree");
681 throw std::runtime_error(
"Can't synch block: block state does not match world state");
686 throw std::runtime_error(result.second);
688 }
catch (
const std::exception& e) {
701 const bb::fr& leaf_key)
const
726 throw std::runtime_error(
"Invalid tree type for find_low_leaf");
732 throw std::runtime_error(low_leaf_info.
message);
734 return low_leaf_info.
inner;
763 auto*
const it =
std::max_element(std::begin(unfinalizedBlockNumbers), std::end(unfinalizedBlockNumbers));
766 if (toBlockNumber >= highestUnfinalizedBlock) {
767 throw std::runtime_error(
format(
"Unable to unwind blocks to block number ",
769 ", current pending block ",
770 highestUnfinalizedBlock));
774 for (
block_number_t blockNumber = highestUnfinalizedBlock; blockNumber > toBlockNumber; blockNumber--) {
794 auto*
const it =
std::min_element(std::begin(historicalBlockNumbers), std::end(historicalBlockNumbers));
796 if (toBlockNumber <= oldestHistoricBlock) {
797 throw std::runtime_error(
format(
"Unable to remove historical blocks to block number ",
799 ", blocks not found. Current oldest block: ",
800 oldestHistoricBlock));
803 for (
block_number_t blockNumber = oldestHistoricBlock; blockNumber < toBlockNumber; blockNumber++) {
814 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
817 for (
auto& [
id, tree] : fork->_trees) {
819 [&signal, &local, blockNumber,
id, &
mtx](
auto&& wrapper) {
820 wrapper.tree->finalize_block(blockNumber, [&signal, &local, &
mtx,
id](
Response& resp) {
831 for (
auto& m : local) {
833 throw std::runtime_error(m.message);
843 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
899 throw std::runtime_error(message);
909 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
965 throw std::runtime_error(message);
972 uint32_t generator_point,
973 uint64_t genesis_timestamp)
997 bb::fr(genesis_timestamp),
1014 }
catch (std::runtime_error&) {
1017 if (indices.empty() || !indices[0].has_value()) {
1022 return archive_state.
meta.
size == indices[0].value() + 1;
1067 throw std::runtime_error(
"World state trees are out of sync");
1073 block_number_t blockNumber = metaResponses[0].unfinalizedBlockHeight;
1074 block_number_t finalizedBlockNumber = metaResponses[0].finalizedBlockHeight;
1075 for (
size_t i = 1; i < metaResponses.size(); i++) {
1076 if (blockNumber != metaResponses[i].unfinalizedBlockHeight) {
1079 if (finalizedBlockNumber != metaResponses[i].finalizedBlockHeight) {
1089 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1092 for (
auto& [
id, tree] : fork->_trees) {
1094 [&signal, &local,
id, &
mtx](
auto&& wrapper) {
1106 for (
auto& m : local) {
1108 throw std::runtime_error(m.message);
1112 return local[0].inner.depth;
1118 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1121 for (
auto& [
id, tree] : fork->_trees) {
1123 [&signal, &local,
id, &
mtx](
auto&& wrapper) {
1124 wrapper.tree->commit_checkpoint([&signal, &local, &
mtx,
id](
Response& resp) {
1135 for (
auto& m : local) {
1137 throw std::runtime_error(m.message);
1145 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1148 for (
auto& [
id, tree] : fork->_trees) {
1150 [&signal, &local,
id, &
mtx](
auto&& wrapper) {
1151 wrapper.tree->revert_checkpoint([&signal, &local, &
mtx,
id](
Response& resp) {
1162 for (
auto& m : local) {
1164 throw std::runtime_error(m.message);
1172 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1175 for (
auto& [
id, tree] : fork->_trees) {
1177 [&signal, &local,
id, &
mtx, depth](
auto&& wrapper) {
1178 auto callback = [&signal, &local, &
mtx, id](
Response& resp) {
1185 wrapper.tree->commit_to_depth(depth, callback);
1190 for (
auto& m : local) {
1192 throw std::runtime_error(m.message);
1200 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1203 for (
auto& [
id, tree] : fork->_trees) {
1205 [&signal, &local,
id, &
mtx, depth](
auto&& wrapper) {
1206 auto callback = [&signal, &local, &
mtx, id](
Response& resp) {
1213 wrapper.tree->revert_to_depth(depth, callback);
1218 for (
auto& m : local) {
1220 throw std::runtime_error(m.message);
1255 auto historicBlockRange =
std::minmax_element(std::begin(historicalBlockNumbers), std::end(historicalBlockNumbers));
1257 auto unfinalizedBlockRange =
1258 std::minmax_element(std::begin(unfinalizedBlockNumbers), std::end(unfinalizedBlockNumbers));
1260 auto finalizedBlockRange =
std::minmax_element(std::begin(finalizedBlockNumbers), std::end(finalizedBlockNumbers));
1269 while (blockToUnwind > *unfinalizedBlockRange.first) {
1274 if (*finalizedBlockRange.first != *finalizedBlockRange.second) {
1279 while (blockToRemove < *historicBlockRange.second) {
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 ...
void signal_level(uint32_t level=0)
Signals that the given level has been passed.
void signal_decrement(uint32_t delta=1)
void wait_for_level(uint32_t level=0)
Causes the thread to wait until the required level has been signalled.
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
void create_canonical_fork(const std::string &dataDir, const std::unordered_map< MerkleTreeId, uint64_t > &dbSize, const std::vector< PublicDataLeafValue > &prefilled_public_data, uint64_t maxReaders, bool ephemeral)
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
uint64_t _genesis_timestamp
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)
uint32_t _initial_header_generator_point
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)
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.
WorldStateStatusFull sync_block(const StateReference &block_state_ref, const bb::fr &block_header_hash, const std::vector< bb::fr > ¬es, 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)
WorldStateStatusSummary set_finalized_blocks(const block_number_t &toBlockNumber)
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 validate_trees_are_equally_synched()
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)
std::vector< fr > fr_sibling_path
const uint64_t DEFAULT_MIN_NUMBER_OF_READERS
const uint64_t CANONICAL_FORK_ID
std::string getMerkleTreeName(MerkleTreeId id)
std::unordered_map< MerkleTreeId, TreeStateReference > StateReference
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static fr hash(const std::vector< fr > &inputs)
std::shared_ptr< Fork > SharedPtr
TreeDBStats nullifierTreeStats
TreeDBStats noteHashTreeStats
TreeDBStats archiveTreeStats
TreeDBStats publicDataTreeStats
TreeDBStats messageTreeStats
block_number_t blockNumber
static WorldStateRevision committed()
bool is_historical() const
static WorldStateRevision uncommitted()
WorldStateDBStats dbStats
WorldStateStatusSummary summary
index_t unfinalizedBlockNumber
index_t finalizedBlockNumber
index_t oldestHistoricalBlock