store/rootmulti: On initialization, prune all old versions according to existing settings #10942
Description
Summary
If you update pruning settings, it will never prune old state. Prune heights are tracked by a pruneHeights variable in RAM thats updated after each block, and a separate region of disk being written to track recent blocks that need to be pruned at next pruning interval.
However, at rootmulti store load, it should get all versions from the underlying database (or at least the oldest version to handle removing keep-every), and then prune everything that should be pruned according to the new settings.
Problem Definition
So node operators can change their pruning settings, and actually get space savings.
Proposal
-
Add a
GetAllVersions
function to IAVL's nodeDB. -
In RootMultiStore, change the following logic in loadVersion: https://github.com/cosmos/cosmos-sdk/blob/master/store/rootmulti/store.go#L265-L269 to the following (pseudocode):
func (rs *Store) PruneOnInitialLoad() {
if rs.HasAlreadyPrunedThisLoad || rs.pruningOptions.KeepEvery == 0 {
return
}
for key, store := range rs.stores {
if store.GetStoreType() == types.StoreTypeIAVL {
// If the store is wrapped with an inter-block cache, we must first unwrap
// it to get the underlying IAVL store.
store = rs.GetCommitKVStore(key)
latestVersion := store.GetLatestVersion()
allVersions := store.GetAllVersions()
pruneVersions := []int64{}
for v := range allVersions {
if v % rs.PruningOptions.KeepEvery != 0 && v + rs.PruningOptions.KeepRecent < latestVersion {
pruneVersions = append(pruneVersions, v)
}
}
if err := store.(*iavl.Store).DeleteVersions(pruneVersions...); err != nil {
if errCause := errors.Cause(err); errCause != nil && errCause != iavltree.ErrVersionDoesNotExist {
panic(err)
}
}
}
}
}
For Admin Use
- Not duplicate issue
- Appropriate labels applied
- Appropriate contributors tagged
- Contributor assigned/self-assigned