Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,9 @@ void ContentAddressedAppendOnlyTree<Store, HashingPolicy>::find_leaf_index_from(
auto job = [=, this]() -> void {
execute_and_report<FindLeafIndexResponse>(
[=, this](TypedResponse<FindLeafIndexResponse>& response) {
if (leaf == fr::zero()) {
throw std::runtime_error("Requesting indices for zero leaves is prohibited");
}
ReadTransactionPtr tx = store_->create_read_transaction();
RequestContext requestContext;
requestContext.includeUncommitted = includeUncommitted;
Expand Down Expand Up @@ -693,6 +696,9 @@ void ContentAddressedAppendOnlyTree<Store, HashingPolicy>::find_leaf_index_from(
if (blockNumber == 0) {
throw std::runtime_error("Unable to find leaf index for block number 0");
}
if (leaf == fr::zero()) {
throw std::runtime_error("Requesting indices for zero leaves is prohibited");
}
ReadTransactionPtr tx = store_->create_read_transaction();
BlockPayload blockData;
if (!store_->get_block_data(blockNumber, blockData, *tx)) {
Expand Down Expand Up @@ -899,6 +905,10 @@ void ContentAddressedAppendOnlyTree<Store, HashingPolicy>::add_batch_internal(
// If we have been told to add these leaves to the index then do so now
if (update_index) {
for (uint32_t i = 0; i < number_to_insert; ++i) {
// We don't store indices of zero leaves
if (hashes_local[i] == fr::zero()) {
continue;
}
// std::cout << "Updating index " << index + i << " : " << hashes_local[i] << std::endl;
store_->update_index(index + i, hashes_local[i]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,57 @@ TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_add_multiple_values_in_a
check_sibling_path(tree, 4 - 1, memdb.get_sibling_path(4 - 1));
}

TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_pad_with_zero_leaves)
{
constexpr size_t depth = 10;
std::string name = random_string();
LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(_directory, name, _mapSize, _maxReaders);
std::unique_ptr<Store> store = std::make_unique<Store>(name, depth, db);
ThreadPoolPtr pool = make_thread_pool(1);
TreeType tree(std::move(store), pool);
MemoryTree<Poseidon2HashPolicy> memdb(depth);

std::vector<fr> to_add(32, fr::zero());
to_add[0] = VALUES[0];

for (size_t i = 0; i < 32; ++i) {
memdb.update_element(i, to_add[i]);
}
add_values(tree, to_add);
check_size(tree, 32);
check_root(tree, memdb.root());

commit_tree(tree, true);

check_size(tree, 32);
check_root(tree, memdb.root());
}

TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_not_retrieve_zero_leaf_indices)
{
constexpr size_t depth = 8;
std::string name = random_string();
LMDBTreeStore::SharedPtr db = std::make_shared<LMDBTreeStore>(_directory, name, _mapSize, _maxReaders);
std::unique_ptr<Store> store = std::make_unique<Store>(name, depth, db);
ThreadPoolPtr pool = make_thread_pool(1);
TreeType tree(std::move(store), pool);
MemoryTree<Poseidon2HashPolicy> memdb(depth);

std::vector<fr> to_add(32, fr::zero());
to_add[0] = VALUES[0];

for (size_t i = 0; i < 32; ++i) {
memdb.update_element(i, VALUES[i]);
}
add_values(tree, to_add);
commit_tree(tree);
fr leaf = fr::zero();
check_find_leaf_index(tree, leaf, 0, false);
check_find_historic_leaf_index(tree, 1, leaf, 0, false);
check_find_leaf_index_from(tree, leaf, 0, 0, false);
check_find_historic_leaf_index_from(tree, 1, leaf, 0, 0, false);
}

TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_commit_multiple_blocks)
{
constexpr size_t depth = 10;
Expand Down Expand Up @@ -1354,7 +1405,12 @@ void test_unwind(std::string directory,
// attempting to unwind a block that is not the tip should fail
unwind_block(tree, blockNumber + 1, false);
unwind_block(tree, blockNumber);
check_block_and_root_data(db, blockNumber, roots[blockNumber - 1], false);

// the root should now only exist if there are other blocks with same root
const auto last = roots.begin() + long(blockNumber - 1);
const auto it =
std::find_if(roots.begin(), last, [=](const fr& r) -> bool { return r == roots[blockNumber - 1]; });
check_block_and_root_data(db, blockNumber, roots[blockNumber - 1], false, it != last);

const index_t previousValidBlock = blockNumber - 1;
index_t deletedBlockStartIndex = previousValidBlock * batchSize;
Expand Down Expand Up @@ -1384,9 +1440,19 @@ void test_unwind(std::string directory,

const index_t leafIndex = 1;
check_historic_leaf(tree, historicBlockNumber, values[leafIndex], leafIndex, expectedSuccess);
check_find_historic_leaf_index(tree, historicBlockNumber, values[leafIndex], leafIndex, expectedSuccess);
check_find_historic_leaf_index_from(
tree, historicBlockNumber, values[leafIndex], 0, leafIndex, expectedSuccess);

// find historic leaves, provided they are not zero leaves
check_find_historic_leaf_index(tree,
historicBlockNumber,
values[leafIndex],
leafIndex,
expectedSuccess && values[leafIndex] != fr::zero());
check_find_historic_leaf_index_from(tree,
historicBlockNumber,
values[leafIndex],
0,
leafIndex,
expectedSuccess && values[leafIndex] != fr::zero());
}
}
}
Expand All @@ -1405,6 +1471,33 @@ TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_unwind_all_blocks)
test_unwind(_directory, "DB", _mapSize, _maxReaders, 10, 16, 16, 16, second);
}

TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_unwind_initial_blocks_that_are_empty)
{
const size_t block_size = 16;
// First we add 16 blocks worth pf zero leaves and unwind them all
std::vector<fr> first(1024, fr::zero());
test_unwind(_directory, "DB", _mapSize, _maxReaders, 10, block_size, 16, 16, first);
// now we add 1 block of zero leaves and the other blocks non-zero leaves and unwind them all
std::vector<fr> second = create_values(1024);
// set the first 16 values to be zeros
for (size_t i = 0; i < block_size; i++) {
second[i] = fr::zero();
}
test_unwind(_directory, "DB", _mapSize, _maxReaders, 10, block_size, 16, 16, second);

// now we add 2 block of zero leaves in the middle and the other blocks non-zero leaves and unwind them all
std::vector<fr> third = create_values(1024);
size_t offset = block_size * 2;
for (size_t i = 0; i < block_size * 2; i++) {
third[i + offset] = fr::zero();
}
test_unwind(_directory, "DB", _mapSize, _maxReaders, 10, block_size, 16, 16, third);

// Now we add a number of regular blocks and unwind
std::vector<fr> fourth = create_values(1024);
test_unwind(_directory, "DB", _mapSize, _maxReaders, 10, block_size, 16, 16, fourth);
}

TEST_F(PersistedContentAddressedAppendOnlyTreeTest, can_sync_and_unwind_large_blocks)
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,6 @@ void ContentAddressedCachedTreeStore<LeafValueType>::put_cached_node_by_index(ui
return;
}
}

nodes_by_index_[level][index] = data;
}

Expand Down Expand Up @@ -695,7 +694,6 @@ void ContentAddressedCachedTreeStore<LeafValueType>::persist_leaf_pre_image(cons
if (leafPreImageIter == leaves_.end()) {
return;
}
// std::cout << "Persisting leaf preimage " << leafPreImageIter->second << std::endl;
dataStore_->write_leaf_by_hash(hash, leafPreImageIter->second, tx);
}

Expand Down
10 changes: 9 additions & 1 deletion barretenberg/cpp/src/barretenberg/world_state/world_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,15 @@ WorldStateStatusFull WorldState::sync_block(

{
auto& wrapper = std::get<TreeWithStore<NullifierTree>>(fork->_trees.at(MerkleTreeId::NULLIFIER_TREE));
NullifierTree::AddCompletionCallback completion = [&](const auto&) -> void { signal.signal_decrement(); };
NullifierTree::AddCompletionCallback completion = [&](const auto& resp) -> void {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is unrelated, but I noticed this was incorrect.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that's me, thanks for fixing!

// take the first error
bool expected = true;
if (!resp.success && success.compare_exchange_strong(expected, false)) {
err_message = resp.message;
}

signal.signal_decrement();
};
wrapper.tree->add_or_update_values(nullifiers, 0, completion);
}

Expand Down