653void test_batch_insert(uint32_t batchSize, std::string directory, uint64_t mapSize, uint64_t maxReaders)
656 const uint32_t batch_size = batchSize;
657 const uint32_t num_batches = 16;
663 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
664 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
665 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
667 for (uint32_t i = 0; i < num_batches; i++) {
682 for (uint32_t j = 0; j < batch_size; j++) {
685 memory_tree_sibling_paths.push_back(path);
693 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
696 tree1->add_or_update_values(batch, completion);
704 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
707 tree2->add_or_update_values(batch, completion);
714 tree3->add_or_update_values(batch, completion);
729 for (uint32_t j = 0; j < batch_size; j++) {
730 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
731 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
732 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
738 std::string directory,
743 const uint32_t batch_size = batchSize;
744 const uint32_t num_batches = 16;
750 for (uint32_t i = 0; i < num_batches; i++) {
752 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
753 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
754 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
769 for (uint32_t j = 0; j < batch_size; j++) {
772 memory_tree_sibling_paths.push_back(path);
780 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
783 tree1->add_or_update_values(batch, completion);
791 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
794 tree2->add_or_update_values(batch, completion);
801 tree3->add_or_update_values(batch, completion);
816 for (uint32_t j = 0; j < batch_size; j++) {
817 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
818 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
819 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
848 const uint32_t batch_size = 128;
853 auto tree1 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
854 auto tree2 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
857 for (uint32_t i = 1; i <= 12; i++) {
859 auto tree =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, multiWorkers);
863 std::vector<fr> tree1Roots;
864 std::vector<fr> tree2Roots;
866 for (uint32_t round = 0; round < 10; round++) {
867 std::vector<fr> frValues1 = create_values(3);
868 std::vector<fr> frValues2 = create_values(3);
870 for (uint32_t i = 0; i < 3; i++) {
871 leaves[i] = frValues1[i];
872 leaves[i + 64] = frValues2[i];
883 tree1Roots.push_back(
get_root(*tree1));
884 tree2Roots.push_back(
get_root(*tree2,
true));
885 EXPECT_EQ(tree1Roots[round], tree2Roots[round]);
887 for (
const auto& tree : trees) {
890 EXPECT_EQ(treeRoot, tree1Roots[round]);
928 const uint32_t batch_size = batchSize;
929 const uint32_t num_batches = 16;
935 auto sequential_tree_1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
936 auto sequential_tree_2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
937 auto sequential_tree_3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
938 auto batch_tree =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
940 for (uint32_t i = 0; i < num_batches; i++) {
958 for (uint32_t j = 0; j < batch_size; j++) {
961 memory_tree_sibling_paths.push_back(path);
965 sequential_tree_1_insertion_witness_data;
968 sequential_tree_2_insertion_witness_data;
974 sequential_tree_1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
975 sequential_tree_1_insertion_witness_data = response.inner.insertion_witness_data;
978 sequential_tree_1->add_or_update_values_sequentially(batch, completion);
986 sequential_tree_2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
987 sequential_tree_2_insertion_witness_data = response.inner.insertion_witness_data;
990 sequential_tree_2->add_or_update_values_sequentially(batch, completion);
997 sequential_tree_3->add_or_update_values_sequentially(batch, completion);
1004 batch_tree->add_or_update_values(batch, completion);
1022 for (uint32_t j = 0; j < batch_size; j++) {
1023 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).leaf,
1024 sequential_tree_2_low_leaf_witness_data->at(j).leaf);
1025 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).index,
1026 sequential_tree_2_low_leaf_witness_data->at(j).index);
1027 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).path,
1028 sequential_tree_2_low_leaf_witness_data->at(j).path);
1030 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).leaf,
1031 sequential_tree_2_insertion_witness_data->at(j).leaf);
1032 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).index,
1033 sequential_tree_2_insertion_witness_data->at(j).index);
1034 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).path,
1035 sequential_tree_2_insertion_witness_data->at(j).path);
1095 constexpr size_t depth = 3;
1113 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 0), zero_leaf);
1114 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 1), one_leaf);
1191 auto e000 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 0));
1192 auto e001 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 1));
1193 auto e010 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 2));
1194 auto e011 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 3));
1195 auto e100 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 4));
1196 auto e101 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 5));
1346 constexpr size_t depth = 3;
1352 std::move(store), workers, current_size);
1367 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1368 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1443 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1444 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1445 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1446 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1448 auto e101 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 5));
1507 constexpr size_t depth = 3;
1513 std::move(store), workers, current_size);
1528 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1529 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1602 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1603 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1604 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1605 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1606 auto e100 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 4));
1773 constexpr size_t depth = 3;
1778 using LocalTreeType =
1780 auto tree = LocalTreeType(
std::move(store), workers, current_size);
1795 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1796 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1890 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
1896 EXPECT_EQ(lowLeaf.
index, 1);
1899 EXPECT_EQ(lowLeaf.
index, 3);
1902 EXPECT_EQ(lowLeaf.
index, 2);
1969 const uint32_t batch_size = 16;
1970 uint32_t depth = 10;
1985 for (uint32_t j = 0; j < batch_size; j++) {
1996 for (uint32_t j = 0; j < batch_size; j++) {
2004 fr block2Root = memdb.
root();
2010 for (uint32_t j = 0; j < batch_size; j++) {
2023 auto treeAtBlock2 =
TreeType(
std::move(storeAtBlock2), multi_workers, batch_size);
2026 check_sibling_path(treeAtBlock2, 3 + batch_size, block2SiblingPathIndex3,
false,
true);
2027 auto block2TreeLeaf10 = get_leaf<NullifierLeafValue>(treeAtBlock2, 7 + batch_size);
2028 EXPECT_EQ(block2TreeLeaf10.leaf.nullifier, batch1[7].nullifier);
2034 get_leaf<NullifierLeafValue>(treeAtBlock2, 35 + batch_size,
false,
false);
2035 check_find_leaf_index<NullifierLeafValue, TreeType>(treeAtBlock2, { batch3[4] }, {
std::nullopt },
true);
2046 check_sibling_path(treeAtBlock2, 3 + batch_size, block3SiblingPathIndex3,
true,
true);
2047 check_sibling_path(treeAtBlock2, 19 + batch_size, block3SiblingPathIndex19,
true,
true);
2048 check_sibling_path(treeAtBlock2, 35 + batch_size, block3SiblingPathIndex35,
true,
true);
2052 EXPECT_EQ(historicSiblingPath, block1SiblingPathIndex3);
2055 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2056 treeAtBlock2, { batch3[3] }, 2, {
std::nullopt },
true,
false);
2059 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2060 treeAtBlock2, { batch3[3] }, 2, 20 + batch_size, {
std::nullopt },
true,
false);
2074 constexpr size_t depth = 3;
2079 using LocalTreeType =
2081 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2096 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2097 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2197 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2203 EXPECT_EQ(lowLeaf.
index, 1);
2206 EXPECT_EQ(lowLeaf.
index, 3);
2209 EXPECT_EQ(lowLeaf.
index, 2);
2218 check_historic_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2238 constexpr size_t depth = 3;
2243 using LocalTreeType =
2245 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2260 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2261 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2263 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2264 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2290 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2291 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2318 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2319 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2354 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2355 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2395 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2396 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2409 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2415 EXPECT_EQ(lowLeaf.
index, 1);
2418 EXPECT_EQ(lowLeaf.
index, 3);
2421 EXPECT_EQ(lowLeaf.
index, 2);
2428 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2429 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2449 check_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2451 check_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2463 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2464 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2483 constexpr size_t depth = 3;
2489 std::move(store), workers, current_size);
2504 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2505 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2529 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2530 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2556 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2557 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2582 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2583 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2601 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2602 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2620 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2621 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2643 uint64_t maxReaders,
2647 uint32_t numBlocksToUnwind,
2648 std::vector<fr> values)
2656 auto it =
std::find_if(values.begin(), values.end(), [&](
const fr& v) { return v != fr::zero(); });
2657 bool emptyBlocks = it == values.end();
2659 uint32_t batchSize = blockSize;
2663 std::vector<fr> roots;
2665 fr initialRoot = memdb.
root();
2669 leafValues.reserve(values.size());
2670 for (
const fr& v : values) {
2671 leafValues.emplace_back(v);
2674 for (uint32_t i = 0; i < numBlocks; i++) {
2677 for (
size_t j = 0; j < batchSize; ++j) {
2678 size_t ind = i * batchSize + j;
2680 to_add.push_back(leafValues[ind]);
2683 index_t expected_size = (i + 2) * batchSize;
2688 historicPathsMaxIndex.push_back(memdb.
get_sibling_path(expected_size - 1));
2689 roots.push_back(memdb.
root());
2698 const uint32_t blocksToRemove = numBlocksToUnwind;
2699 for (uint32_t i = 0; i < blocksToRemove; i++) {
2712 const index_t previousValidBlock = blockNumber - 1;
2714 index_t deletedBlockStartIndex = (1 + previousValidBlock) * batchSize;
2715 index_t deletedBlockStartIndexIntoLocalValues = previousValidBlock * batchSize;
2719 check_root(tree, previousValidBlock == 0 ? initialRoot : roots[previousValidBlock - 1]);
2724 previousValidBlock == 0 ? initialPath : historicPathsZeroIndex[previousValidBlock - 1],
2730 get_leaf<NullifierLeafValue>(tree, 1 + deletedBlockStartIndex,
false,
false);
2732 check_find_leaf_index<NullifierLeafValue, TreeType>(
2733 tree, { leafValues[1 + deletedBlockStartIndexIntoLocalValues] }, {
std::nullopt },
true);
2736 for (
index_t j = 0; j < numBlocks; j++) {
2738 bool expectedSuccess = historicBlockNumber <= previousValidBlock;
2740 tree, 0, historicBlockNumber, historicPathsZeroIndex[j],
false, expectedSuccess);
2741 index_t maxSizeAtBlock = ((j + 2) * batchSize) - 1;
2743 tree, maxSizeAtBlock, historicBlockNumber, historicPathsMaxIndex[j],
false, expectedSuccess);
2749 const index_t expectedIndexInTree = leafIndex + batchSize;
2751 tree, leafValues[leafIndex], expectedIndexInTree, historicBlockNumber, expectedSuccess,
false);
2754 if (expectedSuccess) {
2757 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2758 tree, { leafValues[leafIndex] }, historicBlockNumber, expectedResults, expectedSuccess,
true);
2759 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2760 tree, { leafValues[leafIndex] }, historicBlockNumber, 0, expectedResults, expectedSuccess,
true);
2896 index_t current_size = initial_size;
2899 constexpr size_t depth = 3;
2905 std::move(store), workers, current_size);
2960 index_t fork_size = current_size;
2965 std::move(forkStore), workers, initial_size);
2971 EXPECT_EQ(predecessor.is_already_present,
false);
2972 EXPECT_EQ(predecessor.index, 2);
2999 EXPECT_EQ(predecessor.is_already_present,
false);
3000 EXPECT_EQ(predecessor.index, 4);
3014 EXPECT_EQ(predecessor.is_already_present,
false);
3015 EXPECT_EQ(predecessor.index, 2);
3046 EXPECT_EQ(predecessor.is_already_present,
false);
3047 EXPECT_EQ(predecessor.index, 4);
3074 EXPECT_EQ(predecessor.is_already_present,
false);
3075 EXPECT_EQ(predecessor.index, 4);
3104 EXPECT_EQ(predecessor.is_already_present,
false);
3105 EXPECT_EQ(predecessor.index, 4);
3111 EXPECT_EQ(predecessor.is_already_present,
false);
3112 EXPECT_EQ(predecessor.index, 5);
3130 EXPECT_EQ(predecessor.is_already_present,
false);
3131 EXPECT_EQ(predecessor.index, 4);
3137 EXPECT_EQ(predecessor.is_already_present,
false);
3138 EXPECT_EQ(predecessor.index, 5);
3166 EXPECT_EQ(predecessor.is_already_present,
false);
3167 EXPECT_EQ(predecessor.index, 4);
3173 EXPECT_EQ(predecessor.is_already_present,
false);
3174 EXPECT_EQ(predecessor.index, 2);
3192 constexpr size_t depth = 10;
3193 std::string name =
"Nullifier Tree";
3204 uint32_t size_to_insert = 8;
3205 uint32_t num_insertions = 5;
3207 for (uint32_t i = 0; i < num_insertions - 1; i++) {
3209 current_size += size_to_insert;
3215 current_size += size_to_insert;
3219 current_size -= size_to_insert;
3228 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)