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.
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()