637void test_batch_insert(uint32_t batchSize, std::string directory, uint64_t mapSize, uint64_t maxReaders)
640 const uint32_t batch_size = batchSize;
641 const uint32_t num_batches = 16;
647 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
648 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
649 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
651 for (uint32_t i = 0; i < num_batches; i++) {
666 for (uint32_t j = 0; j < batch_size; j++) {
669 memory_tree_sibling_paths.push_back(path);
677 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
680 tree1->add_or_update_values(batch, completion);
688 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
691 tree2->add_or_update_values(batch, completion);
698 tree3->add_or_update_values(batch, completion);
713 for (uint32_t j = 0; j < batch_size; j++) {
714 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
715 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
716 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
722 std::string directory,
727 const uint32_t batch_size = batchSize;
728 const uint32_t num_batches = 16;
734 for (uint32_t i = 0; i < num_batches; i++) {
736 auto tree1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
737 auto tree2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
738 auto tree3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
753 for (uint32_t j = 0; j < batch_size; j++) {
756 memory_tree_sibling_paths.push_back(path);
764 tree1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
767 tree1->add_or_update_values(batch, completion);
775 tree2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
778 tree2->add_or_update_values(batch, completion);
785 tree3->add_or_update_values(batch, completion);
800 for (uint32_t j = 0; j < batch_size; j++) {
801 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).leaf, tree2_low_leaf_witness_data->at(j).leaf);
802 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).index, tree2_low_leaf_witness_data->at(j).index);
803 EXPECT_EQ(tree1_low_leaf_witness_data->at(j).path, tree2_low_leaf_witness_data->at(j).path);
832 const uint32_t batch_size = 128;
837 auto tree1 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
838 auto tree2 =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, workers);
841 for (uint32_t i = 1; i <= 12; i++) {
843 auto tree =
create_tree(_directory, _mapSize, _maxReaders, depth, batch_size, multiWorkers);
847 std::vector<fr> tree1Roots;
848 std::vector<fr> tree2Roots;
850 for (uint32_t round = 0; round < 10; round++) {
851 std::vector<fr> frValues1 = create_values(3);
852 std::vector<fr> frValues2 = create_values(3);
854 for (uint32_t i = 0; i < 3; i++) {
855 leaves[i] = frValues1[i];
856 leaves[i + 64] = frValues2[i];
867 tree1Roots.push_back(
get_root(*tree1));
868 tree2Roots.push_back(
get_root(*tree2,
true));
869 EXPECT_EQ(tree1Roots[round], tree2Roots[round]);
871 for (
const auto& tree : trees) {
874 EXPECT_EQ(treeRoot, tree1Roots[round]);
912 const uint32_t batch_size = batchSize;
913 const uint32_t num_batches = 16;
919 auto sequential_tree_1 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, workers);
920 auto sequential_tree_2 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
921 auto sequential_tree_3 =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
922 auto batch_tree =
create_tree(directory, mapSize, maxReaders, depth, batch_size, multi_workers);
924 for (uint32_t i = 0; i < num_batches; i++) {
942 for (uint32_t j = 0; j < batch_size; j++) {
945 memory_tree_sibling_paths.push_back(path);
949 sequential_tree_1_insertion_witness_data;
952 sequential_tree_2_insertion_witness_data;
958 sequential_tree_1_low_leaf_witness_data = response.inner.low_leaf_witness_data;
959 sequential_tree_1_insertion_witness_data = response.inner.insertion_witness_data;
962 sequential_tree_1->add_or_update_values_sequentially(batch, completion);
970 sequential_tree_2_low_leaf_witness_data = response.inner.low_leaf_witness_data;
971 sequential_tree_2_insertion_witness_data = response.inner.insertion_witness_data;
974 sequential_tree_2->add_or_update_values_sequentially(batch, completion);
981 sequential_tree_3->add_or_update_values_sequentially(batch, completion);
988 batch_tree->add_or_update_values(batch, completion);
1006 for (uint32_t j = 0; j < batch_size; j++) {
1007 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).leaf,
1008 sequential_tree_2_low_leaf_witness_data->at(j).leaf);
1009 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).index,
1010 sequential_tree_2_low_leaf_witness_data->at(j).index);
1011 EXPECT_EQ(sequential_tree_1_low_leaf_witness_data->at(j).path,
1012 sequential_tree_2_low_leaf_witness_data->at(j).path);
1014 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).leaf,
1015 sequential_tree_2_insertion_witness_data->at(j).leaf);
1016 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).index,
1017 sequential_tree_2_insertion_witness_data->at(j).index);
1018 EXPECT_EQ(sequential_tree_1_insertion_witness_data->at(j).path,
1019 sequential_tree_2_insertion_witness_data->at(j).path);
1079 constexpr size_t depth = 3;
1097 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 0), zero_leaf);
1098 EXPECT_EQ(get_leaf<NullifierLeafValue>(tree, 1), one_leaf);
1175 auto e000 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 0));
1176 auto e001 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 1));
1177 auto e010 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 2));
1178 auto e011 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 3));
1179 auto e100 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 4));
1180 auto e101 =
hash_leaf(get_leaf<NullifierLeafValue>(tree, 5));
1330 constexpr size_t depth = 3;
1336 std::move(store), workers, current_size);
1351 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1352 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1427 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1428 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1429 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1430 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1432 auto e101 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 5));
1491 constexpr size_t depth = 3;
1497 std::move(store), workers, current_size);
1512 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1513 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1586 auto e000 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 0));
1587 auto e001 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 1));
1588 auto e010 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 2));
1589 auto e011 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 3));
1590 auto e100 =
hash_leaf(get_leaf<PublicDataLeafValue>(tree, 4));
1757 constexpr size_t depth = 3;
1762 using LocalTreeType =
1764 auto tree = LocalTreeType(
std::move(store), workers, current_size);
1779 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
1780 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
1874 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
1880 EXPECT_EQ(lowLeaf.
index, 1);
1883 EXPECT_EQ(lowLeaf.
index, 3);
1886 EXPECT_EQ(lowLeaf.
index, 2);
1953 const uint32_t batch_size = 16;
1954 uint32_t depth = 10;
1969 for (uint32_t j = 0; j < batch_size; j++) {
1980 for (uint32_t j = 0; j < batch_size; j++) {
1988 fr block2Root = memdb.
root();
1994 for (uint32_t j = 0; j < batch_size; j++) {
2007 auto treeAtBlock2 =
TreeType(
std::move(storeAtBlock2), multi_workers, batch_size);
2010 check_sibling_path(treeAtBlock2, 3 + batch_size, block2SiblingPathIndex3,
false,
true);
2011 auto block2TreeLeaf10 = get_leaf<NullifierLeafValue>(treeAtBlock2, 7 + batch_size);
2012 EXPECT_EQ(block2TreeLeaf10.leaf.nullifier, batch1[7].nullifier);
2018 get_leaf<NullifierLeafValue>(treeAtBlock2, 35 + batch_size,
false,
false);
2019 check_find_leaf_index<NullifierLeafValue, TreeType>(treeAtBlock2, { batch3[4] }, {
std::nullopt },
true);
2030 check_sibling_path(treeAtBlock2, 3 + batch_size, block3SiblingPathIndex3,
true,
true);
2031 check_sibling_path(treeAtBlock2, 19 + batch_size, block3SiblingPathIndex19,
true,
true);
2032 check_sibling_path(treeAtBlock2, 35 + batch_size, block3SiblingPathIndex35,
true,
true);
2036 EXPECT_EQ(historicSiblingPath, block1SiblingPathIndex3);
2039 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2040 treeAtBlock2, { batch3[3] }, 2, {
std::nullopt },
true,
false);
2043 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2044 treeAtBlock2, { batch3[3] }, 2, 20 + batch_size, {
std::nullopt },
true,
false);
2058 constexpr size_t depth = 3;
2063 using LocalTreeType =
2065 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2080 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2081 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2181 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2187 EXPECT_EQ(lowLeaf.
index, 1);
2190 EXPECT_EQ(lowLeaf.
index, 3);
2193 EXPECT_EQ(lowLeaf.
index, 2);
2202 check_historic_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2222 constexpr size_t depth = 3;
2227 using LocalTreeType =
2229 auto tree = LocalTreeType(
std::move(store), workers, current_size);
2244 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2245 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2247 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2248 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2274 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2275 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2302 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2303 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2338 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2339 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2379 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2380 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2393 check_historic_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2399 EXPECT_EQ(lowLeaf.
index, 1);
2402 EXPECT_EQ(lowLeaf.
index, 3);
2405 EXPECT_EQ(lowLeaf.
index, 2);
2412 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2413 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2433 check_find_leaf_index<PublicDataLeafValue, LocalTreeType>(
2435 check_find_leaf_index_from<PublicDataLeafValue, LocalTreeType>(
2447 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2448 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2467 constexpr size_t depth = 3;
2473 std::move(store), workers, current_size);
2488 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 0), zero_leaf);
2489 EXPECT_EQ(get_leaf<PublicDataLeafValue>(tree, 1), one_leaf);
2513 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2514 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2540 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2541 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2566 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2567 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2585 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2586 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2604 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, zero_leaf,
true);
2605 check_leaf_by_hash<PublicDataLeafValue, HashPolicy>(db, one_leaf,
true);
2627 uint64_t maxReaders,
2631 uint32_t numBlocksToUnwind,
2632 std::vector<fr> values)
2640 auto it =
std::find_if(values.begin(), values.end(), [&](
const fr& v) { return v != fr::zero(); });
2641 bool emptyBlocks = it == values.end();
2643 uint32_t batchSize = blockSize;
2647 std::vector<fr> roots;
2649 fr initialRoot = memdb.
root();
2653 leafValues.reserve(values.size());
2654 for (
const fr& v : values) {
2655 leafValues.emplace_back(v);
2658 for (uint32_t i = 0; i < numBlocks; i++) {
2661 for (
size_t j = 0; j < batchSize; ++j) {
2662 size_t ind = i * batchSize + j;
2664 to_add.push_back(leafValues[ind]);
2667 index_t expected_size = (i + 2) * batchSize;
2672 historicPathsMaxIndex.push_back(memdb.
get_sibling_path(expected_size - 1));
2673 roots.push_back(memdb.
root());
2682 const uint32_t blocksToRemove = numBlocksToUnwind;
2683 for (uint32_t i = 0; i < blocksToRemove; i++) {
2696 const index_t previousValidBlock = blockNumber - 1;
2698 index_t deletedBlockStartIndex = (1 + previousValidBlock) * batchSize;
2699 index_t deletedBlockStartIndexIntoLocalValues = previousValidBlock * batchSize;
2703 check_root(tree, previousValidBlock == 0 ? initialRoot : roots[previousValidBlock - 1]);
2708 previousValidBlock == 0 ? initialPath : historicPathsZeroIndex[previousValidBlock - 1],
2714 get_leaf<NullifierLeafValue>(tree, 1 + deletedBlockStartIndex,
false,
false);
2716 check_find_leaf_index<NullifierLeafValue, TreeType>(
2717 tree, { leafValues[1 + deletedBlockStartIndexIntoLocalValues] }, {
std::nullopt },
true);
2720 for (
index_t j = 0; j < numBlocks; j++) {
2722 bool expectedSuccess = historicBlockNumber <= previousValidBlock;
2724 tree, 0, historicBlockNumber, historicPathsZeroIndex[j],
false, expectedSuccess);
2725 index_t maxSizeAtBlock = ((j + 2) * batchSize) - 1;
2727 tree, maxSizeAtBlock, historicBlockNumber, historicPathsMaxIndex[j],
false, expectedSuccess);
2733 const index_t expectedIndexInTree = leafIndex + batchSize;
2735 tree, leafValues[leafIndex], expectedIndexInTree, historicBlockNumber, expectedSuccess,
false);
2738 if (expectedSuccess) {
2741 check_historic_find_leaf_index<NullifierLeafValue, TreeType>(
2742 tree, { leafValues[leafIndex] }, historicBlockNumber, expectedResults, expectedSuccess,
true);
2743 check_historic_find_leaf_index_from<NullifierLeafValue, TreeType>(
2744 tree, { leafValues[leafIndex] }, historicBlockNumber, 0, expectedResults, expectedSuccess,
true);
2880 index_t current_size = initial_size;
2883 constexpr size_t depth = 3;
2889 std::move(store), workers, current_size);
2944 index_t fork_size = current_size;
2949 std::move(forkStore), workers, initial_size);
2955 EXPECT_EQ(predecessor.is_already_present,
false);
2956 EXPECT_EQ(predecessor.index, 2);
2983 EXPECT_EQ(predecessor.is_already_present,
false);
2984 EXPECT_EQ(predecessor.index, 4);
2998 EXPECT_EQ(predecessor.is_already_present,
false);
2999 EXPECT_EQ(predecessor.index, 2);
3030 EXPECT_EQ(predecessor.is_already_present,
false);
3031 EXPECT_EQ(predecessor.index, 4);
3058 EXPECT_EQ(predecessor.is_already_present,
false);
3059 EXPECT_EQ(predecessor.index, 4);
3088 EXPECT_EQ(predecessor.is_already_present,
false);
3089 EXPECT_EQ(predecessor.index, 4);
3095 EXPECT_EQ(predecessor.is_already_present,
false);
3096 EXPECT_EQ(predecessor.index, 5);
3114 EXPECT_EQ(predecessor.is_already_present,
false);
3115 EXPECT_EQ(predecessor.index, 4);
3121 EXPECT_EQ(predecessor.is_already_present,
false);
3122 EXPECT_EQ(predecessor.index, 5);
3150 EXPECT_EQ(predecessor.is_already_present,
false);
3151 EXPECT_EQ(predecessor.index, 4);
3157 EXPECT_EQ(predecessor.is_already_present,
false);
3158 EXPECT_EQ(predecessor.index, 2);
3176 constexpr size_t depth = 10;
3177 std::string name =
"Nullifier Tree";
3188 uint32_t size_to_insert = 8;
3189 uint32_t num_insertions = 5;
3191 for (uint32_t i = 0; i < num_insertions - 1; i++) {
3193 current_size += size_to_insert;
3199 current_size += size_to_insert;
3203 current_size -= size_to_insert;
3212 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)