@@ -786,6 +786,57 @@ TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_add_multiple_values_in_a
786
786
check_sibling_path (tree, 4 - 1 , memdb.get_sibling_path (4 - 1 ));
787
787
}
788
788
789
+ TEST_F (PersistedContentAddressedAppendOnlyTreeTest, can_pad_with_zero_leaves)
790
+ {
791
+ constexpr size_t depth = 10 ;
792
+ std::string name = random_string ();
793
+ LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(_directory, name, _mapSize, _maxReaders);
794
+ std::unique_ptr<Store> store = std::make_unique<Store>(name, depth, db);
795
+ ThreadPoolPtr pool = make_thread_pool (1 );
796
+ TreeType tree (std::move (store), pool);
797
+ MemoryTree<Poseidon2HashPolicy> memdb (depth);
798
+
799
+ std::vector<fr> to_add (32 , fr::zero ());
800
+ to_add[0 ] = VALUES[0 ];
801
+
802
+ for (size_t i = 0 ; i < 32 ; ++i) {
803
+ memdb.update_element (i, to_add[i]);
804
+ }
805
+ add_values (tree, to_add);
806
+ check_size (tree, 32 );
807
+ check_root (tree, memdb.root ());
808
+
809
+ commit_tree (tree, true );
810
+
811
+ check_size (tree, 32 );
812
+ check_root (tree, memdb.root ());
813
+ }
814
+
815
+ TEST_F (PersistedContentAddressedAppendOnlyTreeTest, can_not_retrieve_zero_leaf_indices)
816
+ {
817
+ constexpr size_t depth = 8 ;
818
+ std::string name = random_string ();
819
+ LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(_directory, name, _mapSize, _maxReaders);
820
+ std::unique_ptr<Store> store = std::make_unique<Store>(name, depth, db);
821
+ ThreadPoolPtr pool = make_thread_pool (1 );
822
+ TreeType tree (std::move (store), pool);
823
+ MemoryTree<Poseidon2HashPolicy> memdb (depth);
824
+
825
+ std::vector<fr> to_add (32 , fr::zero ());
826
+ to_add[0 ] = VALUES[0 ];
827
+
828
+ for (size_t i = 0 ; i < 32 ; ++i) {
829
+ memdb.update_element (i, VALUES[i]);
830
+ }
831
+ add_values (tree, to_add);
832
+ commit_tree (tree);
833
+ fr leaf = fr::zero ();
834
+ check_find_leaf_index (tree, leaf, 0 , false );
835
+ check_find_historic_leaf_index (tree, 1 , leaf, 0 , false );
836
+ check_find_leaf_index_from (tree, leaf, 0 , 0 , false );
837
+ check_find_historic_leaf_index_from (tree, 1 , leaf, 0 , 0 , false );
838
+ }
839
+
789
840
TEST_F (PersistedContentAddressedAppendOnlyTreeTest, can_commit_multiple_blocks)
790
841
{
791
842
constexpr size_t depth = 10 ;
@@ -1354,7 +1405,12 @@ void test_unwind(std::string directory,
1354
1405
// attempting to unwind a block that is not the tip should fail
1355
1406
unwind_block (tree, blockNumber + 1 , false );
1356
1407
unwind_block (tree, blockNumber);
1357
- check_block_and_root_data (db, blockNumber, roots[blockNumber - 1 ], false );
1408
+
1409
+ // the root should now only exist if there are other blocks with same root
1410
+ const auto last = roots.begin () + long (blockNumber - 1 );
1411
+ const auto it =
1412
+ std::find_if (roots.begin (), last, [=](const fr& r) -> bool { return r == roots[blockNumber - 1 ]; });
1413
+ check_block_and_root_data (db, blockNumber, roots[blockNumber - 1 ], false , it != last);
1358
1414
1359
1415
const index_t previousValidBlock = blockNumber - 1 ;
1360
1416
index_t deletedBlockStartIndex = previousValidBlock * batchSize;
@@ -1384,9 +1440,19 @@ void test_unwind(std::string directory,
1384
1440
1385
1441
const index_t leafIndex = 1 ;
1386
1442
check_historic_leaf (tree, historicBlockNumber, values[leafIndex], leafIndex, expectedSuccess);
1387
- check_find_historic_leaf_index (tree, historicBlockNumber, values[leafIndex], leafIndex, expectedSuccess);
1388
- check_find_historic_leaf_index_from (
1389
- tree, historicBlockNumber, values[leafIndex], 0 , leafIndex, expectedSuccess);
1443
+
1444
+ // find historic leaves, provided they are not zero leaves
1445
+ check_find_historic_leaf_index (tree,
1446
+ historicBlockNumber,
1447
+ values[leafIndex],
1448
+ leafIndex,
1449
+ expectedSuccess && values[leafIndex] != fr::zero ());
1450
+ check_find_historic_leaf_index_from (tree,
1451
+ historicBlockNumber,
1452
+ values[leafIndex],
1453
+ 0 ,
1454
+ leafIndex,
1455
+ expectedSuccess && values[leafIndex] != fr::zero ());
1390
1456
}
1391
1457
}
1392
1458
}
@@ -1405,6 +1471,33 @@ TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_unwind_all_blocks)
1405
1471
test_unwind (_directory, " DB" , _mapSize, _maxReaders, 10 , 16 , 16 , 16 , second);
1406
1472
}
1407
1473
1474
+ TEST_F (PersistedContentAddressedAppendOnlyTreeTest, can_unwind_initial_blocks_that_are_empty)
1475
+ {
1476
+ const size_t block_size = 16 ;
1477
+ // First we add 16 blocks worth pf zero leaves and unwind them all
1478
+ std::vector<fr> first (1024 , fr::zero ());
1479
+ test_unwind (_directory, " DB" , _mapSize, _maxReaders, 10 , block_size, 16 , 16 , first);
1480
+ // now we add 1 block of zero leaves and the other blocks non-zero leaves and unwind them all
1481
+ std::vector<fr> second = create_values (1024 );
1482
+ // set the first 16 values to be zeros
1483
+ for (size_t i = 0 ; i < block_size; i++) {
1484
+ second[i] = fr::zero ();
1485
+ }
1486
+ test_unwind (_directory, " DB" , _mapSize, _maxReaders, 10 , block_size, 16 , 16 , second);
1487
+
1488
+ // now we add 2 block of zero leaves in the middle and the other blocks non-zero leaves and unwind them all
1489
+ std::vector<fr> third = create_values (1024 );
1490
+ size_t offset = block_size * 2 ;
1491
+ for (size_t i = 0 ; i < block_size * 2 ; i++) {
1492
+ third[i + offset] = fr::zero ();
1493
+ }
1494
+ test_unwind (_directory, " DB" , _mapSize, _maxReaders, 10 , block_size, 16 , 16 , third);
1495
+
1496
+ // Now we add a number of regular blocks and unwind
1497
+ std::vector<fr> fourth = create_values (1024 );
1498
+ test_unwind (_directory, " DB" , _mapSize, _maxReaders, 10 , block_size, 16 , 16 , fourth);
1499
+ }
1500
+
1408
1501
TEST_F (PersistedContentAddressedAppendOnlyTreeTest, can_sync_and_unwind_large_blocks)
1409
1502
{
1410
1503
0 commit comments