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)
45 , _tree_heights(tree_heights)
46 , _initial_tree_size(tree_prefill)
48 , _initial_header_generator_point(initial_header_generator_point)
49 , _genesis_timestamp(genesis_timestamp)
56 }
catch (std::exception& e) {
62 const std::string& data_dir,
64 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
65 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
66 uint32_t initial_header_generator_point,
67 uint64_t genesis_timestamp)
74 initial_header_generator_point,
79 const std::string& data_dir,
81 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
82 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
84 uint32_t initial_header_generator_point,
85 uint64_t genesis_timestamp)
97 prefilled_public_data,
98 initial_header_generator_point,
103 const std::string& data_dir,
105 const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
106 const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
107 uint32_t initial_header_generator_point,
108 uint64_t genesis_timestamp)
115 initial_header_generator_point,
127 std::filesystem::path directory = dataDir;
129 std::filesystem::create_directories(directory);
181 _forks[fork->_forkId] = fork;
187 std::filesystem::path directory = dstPath;
188 directory /= store->get_name();
189 std::filesystem::create_directories(directory);
190 store->copy_store(directory, compact);
198 std::unique_lock lock(
mtx);
199 auto it =
_forks.find(forkId);
201 throw std::runtime_error(
"Fork not found");
208 if (!blockNumber.has_value()) {
214 blockNumberForFork = blockNumber.value();
217 std::unique_lock lock(
mtx);
219 fork->_forkId = forkId;
229 std::unique_lock lock(
mtx);
231 if (it->second->_blockNumber == blockNumber) {
232 forks.push_back(it->second);
245 throw std::runtime_error(
"Unable to delete canonical fork");
251 std::unique_lock lock(
mtx);
259 fork->_blockNumber = blockNumber;
306 [=](
auto&& wrapper) {
323 throw std::runtime_error(local.
message);
327 fork->_trees.at(tree_id));
339 Signal signal(
static_cast<uint32_t
>(tree_ids.size()));
343 for (
auto id : tree_ids) {
344 const auto& tree = fork->_trees.at(
id);
353 [&callback, &revision](
auto&& wrapper) {
355 wrapper.tree->get_meta_data(revision.blockNumber, revision.includeUncommitted, callback);
357 wrapper.tree->get_meta_data(revision.includeUncommitted, callback);
365 for (
auto tree_id : tree_ids) {
366 auto& m = local[tree_id];
368 throw std::runtime_error(m.message);
390 if (fork->_forkId != revision.
forkId) {
391 throw std::runtime_error(
"Fork does not match revision");
401 Signal signal(
static_cast<uint32_t
>(tree_ids.size()));
404 std::mutex state_ref_mutex;
406 for (
auto id : tree_ids) {
407 const auto& tree = fork->_trees.at(
id);
416 [&callback, &revision](
auto&& wrapper) {
418 wrapper.tree->get_meta_data(revision.blockNumber, revision.includeUncommitted, callback);
420 wrapper.tree->get_meta_data(revision.includeUncommitted, callback);
428 for (
auto tree_id : tree_ids) {
429 auto& m = local[tree_id];
431 throw std::runtime_error(m.message);
434 state_reference[tree_id] =
std::make_pair(m.inner.meta.initialRoot, m.inner.meta.initialSize);
437 state_reference[tree_id] =
std::make_pair(m.inner.meta.root, m.inner.meta.size);
440 return state_reference;
450 [leaf_index, revision](
auto&& wrapper) {
467 throw std::runtime_error(local.
message);
469 return local.
inner.path;
471 fork->_trees.at(tree_id));
476 const std::vector<index_t>& leafIndices,
482 [&leafIndices, revision, &blockNumbers](
auto&& wrapper) {
492 wrapper.tree->find_block_numbers(leafIndices, revision.
blockNumber, callback);
494 wrapper.tree->find_block_numbers(leafIndices, callback);
499 throw std::runtime_error(local.
message);
503 fork->_trees.at(tree_id));
509 if (
const auto* wrapper =
512 wrapper->tree->add_or_update_value(
517 throw std::runtime_error(
"Invalid tree type for PublicDataTree");
522 const bb::fr& block_header_hash,
528 throw std::runtime_error(
"Can't update archive tree: Block state does not match world state");
538 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
581 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
582 for (
auto& [
id, tree] : fork->_trees) {
584 [&signal](
auto&& wrapper) {
593 const bb::fr& block_header_hash,
594 const std::vector<bb::fr>& notes,
595 const std::vector<bb::fr>& l1_to_l2_messages,
603 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
605 std::string err_message;
606 auto decr = [&signal, &success, &err_message](
const auto& resp) {
608 bool expected =
true;
609 if (!resp.success && success.compare_exchange_strong(expected,
false)) {
610 err_message = resp.message;
620 bool expected =
true;
621 if (!resp.success && success.compare_exchange_strong(expected,
false)) {
622 err_message = resp.message;
627 wrapper.tree->add_or_update_values(nullifiers, 0, completion);
632 wrapper.tree->add_values(notes, decr);
637 wrapper.tree->add_values(l1_to_l2_messages, decr);
642 wrapper.tree->add_value(block_header_hash, decr);
649 bool expected =
true;
650 if (!resp.success && success.compare_exchange_strong(expected,
false)) {
651 err_message = resp.message;
656 wrapper.tree->add_or_update_values_sequentially(public_writes, completion);
665 throw std::runtime_error(
"Failed to sync block: " + err_message);
669 throw std::runtime_error(
"Can't synch block: block header hash is not the tip of the archive tree");
673 throw std::runtime_error(
"Can't synch block: block state does not match world state");
678 throw std::runtime_error(result.second);
680 }
catch (
const std::exception& e) {
693 const bb::fr& leaf_key)
const
718 throw std::runtime_error(
"Invalid tree type for find_low_leaf");
724 throw std::runtime_error(low_leaf_info.
message);
726 return low_leaf_info.
inner;
755 auto*
const it =
std::max_element(std::begin(unfinalizedBlockNumbers), std::end(unfinalizedBlockNumbers));
758 if (toBlockNumber >= highestUnfinalizedBlock) {
759 throw std::runtime_error(
format(
"Unable to unwind blocks to block number ",
761 ", current pending block ",
762 highestUnfinalizedBlock));
766 for (
block_number_t blockNumber = highestUnfinalizedBlock; blockNumber > toBlockNumber; blockNumber--) {
786 auto*
const it =
std::min_element(std::begin(historicalBlockNumbers), std::end(historicalBlockNumbers));
788 if (toBlockNumber <= oldestHistoricBlock) {
789 throw std::runtime_error(
format(
"Unable to remove historical blocks to block number ",
791 ", blocks not found. Current oldest block: ",
792 oldestHistoricBlock));
795 for (
block_number_t blockNumber = oldestHistoricBlock; blockNumber < toBlockNumber; blockNumber++) {
806 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
809 for (
auto& [
id, tree] : fork->_trees) {
811 [&signal, &local, blockNumber,
id, &
mtx](
auto&& wrapper) {
812 wrapper.tree->finalize_block(blockNumber, [&signal, &local, &
mtx,
id](
Response& resp) {
823 for (
auto& m : local) {
825 throw std::runtime_error(m.message);
835 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
891 throw std::runtime_error(message);
901 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
957 throw std::runtime_error(message);
964 uint32_t generator_point,
965 uint64_t genesis_timestamp)
989 bb::fr(genesis_timestamp),
1006 }
catch (std::runtime_error&) {
1009 if (indices.empty() || !indices[0].has_value()) {
1014 return archive_state.
meta.
size == indices[0].value() + 1;
1059 throw std::runtime_error(
"World state trees are out of sync");
1065 block_number_t blockNumber = metaResponses[0].unfinalizedBlockHeight;
1066 block_number_t finalizedBlockNumber = metaResponses[0].finalizedBlockHeight;
1067 for (
size_t i = 1; i < metaResponses.size(); i++) {
1068 if (blockNumber != metaResponses[i].unfinalizedBlockHeight) {
1071 if (finalizedBlockNumber != metaResponses[i].finalizedBlockHeight) {
1081 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1084 for (
auto& [
id, tree] : fork->_trees) {
1086 [&signal, &local,
id, &
mtx](
auto&& wrapper) {
1098 for (
auto& m : local) {
1100 throw std::runtime_error(m.message);
1104 return local[0].inner.depth;
1110 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1113 for (
auto& [
id, tree] : fork->_trees) {
1115 [&signal, &local,
id, &
mtx](
auto&& wrapper) {
1116 wrapper.tree->commit_checkpoint([&signal, &local, &
mtx,
id](
Response& resp) {
1127 for (
auto& m : local) {
1129 throw std::runtime_error(m.message);
1137 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1140 for (
auto& [
id, tree] : fork->_trees) {
1142 [&signal, &local,
id, &
mtx](
auto&& wrapper) {
1143 wrapper.tree->revert_checkpoint([&signal, &local, &
mtx,
id](
Response& resp) {
1154 for (
auto& m : local) {
1156 throw std::runtime_error(m.message);
1164 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1167 for (
auto& [
id, tree] : fork->_trees) {
1169 [&signal, &local,
id, &
mtx, depth](
auto&& wrapper) {
1170 auto callback = [&signal, &local, &
mtx, id](
Response& resp) {
1177 wrapper.tree->commit_to_depth(depth, callback);
1182 for (
auto& m : local) {
1184 throw std::runtime_error(m.message);
1192 Signal signal(
static_cast<uint32_t
>(fork->_trees.size()));
1195 for (
auto& [
id, tree] : fork->_trees) {
1197 [&signal, &local,
id, &
mtx, depth](
auto&& wrapper) {
1198 auto callback = [&signal, &local, &
mtx, id](
Response& resp) {
1205 wrapper.tree->revert_to_depth(depth, callback);
1210 for (
auto& m : local) {
1212 throw std::runtime_error(m.message);
1247 auto historicBlockRange =
std::minmax_element(std::begin(historicalBlockNumbers), std::end(historicalBlockNumbers));
1249 auto unfinalizedBlockRange =
1250 std::minmax_element(std::begin(unfinalizedBlockNumbers), std::end(unfinalizedBlockNumbers));
1252 auto finalizedBlockRange =
std::minmax_element(std::begin(finalizedBlockNumbers), std::end(finalizedBlockNumbers));
1261 while (blockToUnwind > *unfinalizedBlockRange.first) {
1266 if (*finalizedBlockRange.first != *finalizedBlockRange.second) {
1271 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)
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)
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)
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
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