Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bound finalized header, execution header and sync committee by pruning older data beyond threshold #810

Closed
wants to merge 6 commits into from

Conversation

ParthDesai
Copy link
Contributor

@ParthDesai ParthDesai commented Apr 20, 2023

Description

This PR enables pruning older FinalizedHeader, ExecutionHeader and SyncCommittee. This is required to put bounds on the storage of the pallet. As left unchecked it could be huge amount of data.

First three PR adds support for pruning of FinalizedHeader, ExecutionHeader and SyncCommittee respectively. Fourth commit adds comprehensive tests for the same. Fifth commit is just cargo fmt changes. And last commit introduces relayer changes.

How it works?

ExecutionHeader

For ExecutionHeader there is a queue like simulated data maintained that allows pruning of older data as the new data gets added.

Since execution headers are not contiguous, to maintain the queue, we need to maintain a mapping of u64 -> ExecutionHeader and also keep track of front and back of the queue. While we push new data to back, we remove data from front this is supported by (oldest_bound, latest_bound) storage.

FinalizedHeader

For FinalizedHeader we are pruning it as per MaxFinalizedHeaderSlotArray. As, FinalizedHeader and its associated data with slot less than 0th element of the vector will not be used by relayer in anycase.

SyncCommittee

Since SyncCommittee is stored in an order, we can rely on it to prune oldest sync committee.

Configuration changes

Both ExecutionHeader and SyncCommittee's pruning threshold is defined in pallet configuration.

Relayer changes

Due to change in FinalizedSlotArray storage, there is a change in relayer to maintain compatibility.

Comment on lines +911 to +918
while number_of_sync_committees_to_remove > 0 {
<SyncCommittees<T>>::remove(current_sync_committee_to_remove);
number_of_sync_committees_to_remove =
number_of_sync_committees_to_remove.saturating_sub(1);
current_sync_committee_to_remove =
current_sync_committee_to_remove.saturating_sub(1);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The problem here is the performance overhead of the while loop which could use up all the block weight.

Copy link
Contributor Author

@ParthDesai ParthDesai Apr 21, 2023

Choose a reason for hiding this comment

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

while loop would run only 1 time. As it runs after every insert.

Comment on lines +1016 to +1022
for _i in 0..execution_headers_to_delete {
let execution_header_hash =
<ExecutionHeadersMapping<T>>::get(oldest_mapping_to_delete);
<ExecutionHeadersMapping<T>>::remove(oldest_mapping_to_delete);
<ExecutionHeaders<T>>::remove(execution_header_hash);
oldest_mapping_to_delete += 1;
}
Copy link
Contributor

@yrong yrong Apr 21, 2023

Choose a reason for hiding this comment

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

Copy link
Contributor Author

@ParthDesai ParthDesai Apr 21, 2023

Choose a reason for hiding this comment

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

while loop would run only 1 time. As it runs after every insert.

@yrong
Copy link
Contributor

yrong commented Apr 21, 2023

@ParthDesai Cool and thanks for the contribution! Though IMHO implementation with some ringbuffer structure without pruning could be more simple and effiecient.
https://substrate-developer-hub.github.io/substrate-how-to-guides/docs/storage-migrations/ringbuffer/

@ParthDesai
Copy link
Contributor Author

ParthDesai commented Apr 21, 2023

@ParthDesai Cool and thanks for the contribution! Though IMHO implementation with some ringbuffer structure without pruning could be more simple and effiecient. https://substrate-developer-hub.github.io/substrate-how-to-guides/docs/storage-migrations/ringbuffer/

The while loop here is not supposed to be running more than one time in current version of code base. As it tries to prune oldest entry after every insert.

The while loop is there as I wanted to write a generalized pruning function that does not make assumption about number of entries above threshold.

@ParthDesai
Copy link
Contributor Author

@ParthDesai Cool and thanks for the contribution! Though IMHO implementation with some ringbuffer structure without pruning could be more simple and effiecient. https://substrate-developer-hub.github.io/substrate-how-to-guides/docs/storage-migrations/ringbuffer/

But, yes. The Ringbuffer structure does look like something which can be more efficient and simple than this. I will open another PR with updated implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants