2#include "../fixtures.hpp"
4#include "../node_store/array_store.hpp"
5#include "../nullifier_tree/nullifier_memory_tree.hpp"
6#include "../test_fixtures.hpp"
80 std::filesystem::create_directories(
_directory);
102 std::filesystem::path directory = rootDirectory;
103 directory.append(name);
104 std::filesystem::create_directories(directory);
110template <
typename TypeOfTree>
void check_size(TypeOfTree& tree,
index_t expected_size,
bool includeUncommitted =
true)
114 EXPECT_EQ(response.success,
true);
115 EXPECT_EQ(response.inner.meta.size, expected_size);
118 tree.get_meta_data(includeUncommitted, completion);
122template <
typename TypeOfTree>
fr get_root(TypeOfTree& tree,
bool includeUncommitted =
true)
127 r = response.inner.meta.root;
130 tree.get_meta_data(includeUncommitted, completion);
135template <
typename TypeOfTree>
void check_root(TypeOfTree& tree,
fr expected_root,
bool includeUncommitted =
true)
138 EXPECT_EQ(root, expected_root);
141template <
typename TypeOfTree>
145 bool includeUncommitted =
true,
146 bool expected_success =
true)
151 EXPECT_EQ(response.success, expected_success);
152 if (response.success) {
153 h = response.inner.path;
157 tree.get_sibling_path(
index, blockNumber, completion, includeUncommitted);
162template <
typename LeafValueType,
typename TypeOfTree>
165 bool includeUncommitted =
true,
166 bool expected_success =
true)
171 EXPECT_EQ(leaf.success, expected_success);
173 l = leaf.inner.indexed_leaf;
177 tree.get_leaf(
index, includeUncommitted, completion);
182template <
typename LeafValueType,
typename TypeOfTree>
187 auto completion = [&](
const auto& leaf) ->
void {
188 low_leaf_info = leaf.inner;
191 tree.find_low_leaf(leaf.
get_key(), includeUncommitted, completion);
193 return low_leaf_info;
196template <
typename LeafValueType,
typename TypeOfTree>
200 bool includeUncommitted =
true)
204 auto completion = [&](
const auto& leaf) ->
void {
205 low_leaf_info = leaf.inner;
208 tree.find_low_leaf(leaf.
get_key(), blockNumber, includeUncommitted, completion);
210 return low_leaf_info;
213template <
typename LeafValueType,
typename TypeOfTree>
218 bool expected_success,
219 bool includeUncommitted =
true)
223 EXPECT_EQ(response.success, expected_success);
224 if (response.success) {
225 EXPECT_EQ(response.inner.indexed_leaf.value().leaf, leaf);
230 tree.get_leaf(expected_index, blockNumber, includeUncommitted, completion);
234template <
typename TypeOfTree>
239 bool includeUncommitted =
true,
240 bool expected_success =
true)
243 if (expected_success) {
244 EXPECT_EQ(path, expected_sibling_path);
248template <
typename TypeOfTree>
252 bool includeUncommitted =
true,
253 bool expected_success =
true)
256 EXPECT_EQ(path, expected_sibling_path);
263 EXPECT_EQ(response.success,
true);
264 EXPECT_EQ(response.inner.meta.unfinalizedBlockHeight, expected_block_height);
267 tree.get_meta_data(
true, completion);
271template <
typename TypeOfTree>
void commit_tree(TypeOfTree& tree,
bool expectedSuccess =
true)
275 EXPECT_EQ(response.success, expectedSuccess);
278 tree.commit(completion);
282template <
typename LeafValueType,
typename TypeOfTree>
287 EXPECT_EQ(response.success, expectedSuccess);
291 tree.add_or_update_value(
value, completion);
295template <
typename LeafValueType,
typename TypeOfTree>
301 EXPECT_EQ(response.success, expectedSuccess);
305 tree.add_or_update_values_sequentially(values, completion);
309template <
typename LeafValueType,
typename TypeOfTree>
314 EXPECT_EQ(response.success, expectedSuccess);
318 tree.add_or_update_values(values, completion);
322template <
typename LeafValueType,
typename TypeOfTree>
327 EXPECT_EQ(response.success, expectedSuccess);
331 tree.add_or_update_values_sequentially(values, completion);
335template <
typename LeafValueType,
typename TypeOfTree>
340 EXPECT_EQ(response.success, expectedSuccess);
344 tree.add_or_update_values(values, completion);
348template <
typename LeafValueType,
typename TypeOfTree>
351 bool expectedSuccess =
true)
355 EXPECT_EQ(response.success, expectedSuccess);
359 tree.add_or_update_values_sequentially(values, completion);
363template <
typename TypeOfTree>
368 EXPECT_EQ(response.success, expected_success);
371 tree.remove_historic_block(blockNumber, completion);
375template <
typename TypeOfTree>
379 auto completion = [&](
const Response& response) ->
void {
380 EXPECT_EQ(response.success, expected_success);
383 tree.finalize_block(blockNumber, completion);
387template <
typename TypeOfTree>
392 EXPECT_EQ(response.success, expected_success);
395 tree.unwind_block(blockNumber, completion);
403 EXPECT_EQ(response.success,
true);
404 EXPECT_EQ(response.inner.meta.unfinalizedBlockHeight, expected_block_height);
407 tree.get_meta_data(
true, completion);
413 constexpr size_t depth = 10;
428 constexpr size_t depth = 10;
433 EXPECT_ANY_THROW(
Store(
"Wrong name", depth, db));
434 EXPECT_ANY_THROW(
Store(name, depth + 1, db));
441 constexpr size_t depth = 10;
450 for (uint32_t i = 0; i < 4; i++) {
461 constexpr size_t depth = 10;
465 EXPECT_THROW(
TreeType(
std::move(store), workers, current_size), std::runtime_error);
473 constexpr size_t depth = 4;
480 for (uint32_t i = 0; i < 14; i++) {
485 std::stringstream ss;
486 ss <<
"Unable to insert values into tree " << name <<
" new size: 17 max size: 16";
490 EXPECT_EQ(response.success,
false);
491 EXPECT_EQ(response.message, ss.str());
500 constexpr size_t depth = 10;
529 uint32_t num_to_append = 512;
531 for (uint32_t i = 0; i < num_to_append; i += 2) {
534 add_values<NullifierLeafValue>(tree,
537 check_size(tree, num_to_append + current_size);
547 constexpr size_t depth = 10;
560 check_find_leaf_index<NullifierLeafValue, TreeType>(
564 check_find_leaf_index<NullifierLeafValue, TreeType>(
571 check_find_leaf_index<NullifierLeafValue, TreeType>(
573 check_find_leaf_index<NullifierLeafValue, TreeType>(
575 check_find_leaf_index<NullifierLeafValue, TreeType>(
594 check_find_leaf_index<NullifierLeafValue, TreeType>(
611 index_t current_size = initial_size;
614 constexpr size_t depth = 10;
670void test_batch_insert(uint32_t batchSize, std::string directory, uint64_t mapSize, uint64_t maxReaders)
673 const uint32_t batch_size = batchSize;
674 const uint32_t num_batches = 16;
680 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
681 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
682 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
684 for (uint32_t i = 0; i < num_batches; i++) {
699 for (uint32_t j = 0; j < batch_size; j++) {
702 memory_tree_sibling_paths.push_back(path);
710 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
713 tree1->add_or_update_values(batch, completion);
721 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
724 tree2->add_or_update_values(batch, completion);
731 tree3->add_or_update_values(batch, completion);
746 for (uint32_t j = 0; j < batch_size; j++) {
747 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
748 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
749 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
755 std::string directory,
760 const uint32_t batch_size = batchSize;
761 const uint32_t num_batches = 16;
767 for (uint32_t i = 0; i < num_batches; i++) {
769 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
770 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
771 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
786 for (uint32_t j = 0; j < batch_size; j++) {
789 memory_tree_sibling_paths.push_back(path);
797 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
800 tree1->add_or_update_values(batch, completion);
808 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
811 tree2->add_or_update_values(batch, completion);
818 tree3->add_or_update_values(batch, completion);
833 for (uint32_t j = 0; j < batch_size; j++) {
834 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
835 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
836 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
847 uint32_t batchSize = 2;
848 while (batchSize <= 2) {
856 uint32_t batchSize = 2;
857 while (batchSize <= 32) {
865 const uint32_t batch_size = 128;
870 auto tree1 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
871 auto tree2 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
874 for (uint32_t i = 1; i <= 12; i++) {
876 auto tree =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, multiWorkers);
880 std::vector<fr> tree1Roots;
881 std::vector<fr> tree2Roots;
883 for (uint32_t round = 0; round < 10; round++) {
884 std::vector<fr> frValues1 = create_values(3);
885 std::vector<fr> frValues2 = create_values(3);
887 for (uint32_t i = 0; i < 3; i++) {
888 leaves[i] = frValues1[i];
889 leaves[i + 64] = frValues2[i];
900 tree1Roots.push_back(
get_root(*tree1));
901 tree2Roots.push_back(
get_root(*tree2,
true));
902 EXPECT_EQ(tree1Roots[round], tree2Roots[round]);
904 for (
const auto& tree : trees) {
907 EXPECT_EQ(treeRoot, tree1Roots[round]);
917 constexpr size_t depth = 10;
924 for (uint32_t i = 0; i < 16; i++) {
927 values[8] = values[0];
929 std::stringstream ss;
930 ss <<
"Duplicate key not allowed in same batch, key value: " << values[0].nullifier <<
", tree: " << name;
934 EXPECT_EQ(response.success,
false);
935 EXPECT_EQ(response.message, ss.str());
938 tree.add_or_update_values(values, add_completion);
945 const uint32_t batch_size = batchSize;
946 const uint32_t num_batches = 16;
952 auto sequential_tree_1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
953 auto sequential_tree_2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
954 auto sequential_tree_3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
955 auto batch_tree =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
957 for (uint32_t i = 0; i < num_batches; i++) {
975 for (uint32_t j = 0; j < batch_size; j++) {
978 memory_tree_sibling_paths.push_back(path);
982 sequential_tree_1_insertion_witness_data;
985 sequential_tree_2_insertion_witness_data;
991 sequential_tree_1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
992 sequential_tree_1_insertion_witness_data = response.inner.insertion_witness_data;
995 sequential_tree_1->add_or_update_values_sequentially(batch, completion);
1003 sequential_tree_2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
1004 sequential_tree_2_insertion_witness_data = response.inner.insertion_witness_data;
1007 sequential_tree_2->add_or_update_values_sequentially(batch, completion);
1014 sequential_tree_3->add_or_update_values_sequentially(batch, completion);
1021 batch_tree->add_or_update_values(batch, completion);
1039 for (uint32_t j = 0; j < batch_size; j++) {
1040 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).leaf,
1041 sequential_tree_2_low_leaf_witness_data->at(j).leaf);
1042 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).index,
1043 sequential_tree_2_low_leaf_witness_data->at(j).index);
1044 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).path,
1045 sequential_tree_2_low_leaf_witness_data->at(j).path);
1047 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).leaf,
1048 sequential_tree_2_insertion_witness_data->at(j).leaf);
1049 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).index,
1050 sequential_tree_2_insertion_witness_data->at(j).index);
1051 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).path,
1052 sequential_tree_2_insertion_witness_data->at(j).path);
1059 uint32_t batchSize = 2;
1060 while (batchSize <= 2) {
1071 constexpr size_t depth = 3;
1077 std::move(store), workers, current_size);
1082 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 2).leaf.value, values[1].value);
1096 uint32_t depth_ =
static_cast<uint32_t
>(path.size());
1097 uint32_t
index = idx;
1098 for (uint32_t i = 0; i < depth_; ++i) {
1099 fr left = (
index & 1) ? path[i] : current;
1100 fr right = (
index & 1) ? current : path[i];
1104 return current == root;
1112 constexpr size_t depth = 3;
1130 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 0), zero_leaf);
1131 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 1), one_leaf);
1208 auto e000 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 0));
1209 auto e001 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 1));
1210 auto e010 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 2));
1211 auto e011 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 3));
1212 auto e100 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 4));
1213 auto e101 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 5));
1275 constexpr uint32_t depth = 8;
1286 for (uint32_t i = 0; i < 20; i++) {
1305 for (uint32_t i = 0; i < uint32_t(21); i++) {
1307 abs_diff(
uint256_t(new_member),
uint256_t(get_leaf<NullifierLeafValue>(tree, i).leaf.get_key()));
1309 abs_diff(
uint256_t(new_member),
uint256_t(get_leaf<NullifierLeafValue>(tree, i).leaf.get_key()));
1310 differences.push_back(diff_hi + diff_lo);
1313 auto index =
static_cast<uint32_t
>(it - differences.begin());
1321 constexpr size_t depth = 10;
1327 uint32_t num_reads = 16 * 1024;
1339 Signal signal(1 + num_reads);
1343 tree.
commit(commit_completion);
1345 tree.add_or_update_value(
get_value(0), add_completion);
1347 for (
size_t i = 0; i < num_reads; i++) {
1349 paths[i] = response.inner.path;
1363 constexpr size_t depth = 3;
1369 std::move(store), workers, current_size);
1384 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1385 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1460 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1461 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1462 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1463 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1465 auto e101 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 5));
1524 constexpr size_t depth = 3;
1530 std::move(store), workers, current_size);
1545 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1546 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1619 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1620 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1621 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1622 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1623 auto e100 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 4));
1681 constexpr uint32_t depth = 8;
1691 EXPECT_EQ(predecessor.is_already_present,
false);
1692 EXPECT_EQ(predecessor.index, 1);
1698 EXPECT_EQ(predecessor.is_already_present,
true);
1699 EXPECT_EQ(predecessor.index, 2);
1705 constexpr uint32_t depth = 8;
1728 const uint32_t batch_size = 16;
1729 const uint32_t num_batches = 8;
1732 uint32_t depth = 10;
1742 auto check = [&]() {
1747 for (uint32_t i = 0; i < memory_tree_sibling_paths_index_0.size(); i++) {
1752 for (uint32_t i = 0; i < num_batches; i++) {
1760 for (uint32_t j = 0; j < batch_size; j++) {
1771 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
1774 tree1.add_or_update_values(batch, completion);
1790 constexpr size_t depth = 3;
1795 using LocalTreeType =
1797 auto tree = LocalTreeType(
std::move(store), workers, current_size);
1812 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1813 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1907 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
1913 EXPECT_EQ(lowLeaf.
index, 1);
1916 EXPECT_EQ(lowLeaf.
index, 3);
1919 EXPECT_EQ(lowLeaf.
index, 2);
1924 const uint32_t batch_size = 16;
1925 uint32_t depth = 10;
1934 std::vector<fr> values = create_values(batch_size);
1937 values.begin(), values.end(), nullifierValues.begin(), [](
const fr& v) { return NullifierLeafValue(v); });
1943 std::vector<fr> values2 = create_values(batch_size);
1946 values2[batch_size / 2] = values[0];
1949 values2.begin(), values2.end(), nullifierValues2.begin(), [](
const fr& v) { return NullifierLeafValue(v); });
1955 const uint32_t batch_size = 16;
1956 uint32_t depth = 10;
1965 std::vector<fr> values = create_values(batch_size);
1968 values.begin(), values.end(), nullifierValues.begin(), [](
const fr& v) { return NullifierLeafValue(v); });
1973 std::vector<fr> values2 = create_values(batch_size);
1976 values2[batch_size / 2] = values[0];
1979 values2.begin(), values2.end(), nullifierValues2.begin(), [](
const fr& v) { return NullifierLeafValue(v); });
1986 const uint32_t batch_size = 16;
1987 uint32_t depth = 10;
2002 for (uint32_t j = 0; j < batch_size; j++) {
2013 for (uint32_t j = 0; j < batch_size; j++) {
2021 fr block2Root = memdb.
root();
2027 for (uint32_t j = 0; j < batch_size; j++) {
2040 auto treeAtBlock2 =
TreeType(
std::move(storeAtBlock2), multi_workers, batch_size);
2043 check_sibling_path(treeAtBlock2, 3 + batch_size, block2SiblingPathIndex3,
false,
true);
2044 auto block2TreeLeaf10 = get_leaf<NullifierLeafValue>(treeAtBlock2, 7 + batch_size);
2045 EXPECT_EQ(block2TreeLeaf10.leaf.nullifier, batch1[7].nullifier);
2051 get_leaf<NullifierLeafValue>(treeAtBlock2, 35 + batch_size,
false,
false);
2052 check_find_leaf_index<NullifierLeafValue, TreeType>(treeAtBlock2, { batch3[4] }, {
std::nullopt },
true);
2063 check_sibling_path(treeAtBlock2, 3 + batch_size, block3SiblingPathIndex3,
true,
true);
2064 check_sibling_path(treeAtBlock2, 19 + batch_size, block3SiblingPathIndex19,
true,
true);
2065 check_sibling_path(treeAtBlock2, 35 + batch_size, block3SiblingPathIndex35,
true,
true);
2069 EXPECT_EQ(historicSiblingPath, block1SiblingPathIndex3);
2072 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2073 treeAtBlock2, { batch3[3] }, 2, {
std::nullopt },
true,
false);
2076 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2077 treeAtBlock2, { batch3[3] }, 2, 20 + batch_size, {
std::nullopt },
true,
false);
2091 constexpr size_t depth = 3;
2096 using LocalTreeType =
2098 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2113 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2114 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2214 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2220 EXPECT_EQ(lowLeaf.
index, 1);
2223 EXPECT_EQ(lowLeaf.
index, 3);
2226 EXPECT_EQ(lowLeaf.
index, 2);
2235 check_historic_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2255 constexpr size_t depth = 3;
2260 using LocalTreeType =
2262 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2277 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2278 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2280 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2281 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2307 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2308 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2335 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2336 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2371 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2372 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2412 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2413 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2426 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2432 EXPECT_EQ(lowLeaf.
index, 1);
2435 EXPECT_EQ(lowLeaf.
index, 3);
2438 EXPECT_EQ(lowLeaf.
index, 2);
2445 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2446 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2466 check_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2468 check_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2480 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2481 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2500 constexpr size_t depth = 3;
2506 std::move(store), workers, current_size);
2521 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2522 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2546 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2547 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2573 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2574 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2599 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2600 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2618 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2619 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2637 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2638 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2660 uint64_t maxReaders,
2664 uint32_t numBlocksToUnwind,
2665 std::vector<fr> values)
2673 auto it =
std::find_if(values.begin(), values.end(), [&](
const fr& v) { return v != fr::zero(); });
2674 bool emptyBlocks = it == values.end();
2676 uint32_t batchSize = blockSize;
2680 std::vector<fr> roots;
2682 fr initialRoot = memdb.
root();
2686 leafValues.reserve(values.size());
2687 for (
const fr& v : values) {
2688 leafValues.emplace_back(v);
2691 for (uint32_t i = 0; i < numBlocks; i++) {
2694 for (
size_t j = 0; j < batchSize; ++j) {
2695 size_t ind = i * batchSize + j;
2697 to_add.push_back(leafValues[ind]);
2700 index_t expected_size = (i + 2) * batchSize;
2705 historicPathsMaxIndex.push_back(memdb.
get_sibling_path(expected_size - 1));
2706 roots.push_back(memdb.
root());
2715 const uint32_t blocksToRemove = numBlocksToUnwind;
2716 for (uint32_t i = 0; i < blocksToRemove; i++) {
2729 const index_t previousValidBlock = blockNumber - 1;
2731 index_t deletedBlockStartIndex = (1 + previousValidBlock) * batchSize;
2732 index_t deletedBlockStartIndexIntoLocalValues = previousValidBlock * batchSize;
2736 check_root(tree, previousValidBlock == 0 ? initialRoot : roots[previousValidBlock - 1]);
2741 previousValidBlock == 0 ? initialPath : historicPathsZeroIndex[previousValidBlock - 1],
2747 get_leaf<NullifierLeafValue>(tree, 1 + deletedBlockStartIndex,
false,
false);
2749 check_find_leaf_index<NullifierLeafValue, TreeType>(
2750 tree, { leafValues[1 + deletedBlockStartIndexIntoLocalValues] }, {
std::nullopt },
true);
2753 for (
index_t j = 0; j < numBlocks; j++) {
2755 bool expectedSuccess = historicBlockNumber <= previousValidBlock;
2757 tree, 0, historicBlockNumber, historicPathsZeroIndex[j],
false, expectedSuccess);
2758 index_t maxSizeAtBlock = ((j + 2) * batchSize) - 1;
2760 tree, maxSizeAtBlock, historicBlockNumber, historicPathsMaxIndex[j],
false, expectedSuccess);
2766 const index_t expectedIndexInTree = leafIndex + batchSize;
2768 tree, leafValues[leafIndex], expectedIndexInTree, historicBlockNumber, expectedSuccess,
false);
2771 if (expectedSuccess) {
2774 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2775 tree, { leafValues[leafIndex] }, historicBlockNumber, expectedResults, expectedSuccess,
true);
2776 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2777 tree, { leafValues[leafIndex] }, historicBlockNumber, 0, expectedResults, expectedSuccess,
true);
2785 constexpr uint32_t numBlocks = 8;
2786 constexpr uint32_t numBlocksToUnwind = 4;
2787 std::vector<uint32_t> blockSizes = { 2, 4, 8, 16, 32 };
2788 for (
const uint32_t& size : blockSizes) {
2789 uint32_t actualSize = size;
2790 std::vector<fr> values = create_values(actualSize * numBlocks);
2791 std::stringstream ss;
2792 ss <<
"DB " << actualSize;
2794 _directory, ss.str(), _mapSize, _maxReaders, 20, actualSize, numBlocks, numBlocksToUnwind, values);
2801 constexpr uint32_t numBlocks = 8;
2802 constexpr uint32_t numBlocksToUnwind = 4;
2803 std::vector<uint32_t> blockSizes = { 2, 4, 8, 16, 32 };
2804 for (
const uint32_t& size : blockSizes) {
2805 uint32_t actualSize = size;
2806 std::vector<fr> values = std::vector<fr>(actualSize * numBlocks,
fr::zero());
2807 std::stringstream ss;
2808 ss <<
"DB " << actualSize;
2810 _directory, ss.str(), _mapSize, _maxReaders, 20, actualSize, numBlocks, numBlocksToUnwind, values);
2817 constexpr size_t depth = 3;
2841 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), leaf_0);
2842 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), leaf_1);
2843 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 2), leaf_2);
2844 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 3), leaf_3);
2850 constexpr size_t depth = 3;
2876 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), leaf_0);
2877 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), leaf_1);
2878 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 2), leaf_2);
2879 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 3), leaf_3);
2885 constexpr size_t depth = 3;
2899 constexpr size_t depth = 3;
2913 index_t current_size = initial_size;
2916 constexpr size_t depth = 3;
2922 std::move(store), workers, current_size);
2977 index_t fork_size = current_size;
2982 std::move(forkStore), workers, initial_size);
2988 EXPECT_EQ(predecessor.is_already_present,
false);
2989 EXPECT_EQ(predecessor.index, 2);
3016 EXPECT_EQ(predecessor.is_already_present,
false);
3017 EXPECT_EQ(predecessor.index, 4);
3031 EXPECT_EQ(predecessor.is_already_present,
false);
3032 EXPECT_EQ(predecessor.index, 2);
3063 EXPECT_EQ(predecessor.is_already_present,
false);
3064 EXPECT_EQ(predecessor.index, 4);
3091 EXPECT_EQ(predecessor.is_already_present,
false);
3092 EXPECT_EQ(predecessor.index, 4);
3121 EXPECT_EQ(predecessor.is_already_present,
false);
3122 EXPECT_EQ(predecessor.index, 4);
3128 EXPECT_EQ(predecessor.is_already_present,
false);
3129 EXPECT_EQ(predecessor.index, 5);
3147 EXPECT_EQ(predecessor.is_already_present,
false);
3148 EXPECT_EQ(predecessor.index, 4);
3154 EXPECT_EQ(predecessor.is_already_present,
false);
3155 EXPECT_EQ(predecessor.index, 5);
3183 EXPECT_EQ(predecessor.is_already_present,
false);
3184 EXPECT_EQ(predecessor.index, 4);
3190 EXPECT_EQ(predecessor.is_already_present,
false);
3191 EXPECT_EQ(predecessor.index, 2);
3197 std::vector<fr> values = create_values(size);
3199 for (uint32_t j = 0; j < size; j++) {
3200 leaves.emplace_back(values[j]);
3209 constexpr size_t depth = 10;
3210 std::string name =
"Nullifier Tree";
3221 uint32_t size_to_insert = 8;
3222 uint32_t num_insertions = 5;
3224 for (uint32_t i = 0; i < num_insertions - 1; i++) {
3226 current_size += size_to_insert;
3232 current_size += size_to_insert;
3236 current_size -= size_to_insert;
3245 current_size += size_to_insert;
3264 throw std::runtime_error(
"injected failure from put_cached_node_by_index");
3278 constexpr size_t depth = 6;
3279 constexpr index_t initial_size = 2;
3284 auto* raw_store = store.get();
3298 raw_store->throw_on_put_cached_node_by_index =
true;
3301 bool callback_success =
false;
3302 std::string callback_message;
3309 callback_success = response.
success;
3310 callback_message = response.
message;
3317 EXPECT_GT(raw_store->num_put_cached_node_calls.load(), 0);
3320 EXPECT_FALSE(callback_success);
3321 EXPECT_FALSE(callback_message.empty());
static std::string _directory
static uint64_t _maxReaders
std::atomic< bool > throw_on_put_cached_node_by_index
void put_cached_node_by_index(uint32_t level, index_t index, const fr &value)
std::atomic< uint64_t > num_put_cached_node_calls
Implements a simple append-only merkle tree All methods are asynchronous unless specified as otherwis...
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.
Serves as a key-value node store for merkle trees. Caches all changes in memory before persisting the...
void put_cached_node_by_index(uint32_t level, const index_t &index, const fr &data, bool overwriteIfPresent=true)
Writes the provided data at the given node coordinates. Only writes to uncommitted data.
Implements a parallelized batch insertion indexed tree Accepts template argument of the type of store...
std::function< void(TypedResponse< AddIndexedDataSequentiallyResponse< LeafValueType > > &)> AddSequentiallyCompletionCallbackWithWitness
void perform_updates_without_witness(const index_t &highest_index, std::shared_ptr< std::vector< LeafUpdate > > updates, const UpdatesCompletionCallback &completion)
std::function< void(const TypedResponse< UpdatesCompletionResponse > &)> UpdatesCompletionCallback
std::function< void(TypedResponse< AddIndexedDataResponse< LeafValueType > > &)> AddCompletionCallbackWithWitness
std::shared_ptr< LMDBTreeStore > SharedPtr
fr_sibling_path get_sibling_path(size_t index) const
fr_sibling_path update_element(fr const &value)
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.
void commit_tree(TypeOfTree &tree, bool expectedSuccess=true)
void test_batch_insert(uint32_t batchSize, std::string directory, uint64_t mapSize, uint64_t maxReaders)
ContentAddressedCachedTreeStore< NullifierLeafValue > Store
fr get_root(TypeOfTree &tree, bool includeUncommitted=true)
void advance_state(TreeType &fork, uint32_t size)
void add_value_sequentially(TypeOfTree &tree, const LeafValueType &value, bool expectedSuccess=true)
void add_values(TypeOfTree &tree, const std::vector< LeafValueType > &values, bool expectedSuccess=true)
void add_values_sequentially(TypeOfTree &tree, const std::vector< LeafValueType > &values, bool expectedSuccess=true)
void check_sibling_path(TypeOfTree &tree, index_t index, const fr_sibling_path &expected_sibling_path, bool includeUncommitted=true, bool expected_success=true)
TreeType::AddCompletionCallbackWithWitness CompletionCallback
void check_historic_sibling_path(TypeOfTree &tree, index_t index, block_number_t blockNumber, const fr_sibling_path &expected_sibling_path, bool includeUncommitted=true, bool expected_success=true)
void test_batch_insert_with_commit_restore(uint32_t batchSize, std::string directory, uint64_t mapSize, uint64_t maxReaders)
ContentAddressedIndexedTree< PublicDataStore, Poseidon2HashPolicy > PublicDataTreeType
IndexedNullifierLeafType create_indexed_nullifier_leaf(const fr &value, index_t nextIndex, const fr &nextValue)
void add_value(TypeOfTree &tree, const LeafValueType &value, bool expectedSuccess=true)
std::unique_ptr< TreeType > create_tree(const std::string &rootDirectory, uint64_t mapSize, uint64_t maxReaders, uint32_t depth, uint32_t batchSize, ThreadPoolPtr workers)
fr_sibling_path get_historic_sibling_path(TypeOfTree &tree, block_number_t blockNumber, index_t index, bool includeUncommitted=true, bool expected_success=true)
GetLowIndexedLeafResponse get_historic_low_leaf(TypeOfTree &tree, block_number_t blockNumber, const LeafValueType &leaf, bool includeUncommitted=true)
void test_sequential_insert_vs_batch(uint32_t batchSize, std::string directory, uint64_t mapSize, uint64_t maxReaders)
void check_block_height(TypeOfTree &tree, index_t expected_block_height)
IndexedLeaf< LeafValueType > get_leaf(TypeOfTree &tree, index_t index, bool includeUncommitted=true, bool expected_success=true)
void check_root(TypeOfTree &tree, fr expected_root, bool includeUncommitted=true)
GetLowIndexedLeafResponse get_low_leaf(TypeOfTree &tree, const LeafValueType &leaf, bool includeUncommitted=true)
void check_historic_leaf(TypeOfTree &tree, const LeafValueType &leaf, index_t expected_index, block_number_t blockNumber, bool expected_success, bool includeUncommitted=true)
void block_sync_values_sequential(TypeOfTree &tree, const std::vector< LeafValueType > &values, bool expectedSuccess=true)
IndexedPublicDataLeafType create_indexed_public_data_leaf(const fr &slot, const fr &value, index_t nextIndex, const fr &nextValue)
void check_unfinalized_block_height(TypeOfTree &tree, index_t expected_block_height)
void test_nullifier_tree_unwind(std::string directory, std::string name, uint64_t mapSize, uint64_t maxReaders, uint32_t depth, uint32_t blockSize, uint32_t numBlocks, uint32_t numBlocksToUnwind, std::vector< fr > values)
void check_size(TypeOfTree &tree, index_t expected_size, bool includeUncommitted=true)
ContentAddressedIndexedTree< Store, HashPolicy > TreeType
void remove_historic_block(TypeOfTree &tree, const block_number_t &blockNumber, bool expected_success=true)
void block_sync_values(TypeOfTree &tree, const std::vector< LeafValueType > &values, bool expectedSuccess=true)
fr hash_leaf(const IndexedLeaf< LeafValueType > &leaf)
void finalize_block(TypeOfTree &tree, const block_number_t &blockNumber, bool expected_success=true)
void unwind_block(TypeOfTree &tree, const block_number_t &blockNumber, bool expected_success=true)
TreeType::AddSequentiallyCompletionCallbackWithWitness SequentialCompletionCallback
bool verify_sibling_path(TreeType &tree, const IndexedNullifierLeafType &leaf_value, const uint32_t idx)
ThreadPoolPtr make_thread_pool(uint64_t numThreads)
const fr & get_value(size_t index)
void check_indices_data(LMDBTreeStore::SharedPtr db, fr leaf, index_t index, bool entryShouldBePresent, bool indexShouldBePresent)
void check_historic_find_leaf_index_from(TypeOfTree &tree, const std::vector< LeafValueType > &leaves, block_number_t blockNumber, index_t start_index, const std::vector< std::optional< index_t > > &expected_indices, bool expected_success, bool includeUncommitted=true)
std::string random_temp_directory()
uint32_t checkpoint_tree(TreeType &tree)
void check_find_leaf_index(TypeOfTree &tree, const std::vector< LeafValueType > &leaves, const std::vector< std::optional< index_t > > &expected_indices, bool expected_success, bool includeUncommitted=true)
void check_block_and_root_data(LMDBTreeStore::SharedPtr db, block_number_t blockNumber, fr root, bool expectedSuccess)
void check_find_leaf_index_from(TypeOfTree &tree, const std::vector< LeafValueType > &leaves, index_t start_index, const std::vector< std::optional< index_t > > &expected_indices, bool expected_success, bool includeUncommitted=true)
std::string random_string()
std::shared_ptr< ThreadPool > ThreadPoolPtr
void check_block_and_size_data(LMDBTreeStore::SharedPtr db, block_number_t blockNumber, index_t expectedSize, bool expectedSuccess)
void commit_checkpoint_tree(TreeType &tree, bool expected_success=true)
std::vector< fr > fr_sibling_path
void revert_checkpoint_tree(TreeType &tree, bool expected_success=true)
void check_historic_find_leaf_index(TypeOfTree &tree, const std::vector< LeafValueType > &leaves, block_number_t blockNumber, const std::vector< std::optional< index_t > > &expected_indices, bool expected_success, bool includeUncommitted=true)
fr_sibling_path get_sibling_path(TypeOfTree &tree, index_t index, bool includeUncommitted=true, bool expected_success=true)
Key get_key(int64_t keyCount)
Entry point for Barretenberg command-line interface.
TEST_F(IPATest, ChallengesAreZero)
field< Bn254FrParams > fr
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
typename Tree::UpdatesCompletionCallback UpdatesCompletionCallback
typename Tree::UpdatesCompletionResponse UpdatesCompletionResponse
static void perform_updates_without_witness(Tree &tree, const index_t &highest_index, std::shared_ptr< std::vector< LeafUpdate > > updates, const UpdatesCompletionCallback &completion)
typename Tree::LeafUpdate LeafUpdate
static IndexedLeaf< LeafType > empty()
std::vector< fr > get_hash_inputs() const
static fr hash_pair(const fr &lhs, const fr &rhs)
static fr hash(const std::vector< fr > &inputs)
static field random_element(numeric::RNG *engine=nullptr) noexcept
static constexpr field zero()