Skip to content

Commit

Permalink
refactor: move x/staking Init/Export genesis to keeper (#11866)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbez authored May 4, 2022
1 parent 35d3312 commit 35c8146
Show file tree
Hide file tree
Showing 7 changed files with 429 additions and 404 deletions.
3 changes: 1 addition & 2 deletions x/genutil/gentx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

Expand Down Expand Up @@ -181,7 +180,7 @@ func (suite *GenTxTestSuite) TestValidateAccountInGenesis() {
cdc := suite.encodingConfig.Codec

suite.app.StakingKeeper.SetParams(suite.ctx, stakingtypes.DefaultParams())
stakingGenesisState := staking.ExportGenesis(suite.ctx, suite.app.StakingKeeper)
stakingGenesisState := suite.app.StakingKeeper.ExportGenesis(suite.ctx)
suite.Require().Equal(stakingGenesisState.Params, stakingtypes.DefaultParams())
stakingGenesis, err := cdc.MarshalJSON(stakingGenesisState) // TODO switch this to use Marshaler
suite.Require().NoError(err)
Expand Down
3 changes: 1 addition & 2 deletions x/gov/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/gov/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

Expand Down Expand Up @@ -56,7 +55,7 @@ func TestImportExportQueues(t *testing.T) {

authGenState := auth.ExportGenesis(ctx, app.AccountKeeper)
bankGenState := app.BankKeeper.ExportGenesis(ctx)
stakingGenState := staking.ExportGenesis(ctx, app.StakingKeeper)
stakingGenState := app.StakingKeeper.ExportGenesis(ctx)
distributionGenState := app.DistrKeeper.ExportGenesis(ctx)

// export the state and import it into a new app
Expand Down
196 changes: 0 additions & 196 deletions x/staking/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package staking
import (
"fmt"

abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"

cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
Expand All @@ -12,201 +11,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/staking/types"
)

// InitGenesis sets the pool and parameters for the provided keeper. For each
// validator in data, it sets that validator in the keeper along with manually
// setting the indexes. In addition, it also sets any delegations found in
// data. Finally, it updates the bonded validators.
// Returns final validator set after applying all declaration and delegations
func InitGenesis(
ctx sdk.Context, keeper keeper.Keeper, accountKeeper types.AccountKeeper,
bankKeeper types.BankKeeper, data *types.GenesisState,
) (res []abci.ValidatorUpdate) {
bondedTokens := sdk.ZeroInt()
notBondedTokens := sdk.ZeroInt()

// We need to pretend to be "n blocks before genesis", where "n" is the
// validator update delay, so that e.g. slashing periods are correctly
// initialized for the validator set e.g. with a one-block offset - the
// first TM block is at height 1, so state updates applied from
// genesis.json are in block 0.
ctx = ctx.WithBlockHeight(1 - sdk.ValidatorUpdateDelay)

keeper.SetParams(ctx, data.Params)
keeper.SetLastTotalPower(ctx, data.LastTotalPower)

for _, validator := range data.Validators {
keeper.SetValidator(ctx, validator)

// Manually set indices for the first time
keeper.SetValidatorByConsAddr(ctx, validator)
keeper.SetValidatorByPowerIndex(ctx, validator)

// Call the creation hook if not exported
if !data.Exported {
if err := keeper.AfterValidatorCreated(ctx, validator.GetOperator()); err != nil {
panic(err)
}
}

// update timeslice if necessary
if validator.IsUnbonding() {
keeper.InsertUnbondingValidatorQueue(ctx, validator)
}

switch validator.GetStatus() {
case types.Bonded:
bondedTokens = bondedTokens.Add(validator.GetTokens())
case types.Unbonding, types.Unbonded:
notBondedTokens = notBondedTokens.Add(validator.GetTokens())
default:
panic("invalid validator status")
}
}

for _, delegation := range data.Delegations {
delegatorAddress, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress)
if err != nil {
panic(err)
}

// Call the before-creation hook if not exported
if !data.Exported {
if err := keeper.BeforeDelegationCreated(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil {
panic(err)
}
}

keeper.SetDelegation(ctx, delegation)

// Call the after-modification hook if not exported
if !data.Exported {
if err := keeper.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()); err != nil {
panic(err)
}
}
}

for _, ubd := range data.UnbondingDelegations {
keeper.SetUnbondingDelegation(ctx, ubd)

for _, entry := range ubd.Entries {
keeper.InsertUBDQueue(ctx, ubd, entry.CompletionTime)
notBondedTokens = notBondedTokens.Add(entry.Balance)
}
}

for _, red := range data.Redelegations {
keeper.SetRedelegation(ctx, red)

for _, entry := range red.Entries {
keeper.InsertRedelegationQueue(ctx, red, entry.CompletionTime)
}
}

bondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, bondedTokens))
notBondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, notBondedTokens))

// check if the unbonded and bonded pools accounts exists
bondedPool := keeper.GetBondedPool(ctx)
if bondedPool == nil {
panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName))
}

// TODO: remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862
bondedBalance := bankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
if bondedBalance.IsZero() {
accountKeeper.SetModuleAccount(ctx, bondedPool)
}

// if balance is different from bonded coins panic because genesis is most likely malformed
if !bondedBalance.IsEqual(bondedCoins) {
panic(fmt.Sprintf("bonded pool balance is different from bonded coins: %s <-> %s", bondedBalance, bondedCoins))
}

notBondedPool := keeper.GetNotBondedPool(ctx)
if notBondedPool == nil {
panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName))
}

notBondedBalance := bankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress())
if notBondedBalance.IsZero() {
accountKeeper.SetModuleAccount(ctx, notBondedPool)
}

// If balance is different from non bonded coins panic because genesis is most
// likely malformed.
if !notBondedBalance.IsEqual(notBondedCoins) {
panic(fmt.Sprintf("not bonded pool balance is different from not bonded coins: %s <-> %s", notBondedBalance, notBondedCoins))
}

// don't need to run Tendermint updates if we exported
if data.Exported {
for _, lv := range data.LastValidatorPowers {
valAddr, err := sdk.ValAddressFromBech32(lv.Address)
if err != nil {
panic(err)
}

keeper.SetLastValidatorPower(ctx, valAddr, lv.Power)
validator, found := keeper.GetValidator(ctx, valAddr)

if !found {
panic(fmt.Sprintf("validator %s not found", lv.Address))
}

update := validator.ABCIValidatorUpdate(keeper.PowerReduction(ctx))
update.Power = lv.Power // keep the next-val-set offset, use the last power for the first block
res = append(res, update)
}
} else {
var err error

res, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
panic(err)
}
}

return res
}

// ExportGenesis returns a GenesisState for a given context and keeper. The
// GenesisState will contain the pool, params, validators, and bonds found in
// the keeper.
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState {
var unbondingDelegations []types.UnbondingDelegation

keeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
unbondingDelegations = append(unbondingDelegations, ubd)
return false
})

var redelegations []types.Redelegation

keeper.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) {
redelegations = append(redelegations, red)
return false
})

var lastValidatorPowers []types.LastValidatorPower

keeper.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) {
lastValidatorPowers = append(lastValidatorPowers, types.LastValidatorPower{Address: addr.String(), Power: power})
return false
})

return &types.GenesisState{
Params: keeper.GetParams(ctx),
LastTotalPower: keeper.GetLastTotalPower(ctx),
LastValidatorPowers: lastValidatorPowers,
Validators: keeper.GetAllValidators(ctx),
Delegations: keeper.GetAllDelegations(ctx),
UnbondingDelegations: unbondingDelegations,
Redelegations: redelegations,
Exported: true,
}
}

// WriteValidators returns a slice of bonded genesis validators.
func WriteValidators(ctx sdk.Context, keeper keeper.Keeper) (vals []tmtypes.GenesisValidator, err error) {
keeper.IterateLastValidators(ctx, func(_ int64, validator types.ValidatorI) (stop bool) {
Expand Down
Loading

0 comments on commit 35c8146

Please sign in to comment.