638void test_batch_insert(uint32_t batchSize, std::string directory, uint64_t mapSize, uint64_t maxReaders)
641 const uint32_t batch_size = batchSize;
642 const uint32_t num_batches = 16;
648 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
649 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
650 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
652 for (uint32_t i = 0; i < num_batches; i++) {
667 for (uint32_t j = 0; j < batch_size; j++) {
670 memory_tree_sibling_paths.push_back(path);
678 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
681 tree1->add_or_update_values(batch, completion);
689 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
692 tree2->add_or_update_values(batch, completion);
699 tree3->add_or_update_values(batch, completion);
714 for (uint32_t j = 0; j < batch_size; j++) {
715 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
716 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
717 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
723 std::string directory,
728 const uint32_t batch_size = batchSize;
729 const uint32_t num_batches = 16;
735 for (uint32_t i = 0; i < num_batches; i++) {
737 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
738 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
739 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
754 for (uint32_t j = 0; j < batch_size; j++) {
757 memory_tree_sibling_paths.push_back(path);
765 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
768 tree1->add_or_update_values(batch, completion);
776 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
779 tree2->add_or_update_values(batch, completion);
786 tree3->add_or_update_values(batch, completion);
801 for (uint32_t j = 0; j < batch_size; j++) {
802 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
803 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
804 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
833 const uint32_t batch_size = 128;
838 auto tree1 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
839 auto tree2 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
842 for (uint32_t i = 1; i <= 12; i++) {
844 auto tree =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, multiWorkers);
848 std::vector<fr> tree1Roots;
849 std::vector<fr> tree2Roots;
851 for (uint32_t round = 0; round < 10; round++) {
852 std::vector<fr> frValues1 = create_values(3);
853 std::vector<fr> frValues2 = create_values(3);
855 for (uint32_t i = 0; i < 3; i++) {
856 leaves[i] = frValues1[i];
857 leaves[i + 64] = frValues2[i];
868 tree1Roots.push_back(
get_root(*tree1));
869 tree2Roots.push_back(
get_root(*tree2,
true));
870 EXPECT_EQ(tree1Roots[round], tree2Roots[round]);
872 for (
const auto& tree : trees) {
875 EXPECT_EQ(treeRoot, tree1Roots[round]);
913 const uint32_t batch_size = batchSize;
914 const uint32_t num_batches = 16;
920 auto sequential_tree_1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
921 auto sequential_tree_2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
922 auto sequential_tree_3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
923 auto batch_tree =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
925 for (uint32_t i = 0; i < num_batches; i++) {
943 for (uint32_t j = 0; j < batch_size; j++) {
946 memory_tree_sibling_paths.push_back(path);
950 sequential_tree_1_insertion_witness_data;
953 sequential_tree_2_insertion_witness_data;
959 sequential_tree_1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
960 sequential_tree_1_insertion_witness_data = response.inner.insertion_witness_data;
963 sequential_tree_1->add_or_update_values_sequentially(batch, completion);
971 sequential_tree_2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
972 sequential_tree_2_insertion_witness_data = response.inner.insertion_witness_data;
975 sequential_tree_2->add_or_update_values_sequentially(batch, completion);
982 sequential_tree_3->add_or_update_values_sequentially(batch, completion);
989 batch_tree->add_or_update_values(batch, completion);
1007 for (uint32_t j = 0; j < batch_size; j++) {
1008 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).leaf,
1009 sequential_tree_2_low_leaf_witness_data->at(j).leaf);
1010 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).index,
1011 sequential_tree_2_low_leaf_witness_data->at(j).index);
1012 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).path,
1013 sequential_tree_2_low_leaf_witness_data->at(j).path);
1015 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).leaf,
1016 sequential_tree_2_insertion_witness_data->at(j).leaf);
1017 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).index,
1018 sequential_tree_2_insertion_witness_data->at(j).index);
1019 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).path,
1020 sequential_tree_2_insertion_witness_data->at(j).path);
1080 constexpr size_t depth = 3;
1098 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 0), zero_leaf);
1099 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 1), one_leaf);
1176 auto e000 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 0));
1177 auto e001 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 1));
1178 auto e010 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 2));
1179 auto e011 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 3));
1180 auto e100 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 4));
1181 auto e101 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 5));
1331 constexpr size_t depth = 3;
1337 std::move(store), workers, current_size);
1352 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1353 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1428 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1429 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1430 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1431 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1433 auto e101 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 5));
1492 constexpr size_t depth = 3;
1498 std::move(store), workers, current_size);
1513 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1514 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1587 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1588 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1589 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1590 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1591 auto e100 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 4));
1758 constexpr size_t depth = 3;
1763 using LocalTreeType =
1765 auto tree = LocalTreeType(
std::move(store), workers, current_size);
1780 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1781 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1875 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
1881 EXPECT_EQ(lowLeaf.
index, 1);
1884 EXPECT_EQ(lowLeaf.
index, 3);
1887 EXPECT_EQ(lowLeaf.
index, 2);
1954 const uint32_t batch_size = 16;
1955 uint32_t depth = 10;
1970 for (uint32_t j = 0; j < batch_size; j++) {
1981 for (uint32_t j = 0; j < batch_size; j++) {
1989 fr block2Root = memdb.
root();
1995 for (uint32_t j = 0; j < batch_size; j++) {
2008 auto treeAtBlock2 =
TreeType(
std::move(storeAtBlock2), multi_workers, batch_size);
2011 check_sibling_path(treeAtBlock2, 3 + batch_size, block2SiblingPathIndex3,
false,
true);
2012 auto block2TreeLeaf10 = get_leaf<NullifierLeafValue>(treeAtBlock2, 7 + batch_size);
2013 EXPECT_EQ(block2TreeLeaf10.leaf.nullifier, batch1[7].nullifier);
2019 get_leaf<NullifierLeafValue>(treeAtBlock2, 35 + batch_size,
false,
false);
2020 check_find_leaf_index<NullifierLeafValue, TreeType>(treeAtBlock2, { batch3[4] }, {
std::nullopt },
true);
2031 check_sibling_path(treeAtBlock2, 3 + batch_size, block3SiblingPathIndex3,
true,
true);
2032 check_sibling_path(treeAtBlock2, 19 + batch_size, block3SiblingPathIndex19,
true,
true);
2033 check_sibling_path(treeAtBlock2, 35 + batch_size, block3SiblingPathIndex35,
true,
true);
2037 EXPECT_EQ(historicSiblingPath, block1SiblingPathIndex3);
2040 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2041 treeAtBlock2, { batch3[3] }, 2, {
std::nullopt },
true,
false);
2044 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2045 treeAtBlock2, { batch3[3] }, 2, 20 + batch_size, {
std::nullopt },
true,
false);
2059 constexpr size_t depth = 3;
2064 using LocalTreeType =
2066 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2081 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2082 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2182 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2188 EXPECT_EQ(lowLeaf.
index, 1);
2191 EXPECT_EQ(lowLeaf.
index, 3);
2194 EXPECT_EQ(lowLeaf.
index, 2);
2203 check_historic_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2223 constexpr size_t depth = 3;
2228 using LocalTreeType =
2230 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2245 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2246 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2248 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2249 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2275 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2276 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2303 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2304 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2339 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2340 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2380 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2381 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2394 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2400 EXPECT_EQ(lowLeaf.
index, 1);
2403 EXPECT_EQ(lowLeaf.
index, 3);
2406 EXPECT_EQ(lowLeaf.
index, 2);
2413 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2414 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2434 check_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2436 check_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2448 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2449 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2468 constexpr size_t depth = 3;
2474 std::move(store), workers, current_size);
2489 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2490 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2514 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2515 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2541 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2542 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2567 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2568 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2586 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2587 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2605 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2606 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2628 uint64_t maxReaders,
2632 uint32_t numBlocksToUnwind,
2633 std::vector<fr> values)
2641 auto it =
std::find_if(values.begin(), values.end(), [&](
const fr& v) { return v != fr::zero(); });
2642 bool emptyBlocks = it == values.end();
2644 uint32_t batchSize = blockSize;
2648 std::vector<fr> roots;
2650 fr initialRoot = memdb.
root();
2654 leafValues.reserve(values.size());
2655 for (
const fr& v : values) {
2656 leafValues.emplace_back(v);
2659 for (uint32_t i = 0; i < numBlocks; i++) {
2662 for (
size_t j = 0; j < batchSize; ++j) {
2663 size_t ind = i * batchSize + j;
2665 to_add.push_back(leafValues[ind]);
2668 index_t expected_size = (i + 2) * batchSize;
2673 historicPathsMaxIndex.push_back(memdb.
get_sibling_path(expected_size - 1));
2674 roots.push_back(memdb.
root());
2683 const uint32_t blocksToRemove = numBlocksToUnwind;
2684 for (uint32_t i = 0; i < blocksToRemove; i++) {
2697 const index_t previousValidBlock = blockNumber - 1;
2699 index_t deletedBlockStartIndex = (1 + previousValidBlock) * batchSize;
2700 index_t deletedBlockStartIndexIntoLocalValues = previousValidBlock * batchSize;
2704 check_root(tree, previousValidBlock == 0 ? initialRoot : roots[previousValidBlock - 1]);
2709 previousValidBlock == 0 ? initialPath : historicPathsZeroIndex[previousValidBlock - 1],
2715 get_leaf<NullifierLeafValue>(tree, 1 + deletedBlockStartIndex,
false,
false);
2717 check_find_leaf_index<NullifierLeafValue, TreeType>(
2718 tree, { leafValues[1 + deletedBlockStartIndexIntoLocalValues] }, {
std::nullopt },
true);
2721 for (
index_t j = 0; j < numBlocks; j++) {
2723 bool expectedSuccess = historicBlockNumber <= previousValidBlock;
2725 tree, 0, historicBlockNumber, historicPathsZeroIndex[j],
false, expectedSuccess);
2726 index_t maxSizeAtBlock = ((j + 2) * batchSize) - 1;
2728 tree, maxSizeAtBlock, historicBlockNumber, historicPathsMaxIndex[j],
false, expectedSuccess);
2734 const index_t expectedIndexInTree = leafIndex + batchSize;
2736 tree, leafValues[leafIndex], expectedIndexInTree, historicBlockNumber, expectedSuccess,
false);
2739 if (expectedSuccess) {
2742 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2743 tree, { leafValues[leafIndex] }, historicBlockNumber, expectedResults, expectedSuccess,
true);
2744 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2745 tree, { leafValues[leafIndex] }, historicBlockNumber, 0, expectedResults, expectedSuccess,
true);
2881 index_t current_size = initial_size;
2884 constexpr size_t depth = 3;
2890 std::move(store), workers, current_size);
2945 index_t fork_size = current_size;
2950 std::move(forkStore), workers, initial_size);
2956 EXPECT_EQ(predecessor.is_already_present,
false);
2957 EXPECT_EQ(predecessor.index, 2);
2984 EXPECT_EQ(predecessor.is_already_present,
false);
2985 EXPECT_EQ(predecessor.index, 4);
2999 EXPECT_EQ(predecessor.is_already_present,
false);
3000 EXPECT_EQ(predecessor.index, 2);
3031 EXPECT_EQ(predecessor.is_already_present,
false);
3032 EXPECT_EQ(predecessor.index, 4);
3059 EXPECT_EQ(predecessor.is_already_present,
false);
3060 EXPECT_EQ(predecessor.index, 4);
3089 EXPECT_EQ(predecessor.is_already_present,
false);
3090 EXPECT_EQ(predecessor.index, 4);
3096 EXPECT_EQ(predecessor.is_already_present,
false);
3097 EXPECT_EQ(predecessor.index, 5);
3115 EXPECT_EQ(predecessor.is_already_present,
false);
3116 EXPECT_EQ(predecessor.index, 4);
3122 EXPECT_EQ(predecessor.is_already_present,
false);
3123 EXPECT_EQ(predecessor.index, 5);
3151 EXPECT_EQ(predecessor.is_already_present,
false);
3152 EXPECT_EQ(predecessor.index, 4);
3158 EXPECT_EQ(predecessor.is_already_present,
false);
3159 EXPECT_EQ(predecessor.index, 2);
3177 constexpr size_t depth = 10;
3178 std::string name =
"Nullifier Tree";
3189 uint32_t size_to_insert = 8;
3190 uint32_t num_insertions = 5;
3192 for (uint32_t i = 0; i < num_insertions - 1; i++) {
3194 current_size += size_to_insert;
3200 current_size += size_to_insert;
3204 current_size -= size_to_insert;
3213 current_size += size_to_insert;
void check_sibling_path(TypeOfTree &tree, index_t index, const fr_sibling_path &expected_sibling_path, bool includeUncommitted=true, bool expected_success=true)
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)
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)
IndexedLeaf< LeafValueType > get_leaf(TypeOfTree &tree, index_t index, bool includeUncommitted=true, bool expected_success=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 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)