70 const std::vector<fr>& initial_values = {},
71 bool commit_genesis_state =
true);
110 bool includeUncommitted)
const;
121 bool includeUncommitted)
const;
132 uint32_t subtree_depth,
134 bool includeUncommitted)
const;
150 bool includeUncommitted,
170 bool includeUncommitted,
177 bool includeUncommitted,
185 bool includeUncommitted,
192 bool includeUncommitted,
200 bool includeUncommitted,
208 bool includeUncommitted,
217 bool includeUncommitted,
278 uint32_t subtree_depth,
285 bool updateNodesByIndexCache =
false)
const;
299template <
typename Store,
typename HashingPolicy>
301 std::unique_ptr<Store> store,
303 const std::vector<fr>& initial_values,
304 bool commit_genesis_state)
305 : store_(
std::move(store))
315 auto current = HashingPolicy::zero_hash();
316 for (
size_t i =
depth_; i > 0; --i) {
319 current = HashingPolicy::hash_pair(current, current);
330 if (initial_values.empty()) {
343 throw std::runtime_error(
format(
"Failed to initialize tree: ", result.
message));
353 if (commit_genesis_state) {
354 store_->commit_genesis_state();
358template <
typename Store,
typename HashingPolicy>
362 auto job = [=,
this]() {
363 execute_and_report<TreeMetaResponse>(
366 store_->get_meta(response.
inner.meta, *tx, includeUncommitted);
370 workers_->enqueue(job);
373template <
typename Store,
typename HashingPolicy>
375 bool includeUncommitted,
378 auto job = [=,
this]() {
379 execute_and_report<TreeMetaResponse>(
382 store_->get_meta(response.
inner.meta, *tx, includeUncommitted);
385 if (!store_->get_block_data(blockNumber, blockData, *tx)) {
386 throw std::runtime_error(
387 format(
"Unable to get meta data for block ", blockNumber,
", failed to get block data."));
390 response.
inner.meta.size = blockData.
size;
391 response.
inner.meta.committedSize = blockData.
size;
392 response.
inner.meta.root = blockData.
root;
396 workers_->enqueue(job);
399template <
typename Store,
typename HashingPolicy>
402 bool includeUncommitted)
const
404 get_subtree_sibling_path(
index, 0, on_completion, includeUncommitted);
407template <
typename Store,
typename HashingPolicy>
411 bool includeUncommitted)
const
413 auto job = [=,
this]() {
414 execute_and_report<GetSiblingPathResponse>(
416 if (blockNumber == 0) {
417 throw std::runtime_error(
"Unable to get sibling path at block 0");
421 if (!store_->get_block_data(blockNumber, blockData, *tx)) {
422 throw std::runtime_error(
format(
"Unable to get sibling path for index ",
426 ", failed to get block data."));
432 requestContext.
root = blockData.
root;
434 response.
inner.path = optional_sibling_path_to_full_sibling_path(optional_path);
438 workers_->enqueue(job);
441template <
typename Store,
typename HashingPolicy>
445 auto job = [=,
this]() {
446 execute_and_report<BlockForIndexResponse>(
448 response.
inner.blockNumbers.reserve(indices.size());
452 response.
inner.blockNumbers.emplace_back(block);
457 workers_->enqueue(job);
460template <
typename Store,
typename HashingPolicy>
462 const std::vector<index_t>& indices,
466 auto job = [=,
this]() {
467 execute_and_report<BlockForIndexResponse>(
469 response.
inner.blockNumbers.reserve(indices.size());
472 if (!store_->get_block_data(blockNumber, blockPayload, *tx)) {
473 throw std::runtime_error(
format(
"Unable to find block numbers for indices for block ",
475 ", failed to get block data."));
479 bool outOfRange =
index >= maxIndex;
482 response.
inner.blockNumbers.emplace_back(block);
487 workers_->enqueue(job);
490template <
typename Store,
typename HashingPolicy>
492 uint32_t subtree_depth,
const HashPathCallback& on_completion,
bool includeUncommitted)
const
494 auto job = [=,
this]() {
495 execute_and_report<GetSiblingPathResponse>(
499 store_->get_meta(meta, *tx, includeUncommitted);
502 requestContext.
root = store_->get_current_root(*tx, includeUncommitted);
504 get_subtree_sibling_path_internal(meta.
size, subtree_depth, requestContext, *tx);
505 response.
inner.path = optional_sibling_path_to_full_sibling_path(optional_path);
509 workers_->enqueue(job);
512template <
typename Store,
typename HashingPolicy>
515 uint32_t subtree_depth,
517 bool includeUncommitted)
const
519 auto job = [=,
this]() {
520 execute_and_report<GetSiblingPathResponse>(
525 requestContext.
root = store_->get_current_root(*tx, includeUncommitted);
528 get_subtree_sibling_path_internal(leaf_index, subtree_depth, requestContext, *tx);
529 response.
inner.path = optional_sibling_path_to_full_sibling_path(optional_path);
533 workers_->enqueue(job);
536template <
typename Store,
typename HashingPolicy>
540 if (optionalPath.empty()) {
544 size_t pathIndex = optionalPath.size() - 1;
545 for (
index_t level = 1; level <= optionalPath.size(); level++) {
547 path[pathIndex] = op.has_value() ? op.value() : zero_hashes_[level];
553template <
typename Store,
typename HashingPolicy>
558 bool updateNodesByIndexCache)
const
563 index_t child_index_at_level = 0;
564 for (uint32_t i = 0; i < depth_; ++i) {
578 bool is_right =
static_cast<bool>(leaf_index & mask);
586 if (!child.has_value()) {
590 if (updateNodesByIndexCache) {
591 child_index_at_level = is_right ? (child_index_at_level * 2) + 1 : (child_index_at_level * 2);
593 index_t sibling_index_at_level = is_right ? child_index_at_level - 1 : child_index_at_level + 1;
594 if (sibling.has_value()) {
595 store_->put_cached_node_by_index(i + 1, sibling_index_at_level, sibling.value(),
false);
602 hash = child.value();
604 if (!updateNodesByIndexCache) {
608 child_index_at_level = is_right ? (child_index_at_level * 2) + 1 : (child_index_at_level * 2);
611 store_->put_cached_node_by_index(i + 1, child_index_at_level,
hash,
false);
613 index_t sibling_index_at_level = is_right ? child_index_at_level - 1 : child_index_at_level + 1;
614 if (sibling.has_value()) {
618 store_->put_cached_node_by_index(i + 1, sibling_index_at_level, sibling.value(),
false);
626template <
typename Store,
typename HashingPolicy>
629 HashingPolicy>::get_subtree_sibling_path_internal(
const index_t& leaf_index,
630 uint32_t subtree_depth,
636 if (subtree_depth >= depth_) {
639 path.resize(depth_ - subtree_depth);
640 size_t path_index = path.size() - 1;
648 for (uint32_t level = 0; level < depth_ - subtree_depth; ++level) {
651 bool is_right =
static_cast<bool>(leaf_index & mask);
664 hash = child.has_value() ? child.value() : zero_hashes_[level + 1];
667 path[path_index--] = sibling;
673template <
typename Store,
typename HashingPolicy>
675 bool includeUncommitted,
678 auto job = [=,
this]() {
679 execute_and_report<GetLeafResponse>(
682 if (max_size_ < leaf_index) {
686 format(
"Unable to get leaf at index ", leaf_index,
", leaf index out of tree range.");
692 requestContext.
root = store_->get_current_root(*tx, includeUncommitted);
693 std::optional<fr> leaf_hash = find_leaf_hash(leaf_index, requestContext, *tx,
false);
694 response.
success = leaf_hash.has_value();
696 response.
inner.leaf = leaf_hash.value();
704 response.
message =
format(
"Failed to find leaf hash at index ", leaf_index);
709 workers_->enqueue(job);
712template <
typename Store,
typename HashingPolicy>
715 bool includeUncommitted,
718 auto job = [=,
this]() {
719 execute_and_report<GetLeafResponse>(
721 if (blockNumber == 0) {
722 throw std::runtime_error(
"Unable to get leaf at block 0");
726 if (!store_->get_block_data(blockNumber, blockData, *tx)) {
727 throw std::runtime_error(
format(
"Unable to get leaf at index ",
731 ", failed to get block data."));
733 if (max_size_ < leaf_index) {
740 ", leaf index out of tree range.");
744 if (blockData.
size < leaf_index) {
752 ", leaf index out of block range.");
759 requestContext.
root = blockData.
root;
760 std::optional<fr> leaf_hash = find_leaf_hash(leaf_index, requestContext, *tx,
false);
761 response.
success = leaf_hash.has_value();
763 response.
inner.leaf = leaf_hash.value();
772 format(
"Failed to find leaf hash at index ", leaf_index,
" for block number ", blockNumber);
777 workers_->enqueue(job);
780template <
typename Store,
typename HashingPolicy>
783 bool includeUncommitted,
786 find_leaf_indices_from(leaves, 0, includeUncommitted, on_completion);
789template <
typename Store,
typename HashingPolicy>
793 bool includeUncommitted,
796 find_leaf_indices_from(leaves, 0, blockNumber, includeUncommitted, on_completion);
799template <
typename Store,
typename HashingPolicy>
803 bool includeUncommitted,
806 auto job = [=,
this]() ->
void {
807 execute_and_report<FindLeafIndexResponse>(
809 response.
inner.leaf_indices.reserve(leaves.size());
815 for (
const auto& leaf : leaves) {
817 store_->find_leaf_index_from(leaf, start_index, requestContext, *tx);
818 response.
inner.leaf_indices.emplace_back(leaf_index);
823 workers_->enqueue(job);
826template <
typename Store,
typename HashingPolicy>
831 bool includeUncommitted,
834 auto job = [=,
this]() ->
void {
835 execute_and_report<FindLeafIndexResponse>(
837 response.
inner.leaf_indices.reserve(leaves.size());
838 if (blockNumber == 0) {
839 throw std::runtime_error(
"Unable to find leaf index for block number 0");
843 if (!store_->get_block_data(blockNumber, blockData, *tx)) {
844 throw std::runtime_error(
format(
"Unable to find leaf from index ",
848 ", failed to get block data."));
856 for (
const auto& leaf : leaves) {
858 store_->find_leaf_index_from(leaf, start_index, requestContext, *tx);
859 response.
inner.leaf_indices.emplace_back(leaf_index);
864 workers_->enqueue(job);
867template <
typename Store,
typename HashingPolicy>
870 bool includeUncommitted,
873 auto job = [=,
this]() ->
void {
874 execute_and_report<FindLeafPathResponse>(
876 response.
inner.leaf_paths.reserve(leaves.size());
881 requestContext.
root = store_->get_current_root(*tx, includeUncommitted);
883 for (
const auto& leaf : leaves) {
885 if (!leaf_index.has_value()) {
890 get_subtree_sibling_path_internal(leaf_index.value(), 0, requestContext, *tx);
892 sibling_path_and_index.
path = optional_sibling_path_to_full_sibling_path(optional_path);
893 sibling_path_and_index.
index = leaf_index.value();
894 response.
inner.leaf_paths.emplace_back(sibling_path_and_index);
899 workers_->enqueue(job);
902template <
typename Store,
typename HashingPolicy>
906 bool includeUncommitted,
909 auto job = [=,
this]() ->
void {
910 execute_and_report<FindLeafPathResponse>(
912 response.
inner.leaf_paths.reserve(leaves.size());
913 if (blockNumber == 0) {
914 throw std::runtime_error(
"Unable to find leaf index for block number 0");
918 if (!store_->get_block_data(blockNumber, blockData, *tx)) {
919 throw std::runtime_error(
920 format(
"Unable to find sibling path for block ", blockNumber,
", failed to get block data."));
927 requestContext.
root = blockData.
root;
929 for (
const auto& leaf : leaves) {
931 if (!leaf_index.has_value()) {
936 get_subtree_sibling_path_internal(leaf_index.value(), 0, requestContext, *tx);
938 sibling_path_and_index.
path = optional_sibling_path_to_full_sibling_path(optional_path);
939 sibling_path_and_index.
index = leaf_index.value();
940 response.
inner.leaf_paths.emplace_back(sibling_path_and_index);
945 workers_->enqueue(job);
948template <
typename Store,
typename HashingPolicy>
955template <
typename Store,
typename HashingPolicy>
959 add_values_internal(values, on_completion,
true);
962template <
typename Store,
typename HashingPolicy>
967 auto append_op = [=,
this]() ->
void {
968 execute_and_report<AddDataResponse>(
970 add_values_internal(hashes, response.
inner.root, response.
inner.size, update_index);
974 workers_->enqueue(append_op);
977template <
typename Store,
typename HashingPolicy>
980 auto job = [=,
this]() {
981 execute_and_report<CommitResponse>(
983 store_->commit_block(response.
inner.meta, response.
inner.stats);
987 workers_->enqueue(job);
990template <
typename Store,
typename HashingPolicy>
993 auto job = [=,
this]() {
execute_and_report([=,
this]() { store_->rollback(); }, on_completion); };
994 workers_->enqueue(job);
1002template <
typename Store,
typename HashingPolicy>
1005 auto job = [=,
this]() {
execute_and_report([=,
this]() { store_->checkpoint(); }, on_completion); };
1006 workers_->enqueue(job);
1009template <
typename Store,
typename HashingPolicy>
1013 auto job = [=,
this]() {
execute_and_report([=,
this]() { store_->commit_checkpoint(); }, on_completion); };
1014 workers_->enqueue(job);
1017template <
typename Store,
typename HashingPolicy>
1021 auto job = [=,
this]() {
execute_and_report([=,
this]() { store_->revert_checkpoint(); }, on_completion); };
1022 workers_->enqueue(job);
1025template <
typename Store,
typename HashingPolicy>
1029 auto job = [=,
this]() {
execute_and_report([=,
this]() { store_->commit_all_checkpoints(); }, on_completion); };
1030 workers_->enqueue(job);
1033template <
typename Store,
typename HashingPolicy>
1037 auto job = [=,
this]() {
execute_and_report([=,
this]() { store_->revert_all_checkpoints(); }, on_completion); };
1038 workers_->enqueue(job);
1041template <
typename Store,
typename HashingPolicy>
1045 auto job = [=,
this]() {
1046 execute_and_report<RemoveHistoricResponse>(
1048 if (blockNumber == 0) {
1049 throw std::runtime_error(
"Unable to remove historic block 0");
1051 store_->remove_historical_block(blockNumber, response.
inner.meta, response.
inner.stats);
1055 workers_->enqueue(job);
1058template <
typename Store,
typename HashingPolicy>
1062 auto job = [=,
this]() {
1063 execute_and_report<UnwindResponse>(
1065 if (blockNumber == 0) {
1066 throw std::runtime_error(
"Unable to unwind block 0");
1068 store_->unwind_block(blockNumber, response.
inner.meta, response.
inner.stats);
1072 workers_->enqueue(job);
1075template <
typename Store,
typename HashingPolicy>
1079 auto job = [=,
this]() {
1082 if (blockNumber == 0) {
1083 throw std::runtime_error(
"Unable to finalize block 0");
1085 store_->advance_finalized_block(blockNumber);
1089 workers_->enqueue(job);
1092template <
typename Store,
typename HashingPolicy>
1097 if (treeSize != 0U) {
1098 while (!(minPower2 & treeSize)) {
1101 if (minPower2 <= remainingAppendSize) {
1106 while (maxPower2 <= remainingAppendSize) {
1109 return maxPower2 >> 1;
1112template <
typename Store,
typename HashingPolicy>
1120 store_->get_meta(meta);
1122 new_size = meta.
size;
1124 while (sizeToAppend != 0U) {
1125 index_t batchSize = get_batch_insertion_size(new_size, sizeToAppend);
1126 sizeToAppend -= batchSize;
1127 int64_t start =
static_cast<int64_t
>(batchIndex);
1128 int64_t end =
static_cast<int64_t
>(batchIndex + batchSize);
1129 std::vector<fr> batch = std::vector<fr>(values->begin() + start, values->begin() + end);
1130 batchIndex += batchSize;
1131 add_batch_internal(batch, new_root, new_size, update_index, *tx);
1135template <
typename Store,
typename HashingPolicy>
1139 uint32_t start_level = depth_;
1140 uint32_t level = start_level;
1141 std::vector<fr>& hashes_local = values;
1142 auto number_to_insert =
static_cast<uint32_t
>(hashes_local.size());
1145 store_->get_meta(meta);
1147 new_size = meta.
size + number_to_insert;
1150 if (values.empty()) {
1154 if (new_size > max_size_) {
1155 throw std::runtime_error(
1156 format(
"Unable to append leaves to tree ", meta.
name,
" new size: ", new_size,
" max size: ", max_size_));
1160 for (uint32_t i = 0; i < number_to_insert; ++i) {
1164 store_->put_cached_node_by_index(level, i +
index, hashes_local[i]);
1169 for (uint32_t i = 0; i < number_to_insert; ++i) {
1171 if (hashes_local[i] ==
fr::zero()) {
1175 store_->update_index(
index + i, hashes_local[i]);
1180 while (number_to_insert > 1) {
1181 number_to_insert >>= 1;
1185 for (uint32_t i = 0; i < number_to_insert; ++i) {
1186 fr left = hashes_local[i * 2];
1187 fr right = hashes_local[i * 2 + 1];
1188 hashes_local[i] = HashingPolicy::hash_pair(left, right);
1190 store_->put_node_by_hash(hashes_local[i], { .left = left, .right = right, .ref = 1 });
1191 store_->put_cached_node_by_index(level,
index + i, hashes_local[i]);
1197 fr new_hash = hashes_local[0];
1202 requestContext.
root = store_->get_current_root(tx,
true);
1204 get_subtree_sibling_path_internal(meta.
size, depth_ - level, requestContext, tx);
1205 fr_sibling_path sibling_path_to_root = optional_sibling_path_to_full_sibling_path(optional_sibling_path_to_root);
1206 size_t sibling_path_index = 0;
1212 bool is_right =
static_cast<bool>(
index & 0x01);
1216 fr left_hash = is_right ? sibling_path_to_root[sibling_path_index] : new_hash;
1217 fr right_hash = is_right ? new_hash : sibling_path_to_root[sibling_path_index];
1219 std::optional<fr> left_op = is_right ? optional_sibling_path_to_root[sibling_path_index] : new_hash;
1220 std::optional<fr> right_op = is_right ? new_hash : optional_sibling_path_to_root[sibling_path_index];
1222 new_hash = HashingPolicy::hash_pair(left_hash, right_hash);
1227 ++sibling_path_index;
1228 store_->put_cached_node_by_index(level,
index, new_hash);
1229 store_->put_node_by_hash(new_hash, { .left = left_op, .right = right_op, .ref = 1 });
1233 new_root = new_hash;
1234 meta.
root = new_hash;
1235 meta.
size = new_size;
1237 store_->put_meta(meta);
std::shared_ptr< Napi::ThreadSafeFunction > revert_checkpoint
std::shared_ptr< Napi::ThreadSafeFunction > commit_checkpoint
Implements a simple append-only merkle tree All methods are asynchronous unless specified as otherwis...
typename Store::ReadTransaction ReadTransaction
void get_leaf(const index_t &index, bool includeUncommitted, const GetLeafCallback &completion) const
Returns the leaf value at the provided index.
void remove_historic_block(const block_number_t &blockNumber, const RemoveHistoricBlockCallback &on_completion)
std::function< void(TypedResponse< FindLeafPathResponse > &)> FindSiblingPathCallback
OptionalSiblingPath get_subtree_sibling_path_internal(const index_t &leaf_index, uint32_t subtree_depth, const RequestContext &requestContext, ReadTransaction &tx) const
void get_sibling_path(const index_t &index, const HashPathCallback &on_completion, bool includeUncommitted) const
Returns the sibling path from the leaf at the given index to the root.
void commit(const CommitCallback &on_completion)
Commit the tree to the backing store.
void add_values_internal(std::shared_ptr< std::vector< fr > > values, fr &new_root, index_t &new_size, bool update_index)
void add_batch_internal(std::vector< fr > &values, fr &new_root, index_t &new_size, bool update_index, ReadTransaction &tx)
std::function< void(Response &)> EmptyResponseCallback
std::shared_ptr< ThreadPool > workers_
void commit_checkpoint(const CheckpointCommitCallback &on_completion)
void commit_all_checkpoints(const CheckpointCommitCallback &on_completion)
std::vector< fr > zero_hashes_
uint32_t depth() const
Synchronous method to retrieve the depth of the tree.
EmptyResponseCallback RollbackCallback
std::vector< std::optional< fr > > OptionalSiblingPath
virtual ~ContentAddressedAppendOnlyTree()=default
std::function< void(TypedResponse< GetLeafResponse > &)> GetLeafCallback
virtual void add_values(const std::vector< fr > &values, const AppendCompletionCallback &on_completion)
Adds the given set of values to the end of the tree.
ContentAddressedAppendOnlyTree & operator=(ContentAddressedAppendOnlyTree const &other)=delete
void get_meta_data(bool includeUncommitted, const MetaDataCallback &on_completion) const
Returns the tree meta data.
fr_sibling_path optional_sibling_path_to_full_sibling_path(const OptionalSiblingPath &optionalPath) const
std::unique_ptr< Store > store_
EmptyResponseCallback FinalizeBlockCallback
ContentAddressedAppendOnlyTree & operator=(ContentAddressedAppendOnlyTree const &&other)=delete
void find_block_numbers(const std::vector< index_t > &indices, const GetBlockForIndexCallback &on_completion) const
Returns the block numbers that correspond to the given indices values.
void unwind_block(const block_number_t &blockNumber, const UnwindBlockCallback &on_completion)
std::function< void(TypedResponse< FindLeafIndexResponse > &)> FindLeafCallback
std::function< void(TypedResponse< GetSiblingPathResponse > &)> HashPathCallback
std::function< void(TypedResponse< TreeMetaResponse > &)> MetaDataCallback
void revert_checkpoint(const CheckpointRevertCallback &on_completion)
std::function< void(TypedResponse< UnwindResponse > &)> UnwindBlockCallback
std::function< void(TypedResponse< AddDataResponse > &)> AppendCompletionCallback
void revert_all_checkpoints(const CheckpointRevertCallback &on_completion)
virtual void add_value(const fr &value, const AppendCompletionCallback &on_completion)
Adds a single value to the end of the tree.
std::optional< fr > find_leaf_hash(const index_t &leaf_index, const RequestContext &requestContext, ReadTransaction &tx, bool updateNodesByIndexCache=false) const
EmptyResponseCallback CheckpointRevertCallback
void rollback(const RollbackCallback &on_completion)
Rollback the uncommitted changes.
typename Store::ReadTransactionPtr ReadTransactionPtr
void find_leaf_indices(const std::vector< typename Store::LeafType > &leaves, bool includeUncommitted, const FindLeafCallback &on_completion) const
Returns the index of the provided leaf in the tree.
EmptyResponseCallback CheckpointCallback
void get_subtree_sibling_path(uint32_t subtree_depth, const HashPathCallback &on_completion, bool includeUncommitted) const
Get the subtree sibling path object.
std::function< void(TypedResponse< CommitResponse > &)> CommitCallback
index_t get_batch_insertion_size(const index_t &treeSize, const index_t &remainingAppendSize)
ContentAddressedAppendOnlyTree(ContentAddressedAppendOnlyTree &&other)=delete
void finalize_block(const block_number_t &blockNumber, const FinalizeBlockCallback &on_completion)
void checkpoint(const CheckpointCallback &on_completion)
void find_leaf_indices_from(const std::vector< typename Store::LeafType > &leaves, const index_t &start_index, bool includeUncommitted, const FindLeafCallback &on_completion) const
Returns the index of the provided leaf in the tree only if it exists after the index value provided.
std::function< void(TypedResponse< BlockForIndexResponse > &)> GetBlockForIndexCallback
ContentAddressedAppendOnlyTree(std::unique_ptr< Store > store, std::shared_ptr< ThreadPool > workers, const std::vector< fr > &initial_values={}, bool commit_genesis_state=true)
std::function< void(TypedResponse< RemoveHistoricResponse > &)> RemoveHistoricBlockCallback
ContentAddressedAppendOnlyTree(ContentAddressedAppendOnlyTree const &other)=delete
EmptyResponseCallback CheckpointCommitCallback
void find_leaf_sibling_paths(const std::vector< typename Store::LeafType > &leaves, bool includeUncommitted, const FindSiblingPathCallback &on_completion) const
Returns the sibling paths for the provided leaves in the tree.
std::unique_ptr< ReadTransaction > ReadTransactionPtr
typename PersistedStoreType::ReadTransaction ReadTransaction
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 wait_for_level(uint32_t level=0)
Causes the thread to wait until the required level has been signalled.
std::string format(Args... args)
ContentAddressedCachedTreeStore< bb::fr > Store
void add_values(TreeType &tree, const std::vector< NullifierLeafValue > &values)
void hash(State &state) noexcept
void execute_and_report(const std::function< void(TypedResponse< ResponseType > &)> &f, const std::function< void(TypedResponse< ResponseType > &)> &on_completion)
std::vector< fr > fr_sibling_path
constexpr uint64_t pow64(const uint64_t input, const uint64_t exponent)
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::optional< fr > right
std::optional< index_t > maxIndex
std::optional< block_number_t > blockNumber
static constexpr field zero()