github.com/Finschia/finschia-sdk@v0.48.1/x/staking/keeper/historical_info.go (about) 1 package keeper 2 3 import ( 4 sdk "github.com/Finschia/finschia-sdk/types" 5 "github.com/Finschia/finschia-sdk/x/staking/types" 6 ) 7 8 // GetHistoricalInfo gets the historical info at a given height 9 func (k Keeper) GetHistoricalInfo(ctx sdk.Context, height int64) (types.HistoricalInfo, bool) { 10 store := ctx.KVStore(k.storeKey) 11 key := types.GetHistoricalInfoKey(height) 12 13 value := store.Get(key) 14 if value == nil { 15 return types.HistoricalInfo{}, false 16 } 17 18 return types.MustUnmarshalHistoricalInfo(k.cdc, value), true 19 } 20 21 // SetHistoricalInfo sets the historical info at a given height 22 func (k Keeper) SetHistoricalInfo(ctx sdk.Context, height int64, hi *types.HistoricalInfo) { 23 store := ctx.KVStore(k.storeKey) 24 key := types.GetHistoricalInfoKey(height) 25 value := k.cdc.MustMarshal(hi) 26 store.Set(key, value) 27 } 28 29 // DeleteHistoricalInfo deletes the historical info at a given height 30 func (k Keeper) DeleteHistoricalInfo(ctx sdk.Context, height int64) { 31 store := ctx.KVStore(k.storeKey) 32 key := types.GetHistoricalInfoKey(height) 33 34 store.Delete(key) 35 } 36 37 // IterateHistoricalInfo provides an interator over all stored HistoricalInfo 38 // 39 // objects. For each HistoricalInfo object, cb will be called. If the cb returns 40 // 41 // true, the iterator will close and stop. 42 func (k Keeper) IterateHistoricalInfo(ctx sdk.Context, cb func(types.HistoricalInfo) bool) { 43 store := ctx.KVStore(k.storeKey) 44 45 iterator := sdk.KVStorePrefixIterator(store, types.HistoricalInfoKey) 46 defer iterator.Close() 47 48 for ; iterator.Valid(); iterator.Next() { 49 histInfo := types.MustUnmarshalHistoricalInfo(k.cdc, iterator.Value()) 50 if cb(histInfo) { 51 break 52 } 53 } 54 } 55 56 // GetAllHistoricalInfo returns all stored HistoricalInfo objects. 57 func (k Keeper) GetAllHistoricalInfo(ctx sdk.Context) []types.HistoricalInfo { 58 var infos []types.HistoricalInfo 59 60 k.IterateHistoricalInfo(ctx, func(histInfo types.HistoricalInfo) bool { 61 infos = append(infos, histInfo) 62 return false 63 }) 64 65 return infos 66 } 67 68 // TrackHistoricalInfo saves the latest historical-info and deletes the oldest 69 // heights that are below pruning height 70 func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) { 71 entryNum := k.HistoricalEntries(ctx) 72 73 // Prune store to ensure we only have parameter-defined historical entries. 74 // In most cases, this will involve removing a single historical entry. 75 // In the rare scenario when the historical entries gets reduced to a lower value k' 76 // from the original value k. k - k' entries must be deleted from the store. 77 // Since the entries to be deleted are always in a continuous range, we can iterate 78 // over the historical entries starting from the most recent version to be pruned 79 // and then return at the first empty entry. 80 for i := ctx.BlockHeight() - int64(entryNum); i >= 0; i-- { 81 _, found := k.GetHistoricalInfo(ctx, i) 82 if found { 83 k.DeleteHistoricalInfo(ctx, i) 84 } else { 85 break 86 } 87 } 88 89 // if there is no need to persist historicalInfo, return 90 if entryNum == 0 { 91 return 92 } 93 94 // Create HistoricalInfo struct 95 lastVals := k.GetLastValidators(ctx) 96 historicalEntry := types.NewHistoricalInfo(ctx.BlockHeader(), lastVals, k.PowerReduction(ctx)) 97 98 // Set latest HistoricalInfo at current height 99 k.SetHistoricalInfo(ctx, ctx.BlockHeight(), &historicalEntry) 100 }