github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/staking/genesis.go (about) 1 package staking 2 3 import ( 4 "fmt" 5 6 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 7 tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types" 8 9 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 10 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking/exported" 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking/types" 12 ) 13 14 // InitGenesis sets the pool and parameters for the provided keeper. For each 15 // validator in data, it sets that validator in the keeper along with manually 16 // setting the indexes. In addition, it also sets any delegations found in 17 // data. Finally, it updates the bonded validators. 18 // Returns final validator set after applying all declaration and delegations 19 func InitGenesis(ctx sdk.Context, keeper Keeper, accountKeeper types.AccountKeeper, 20 supplyKeeper types.SupplyKeeper, data types.GenesisState) (res []abci.ValidatorUpdate) { 21 22 bondedTokens := sdk.ZeroInt() 23 notBondedTokens := sdk.ZeroInt() 24 25 // We need to pretend to be "n blocks before genesis", where "n" is the 26 // validator update delay, so that e.g. slashing periods are correctly 27 // initialized for the validator set e.g. with a one-block offset - the 28 // first TM block is at height 1, so state updates applied from 29 // genesis.json are in block 0. 30 ctx.SetBlockHeight(1 - sdk.ValidatorUpdateDelay) 31 32 keeper.SetParams(ctx, data.Params) 33 keeper.SetLastTotalPower(ctx, data.LastTotalPower) 34 35 for _, validator := range data.Validators { 36 keeper.SetValidator(ctx, validator) 37 38 // Manually set indices for the first time 39 keeper.SetValidatorByConsAddr(ctx, validator) 40 keeper.SetValidatorByPowerIndex(ctx, validator) 41 42 // Call the creation hook if not exported 43 if !data.Exported { 44 keeper.AfterValidatorCreated(ctx, validator.OperatorAddress) 45 } 46 47 // update timeslice if necessary 48 if validator.IsUnbonding() { 49 keeper.InsertValidatorQueue(ctx, validator) 50 } 51 52 switch validator.GetStatus() { 53 case sdk.Bonded: 54 bondedTokens = bondedTokens.Add(validator.GetTokens()) 55 case sdk.Unbonding, sdk.Unbonded: 56 notBondedTokens = notBondedTokens.Add(validator.GetTokens()) 57 default: 58 panic("invalid validator status") 59 } 60 } 61 62 for _, delegation := range data.Delegations { 63 // Call the before-creation hook if not exported 64 if !data.Exported { 65 keeper.BeforeDelegationCreated(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress) 66 } 67 keeper.SetDelegation(ctx, delegation) 68 69 // Call the after-modification hook if not exported 70 if !data.Exported { 71 keeper.AfterDelegationModified(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress) 72 } 73 } 74 75 for _, ubd := range data.UnbondingDelegations { 76 keeper.SetUnbondingDelegation(ctx, ubd) 77 for _, entry := range ubd.Entries { 78 keeper.InsertUBDQueue(ctx, ubd, entry.CompletionTime) 79 notBondedTokens = notBondedTokens.Add(entry.Balance) 80 } 81 } 82 83 for _, red := range data.Redelegations { 84 keeper.SetRedelegation(ctx, red) 85 for _, entry := range red.Entries { 86 keeper.InsertRedelegationQueue(ctx, red, entry.CompletionTime) 87 } 88 } 89 90 bondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, bondedTokens)) 91 notBondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, notBondedTokens)) 92 93 // check if the unbonded and bonded pools accounts exists 94 bondedPool := keeper.GetBondedPool(ctx) 95 if bondedPool == nil { 96 panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName)) 97 } 98 99 // TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862 100 // add coins if not provided on genesis 101 if bondedPool.GetCoins().IsZero() { 102 if err := bondedPool.SetCoins(bondedCoins); err != nil { 103 panic(err) 104 } 105 supplyKeeper.SetModuleAccount(ctx, bondedPool) 106 } 107 108 notBondedPool := keeper.GetNotBondedPool(ctx) 109 if notBondedPool == nil { 110 panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName)) 111 } 112 113 if notBondedPool.GetCoins().IsZero() { 114 if err := notBondedPool.SetCoins(notBondedCoins); err != nil { 115 panic(err) 116 } 117 supplyKeeper.SetModuleAccount(ctx, notBondedPool) 118 } 119 120 // don't need to run Tendermint updates if we exported 121 if data.Exported { 122 for _, lv := range data.LastValidatorPowers { 123 keeper.SetLastValidatorPower(ctx, lv.Address, lv.Power) 124 validator, found := keeper.GetValidator(ctx, lv.Address) 125 if !found { 126 panic(fmt.Sprintf("validator %s not found", lv.Address)) 127 } 128 update := validator.ABCIValidatorUpdate() 129 update.Power = lv.Power // keep the next-val-set offset, use the last power for the first block 130 res = append(res, update) 131 } 132 } else { 133 res = keeper.ApplyAndReturnValidatorSetUpdates(ctx) 134 } 135 136 return res 137 } 138 139 // ExportGenesis returns a GenesisState for a given context and keeper. The 140 // GenesisState will contain the pool, params, validators, and bonds found in 141 // the keeper. 142 func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { 143 params := keeper.GetParams(ctx) 144 lastTotalPower := keeper.GetLastTotalPower(ctx) 145 validators := keeper.GetAllValidators(ctx) 146 delegations := keeper.GetAllDelegations(ctx) 147 var unbondingDelegations []types.UnbondingDelegation 148 keeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) { 149 unbondingDelegations = append(unbondingDelegations, ubd) 150 return false 151 }) 152 var redelegations []types.Redelegation 153 keeper.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) { 154 redelegations = append(redelegations, red) 155 return false 156 }) 157 var lastValidatorPowers []types.LastValidatorPower 158 keeper.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) { 159 lastValidatorPowers = append(lastValidatorPowers, types.LastValidatorPower{Address: addr, Power: power}) 160 return false 161 }) 162 163 return types.GenesisState{ 164 Params: params, 165 LastTotalPower: lastTotalPower, 166 LastValidatorPowers: lastValidatorPowers, 167 Validators: validators, 168 Delegations: delegations, 169 UnbondingDelegations: unbondingDelegations, 170 Redelegations: redelegations, 171 Exported: true, 172 } 173 } 174 175 // WriteValidators returns a slice of bonded genesis validators. 176 func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) { 177 keeper.IterateLastValidators(ctx, func(_ int64, validator exported.ValidatorI) (stop bool) { 178 vals = append(vals, tmtypes.GenesisValidator{ 179 PubKey: validator.GetConsPubKey(), 180 Power: validator.GetConsensusPower(), 181 Name: validator.GetMoniker(), 182 }) 183 184 return false 185 }) 186 187 return 188 } 189 190 // ValidateGenesis validates the provided staking genesis state to ensure the 191 // expected invariants holds. (i.e. params in correct bounds, no duplicate validators) 192 func ValidateGenesis(data types.GenesisState) error { 193 err := validateGenesisStateValidators(data.Validators) 194 if err != nil { 195 return err 196 } 197 err = data.Params.Validate() 198 if err != nil { 199 return err 200 } 201 202 return nil 203 } 204 205 func validateGenesisStateValidators(validators []types.Validator) (err error) { 206 addrMap := make(map[string]bool, len(validators)) 207 for i := 0; i < len(validators); i++ { 208 val := validators[i] 209 strKey := string(val.ConsPubKey.Bytes()) 210 if _, ok := addrMap[strKey]; ok { 211 return fmt.Errorf("duplicate validator in genesis state: moniker %v, address %v", val.Description.Moniker, val.ConsAddress()) 212 } 213 if val.Jailed && val.IsBonded() { 214 return fmt.Errorf("validator is bonded and jailed in genesis state: moniker %v, address %v", val.Description.Moniker, val.ConsAddress()) 215 } 216 if val.DelegatorShares.IsZero() && !val.IsUnbonding() { 217 return fmt.Errorf("bonded/unbonded genesis validator cannot have zero delegator shares, validator: %v", val) 218 } 219 addrMap[strKey] = true 220 } 221 return 222 }