github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/staking/genesis.go (about) 1 package staking 2 3 import ( 4 "fmt" 5 6 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 7 supplyexported "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply/exported" 8 abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 9 tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types" 10 "github.com/fibonacci-chain/fbc/x/staking/exported" 11 "github.com/fibonacci-chain/fbc/x/staking/types" 12 ) 13 14 // InitGenesis sets the pool and parameters for the provided keeper 15 // For each validator in data, it sets that validator in the keeper along with manually setting the indexes 16 // In addition, it also sets any delegations found in data 17 // 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 bondedTokens, notBondedTokens := sdk.ZeroDec(), sdk.ZeroDec() 22 23 // We need to pretend to be "n blocks before genesis", where "n" is the validator update delay, so that e.g. 24 // slashing periods are correctly initialized for the validator set e.g. with a one-block offset - the first 25 // TM block is at height 1, so state updates applied from genesis.json are in block 0. 26 ctx.SetBlockHeight(1 - sdk.ValidatorUpdateDelay) 27 28 keeper.SetParams(ctx, data.Params) 29 keeper.SetLastTotalPower(ctx, data.LastTotalPower) 30 31 for _, validator := range data.Validators { 32 initValidator(ctx, validator, keeper, &bondedTokens, data.Exported) 33 } 34 35 for _, delegator := range data.Delegators { 36 initDelegator(ctx, delegator, keeper, &bondedTokens) 37 } 38 39 for _, ubd := range data.UnbondingDelegations { 40 initUnbondingDelegation(ctx, ubd, keeper, ¬BondedTokens) 41 } 42 for _, sharesExported := range data.AllShares { 43 keeper.SetShares(ctx, sharesExported.DelAddress, sharesExported.ValidatorAddress, sharesExported.Shares) 44 } 45 for _, proxyDelegatorKeyExported := range data.ProxyDelegatorKeys { 46 keeper.SetProxyBinding(ctx, proxyDelegatorKeyExported.ProxyAddr, proxyDelegatorKeyExported.DelAddr, false) 47 } 48 49 checkPools(ctx, keeper, sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, bondedTokens), 50 sdk.NewDecCoinFromDec(sdk.DefaultBondDenom, notBondedTokens), data.Exported) 51 52 // don't need to run Tendermint updates if we exported 53 if data.Exported { 54 for _, lv := range data.LastValidatorPowers { 55 keeper.SetLastValidatorPower(ctx, lv.Address, lv.Power) 56 validator, found := keeper.GetValidator(ctx, lv.Address) 57 if !found { 58 panic(fmt.Sprintf("validator %s not found", lv.Address)) 59 } 60 update := validator.ABCIValidatorUpdate() 61 update.Power = lv.Power // keep the next-val-set offset, use the last power for the first block 62 res = append(res, update) 63 } 64 } else { 65 res = keeper.ApplyAndReturnValidatorSetUpdates(ctx) 66 } 67 68 return res 69 } 70 71 // assume that there is only fibo in pool, if not panics 72 func checkTokenSum(tokenSum sdk.SysCoin, pool supplyexported.ModuleAccountI) { 73 poolCoins := pool.GetCoins() 74 if !poolCoins.IsZero() { 75 if len(poolCoins) != 1 { 76 panic(fmt.Sprintf("only fibo in %s, but there are %d kinds of coins", pool.GetName(), len(poolCoins))) 77 } 78 79 if !tokenSum.ToCoins().IsEqual(poolCoins) { 80 panic(fmt.Sprintf("coins in %s don't match the token sum, tokenSum: %s, poolCoins: %s", 81 pool.GetName(), tokenSum.String(), poolCoins.String())) 82 } 83 } 84 } 85 86 func checkPools(ctx sdk.Context, keeper Keeper, bondedDecCoin, notBondedDecCoin sdk.SysCoin, isExported bool) { 87 bondedPool := keeper.GetBondedPool(ctx) 88 if bondedPool == nil { 89 panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName)) 90 } 91 notBondedPool := keeper.GetNotBondedPool(ctx) 92 if notBondedPool == nil { 93 panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName)) 94 } 95 if isExported { 96 checkTokenSum(bondedDecCoin, bondedPool) 97 checkTokenSum(notBondedDecCoin, notBondedPool) 98 } 99 } 100 101 func initUnbondingDelegation(ctx sdk.Context, ubd UndelegationInfo, keeper Keeper, notBondedTokens *sdk.Dec) { 102 keeper.SetUndelegating(ctx, ubd) 103 keeper.SetAddrByTimeKeyWithNilValue(ctx, ubd.CompletionTime, ubd.DelegatorAddress) 104 *notBondedTokens = notBondedTokens.Add(ubd.Quantity) 105 } 106 107 func initDelegator(ctx sdk.Context, delegator Delegator, keeper Keeper, pBondedTokens *sdk.Dec) { 108 keeper.SetDelegator(ctx, delegator) 109 *pBondedTokens = pBondedTokens.Add(delegator.Tokens) 110 } 111 112 func initValidator(ctx sdk.Context, valExported ValidatorExport, keeper Keeper, pBondedTokens *sdk.Dec, exported bool) { 113 validator := valExported.Import() 114 keeper.SetValidator(ctx, validator) 115 116 // manually set indices for the first time 117 keeper.SetValidatorByConsAddr(ctx, validator) 118 keeper.SetValidatorByPowerIndex(ctx, validator) 119 120 // call the creation hook if not exported 121 if !exported { 122 keeper.AfterValidatorCreated(ctx, validator.OperatorAddress) 123 } 124 125 // update timeslice if necessary 126 if validator.IsUnbonding() { 127 keeper.InsertValidatorQueue(ctx, validator) 128 } 129 // all the msd on validator should be added into bonded pool 130 *pBondedTokens = pBondedTokens.Add(validator.MinSelfDelegation) 131 } 132 133 // ExportGenesis returns a GenesisState for a given context and keeper 134 // The GenesisState will contain the pool, params, validators, and bonds found in the keeper 135 func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { 136 params := keeper.GetParams(ctx) 137 lastTotalPower := keeper.GetLastTotalPower(ctx) 138 validators := keeper.GetAllValidators(ctx) 139 var delegators []types.Delegator 140 keeper.IterateDelegator(ctx, func(_ int64, delegator types.Delegator) (stop bool) { 141 delegators = append(delegators, delegator) 142 return false 143 }) 144 var undelegationInfos []types.UndelegationInfo 145 keeper.IterateUndelegationInfo(ctx, func(_ int64, ubd types.UndelegationInfo) (stop bool) { 146 undelegationInfos = append(undelegationInfos, ubd) 147 return false 148 }) 149 var lastValidatorPowers []types.LastValidatorPower 150 keeper.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) { 151 lastValidatorPowers = append(lastValidatorPowers, types.NewLastValidatorPower(addr, power)) 152 return false 153 }) 154 var sharesExportedSlice []types.SharesExported 155 keeper.IterateShares(ctx, 156 func(_ int64, delAddr sdk.AccAddress, valAddr sdk.ValAddress, shares types.Shares) (stop bool) { 157 sharesExportedSlice = append(sharesExportedSlice, types.NewSharesExported(delAddr, valAddr, shares)) 158 return false 159 }) 160 161 var proxyDelegatorKeys []types.ProxyDelegatorKeyExported 162 keeper.IterateProxy(ctx, []byte{}, false, func(_ int64, delAddr, proxyAddr sdk.AccAddress) (stop bool) { 163 proxyDelegatorKeys = append(proxyDelegatorKeys, types.NewProxyDelegatorKeyExported(delAddr, proxyAddr)) 164 return false 165 }) 166 167 return types.GenesisState{ 168 Params: params, 169 LastTotalPower: lastTotalPower, 170 LastValidatorPowers: lastValidatorPowers, 171 Validators: validators.Export(), 172 Delegators: delegators, 173 UnbondingDelegations: undelegationInfos, 174 AllShares: sharesExportedSlice, 175 ProxyDelegatorKeys: proxyDelegatorKeys, 176 Exported: true, 177 } 178 } 179 180 // GetLatestGenesisValidator returns a slice of bonded genesis validators 181 func GetLatestGenesisValidator(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) { 182 keeper.IterateLastValidators(ctx, func(_ int64, validator exported.ValidatorI) (stop bool) { 183 vals = append(vals, tmtypes.GenesisValidator{ 184 PubKey: validator.GetConsPubKey(), 185 Power: validator.GetConsensusPower(), 186 Name: validator.GetMoniker(), 187 }) 188 189 return false 190 }) 191 192 return 193 } 194 195 // ValidateGenesis validates the provided staking genesis state to ensure the expected invariants holds 196 // (i.e. params in correct bounds, no duplicate validators) 197 func ValidateGenesis(data types.GenesisState) error { 198 err := validateGenesisStateValidators(data.Validators) 199 if err != nil { 200 return err 201 } 202 return data.Params.Validate() 203 } 204 205 func validateGenesisStateValidators(valsExported []types.ValidatorExported) (err error) { 206 valsLen := len(valsExported) 207 addrMap := make(map[string]bool, valsLen) 208 for i := 0; i < valsLen; i++ { 209 valExported := valsExported[i] 210 strKey := valExported.ConsPubKey 211 if _, ok := addrMap[strKey]; ok { 212 return fmt.Errorf("duplicate validator in genesis state: moniker %v, address %v", 213 valExported.Description.Moniker, valExported.ConsAddress()) 214 } 215 if valExported.Jailed && valExported.IsBonded() { 216 return fmt.Errorf("validator is bonded and jailed in genesis state: moniker %v, address %v", 217 valExported.Description.Moniker, valExported.ConsAddress()) 218 } 219 if valExported.DelegatorShares.IsZero() { 220 return fmt.Errorf("it's impossible for a validator with zero delegator shares, validator: %v", valExported) 221 } 222 addrMap[strKey] = true 223 } 224 return 225 }