github.com/Finschia/finschia-sdk@v0.48.1/simapp/export.go (about) 1 package simapp 2 3 import ( 4 "encoding/json" 5 "log" 6 7 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 8 9 servertypes "github.com/Finschia/finschia-sdk/server/types" 10 sdk "github.com/Finschia/finschia-sdk/types" 11 slashingtypes "github.com/Finschia/finschia-sdk/x/slashing/types" 12 "github.com/Finschia/finschia-sdk/x/staking" 13 stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" 14 ) 15 16 // ExportAppStateAndValidators exports the state of the application for a genesis 17 // file. 18 func (app *SimApp) ExportAppStateAndValidators( 19 forZeroHeight bool, jailAllowedAddrs []string, 20 ) (servertypes.ExportedApp, error) { 21 // as if they could withdraw from the start of the next block 22 ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) 23 24 // We export at last height + 1, because that's the height at which 25 // Tendermint will start InitChain. 26 height := app.LastBlockHeight() + 1 27 if forZeroHeight { 28 height = 0 29 app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs) 30 } 31 32 genState := app.mm.ExportGenesis(ctx, app.appCodec) 33 appState, err := json.MarshalIndent(genState, "", " ") 34 if err != nil { 35 return servertypes.ExportedApp{}, err 36 } 37 38 validators, err := staking.WriteValidators(ctx, app.StakingKeeper) 39 return servertypes.ExportedApp{ 40 AppState: appState, 41 Validators: validators, 42 Height: height, 43 ConsensusParams: app.BaseApp.GetConsensusParams(ctx), 44 }, err 45 } 46 47 // prepare for fresh start at zero height 48 // NOTE zero height genesis is a temporary feature which will be deprecated 49 // 50 // in favour of export at a block height 51 func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { 52 applyAllowedAddrs := false 53 54 // check if there is a allowed address list 55 if len(jailAllowedAddrs) > 0 { 56 applyAllowedAddrs = true 57 } 58 59 allowedAddrsMap := make(map[string]bool) 60 61 for _, addr := range jailAllowedAddrs { 62 _, err := sdk.ValAddressFromBech32(addr) 63 if err != nil { 64 log.Fatal(err) 65 } 66 allowedAddrsMap[addr] = true 67 } 68 69 /* Just to be safe, assert the invariants on current state. */ 70 app.CrisisKeeper.AssertInvariants(ctx) 71 72 /* Handle fee distribution state. */ 73 74 // withdraw all validator commission 75 app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) { 76 _, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator()) 77 return false 78 }) 79 80 // withdraw all delegator rewards 81 dels := app.StakingKeeper.GetAllDelegations(ctx) 82 for _, delegation := range dels { 83 valAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) 84 if err != nil { 85 panic(err) 86 } 87 88 delAddr := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) 89 90 _, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr) 91 } 92 93 // clear validator slash events 94 app.DistrKeeper.DeleteAllValidatorSlashEvents(ctx) 95 96 // clear validator historical rewards 97 app.DistrKeeper.DeleteAllValidatorHistoricalRewards(ctx) 98 99 // set context height to zero 100 height := ctx.BlockHeight() 101 ctx = ctx.WithBlockHeight(0) 102 103 // reinitialize all validators 104 app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) { 105 // donate any unwithdrawn outstanding reward fraction tokens to the community pool 106 scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator()) 107 feePool := app.DistrKeeper.GetFeePool(ctx) 108 feePool.CommunityPool = feePool.CommunityPool.Add(scraps...) 109 app.DistrKeeper.SetFeePool(ctx, feePool) 110 111 app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()) 112 return false 113 }) 114 115 // reinitialize all delegations 116 for _, del := range dels { 117 valAddr, err := sdk.ValAddressFromBech32(del.ValidatorAddress) 118 if err != nil { 119 panic(err) 120 } 121 delAddr := sdk.MustAccAddressFromBech32(del.DelegatorAddress) 122 app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr) 123 app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr) 124 } 125 126 // reset context height 127 ctx = ctx.WithBlockHeight(height) 128 129 /* Handle staking state. */ 130 131 // iterate through redelegations, reset creation height 132 app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) { 133 for i := range red.Entries { 134 red.Entries[i].CreationHeight = 0 135 } 136 app.StakingKeeper.SetRedelegation(ctx, red) 137 return false 138 }) 139 140 // iterate through unbonding delegations, reset creation height 141 app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd stakingtypes.UnbondingDelegation) (stop bool) { 142 for i := range ubd.Entries { 143 ubd.Entries[i].CreationHeight = 0 144 } 145 app.StakingKeeper.SetUnbondingDelegation(ctx, ubd) 146 return false 147 }) 148 149 // Iterate through validators by power descending, reset bond heights, and 150 // update bond intra-tx counters. 151 store := ctx.KVStore(app.keys[stakingtypes.StoreKey]) 152 iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey) 153 counter := int16(0) 154 155 for ; iter.Valid(); iter.Next() { 156 addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key())) 157 validator, found := app.StakingKeeper.GetValidator(ctx, addr) 158 if !found { 159 panic("expected validator, not found") 160 } 161 162 validator.UnbondingHeight = 0 163 if applyAllowedAddrs && !allowedAddrsMap[addr.String()] { 164 validator.Jailed = true 165 } 166 167 app.StakingKeeper.SetValidator(ctx, validator) 168 counter++ 169 } 170 171 iter.Close() 172 173 _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 174 if err != nil { 175 log.Fatal(err) 176 } 177 178 /* Handle slashing state. */ 179 180 // reset start height on signing infos 181 app.SlashingKeeper.IterateValidatorSigningInfos( 182 ctx, 183 func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) { 184 info.StartHeight = 0 185 app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info) 186 return false 187 }, 188 ) 189 }