diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 918bfc67d..765d624e9 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -251,6 +251,8 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData) mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData) distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData) + + // validate genesis state err = GaiaValidateGenesisState(genesisState) if err != nil { panic(err) // TODO find a way to do this w/o panics diff --git a/x/stake/genesis.go b/x/stake/genesis.go index d44055ea8..42a18f904 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -29,17 +29,9 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ keeper.SetIntraTxCounter(ctx, data.IntraTxCounter) keeper.SetLastTotalPower(ctx, data.LastTotalPower) - // We only need to set this if we're starting from a list of validators, not a state export - setBondIntraTxCounter := true - for _, validator := range data.Validators { - if validator.BondIntraTxCounter != 0 { - setBondIntraTxCounter = false - } - } - for i, validator := range data.Validators { // set the intra-tx counter to the order the validators are presented, if necessary - if setBondIntraTxCounter { + if !data.Exported { validator.BondIntraTxCounter = int16(i) } keeper.SetValidator(ctx, validator) @@ -77,6 +69,16 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ } res = keeper.ApplyAndReturnValidatorSetUpdates(ctx) + + // overwrite the pool since we exported + if data.Exported { + keeper.SetPool(ctx, data.Pool) + keeper.ClearLastValidatorPowers(ctx) + for _, lv := range data.LastValidatorPowers { + keeper.SetLastValidatorPower(ctx, lv.Address, lv.Power) + } + } + return } @@ -100,16 +102,23 @@ func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState { redelegations = append(redelegations, red) return false }) + var lastValidatorPowers []types.LastValidatorPower + keeper.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power sdk.Int) (stop bool) { + lastValidatorPowers = append(lastValidatorPowers, types.LastValidatorPower{addr, power}) + return false + }) return types.GenesisState{ Pool: pool, Params: params, IntraTxCounter: intraTxCounter, LastTotalPower: lastTotalPower, + LastValidatorPowers: lastValidatorPowers, Validators: validators, Bonds: bonds, UnbondingDelegations: unbondingDelegations, Redelegations: redelegations, + Exported: true, } } diff --git a/x/stake/keeper/keeper.go b/x/stake/keeper/keeper.go index a74f86084..70506f6ab 100644 --- a/x/stake/keeper/keeper.go +++ b/x/stake/keeper/keeper.go @@ -112,6 +112,31 @@ func (k Keeper) SetLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress, store.Set(GetLastValidatorPowerKey(operator), bz) } +// Iterate over last validator powers. +func (k Keeper) IterateLastValidatorPowers(ctx sdk.Context, handler func(operator sdk.ValAddress, power sdk.Int) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, LastValidatorPowerKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + addr := sdk.ValAddress(iter.Key()[len(LastValidatorPowerKey):]) + var power sdk.Int + k.cdc.MustUnmarshalBinaryLengthPrefixed(iter.Value(), &power) + if handler(addr, power) { + break + } + } +} + +// Clear last validator powers. +func (k Keeper) ClearLastValidatorPowers(ctx sdk.Context) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, LastValidatorPowerKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + store.Delete(iter.Key()) + } +} + // Delete the last validator power. func (k Keeper) DeleteLastValidatorPower(ctx sdk.Context, operator sdk.ValAddress) { store := ctx.KVStore(k.storeKey) diff --git a/x/stake/types/genesis.go b/x/stake/types/genesis.go index f1673a376..1085e8f97 100644 --- a/x/stake/types/genesis.go +++ b/x/stake/types/genesis.go @@ -10,10 +10,18 @@ type GenesisState struct { Params Params `json:"params"` IntraTxCounter int16 `json:"intra_tx_counter"` LastTotalPower sdk.Int `json:"last_total_power"` + LastValidatorPowers []LastValidatorPower `json:"last_validator_powers"` Validators []Validator `json:"validators"` Bonds []Delegation `json:"bonds"` UnbondingDelegations []UnbondingDelegation `json:"unbonding_delegations"` Redelegations []Redelegation `json:"redelegations"` + Exported bool `json:"exported"` +} + +// Last validator power, needed for validator set update logic +type LastValidatorPower struct { + Address sdk.ValAddress + Power sdk.Int } func NewGenesisState(pool Pool, params Params, validators []Validator, bonds []Delegation) GenesisState {