29d3abcf09
* Reuse cosmos-sdk client library to create keyring Extracted from https://github.com/evmos/ethermint/pull/1168 Cleanup cmd code for easier to migration to cosmos-sdk 0.46 * Update cosmos-sdk v0.46 prepare for implementing cosmos-sdk feemarket and tx prioritization changelog refactor cmd use sdkmath fix lint fix unit tests fix unit test genesis fix unit tests fix unit test env setup fix unit tests fix unit tests register PrivKey impl fix extension options fix lint fix unit tests make HandlerOption.Validate private gofumpt fix msg response decoding fix sim test bump cosmos-sdk version fix sim test sdk 46 fix unit test fix unit tests update ibc-go
216 lines
6.4 KiB
Go
216 lines
6.4 KiB
Go
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
|
|
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
|
"github.com/cosmos/cosmos-sdk/simapp"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
|
"github.com/cosmos/cosmos-sdk/x/staking"
|
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
|
|
|
"github.com/evmos/ethermint/encoding"
|
|
)
|
|
|
|
// NewDefaultGenesisState generates the default state for the application.
|
|
func NewDefaultGenesisState() simapp.GenesisState {
|
|
encCfg := encoding.MakeConfig(ModuleBasics)
|
|
return ModuleBasics.DefaultGenesis(encCfg.Codec)
|
|
}
|
|
|
|
// ExportAppStateAndValidators exports the state of the application for a genesis
|
|
// file.
|
|
func (app *EthermintApp) ExportAppStateAndValidators(
|
|
forZeroHeight bool, jailAllowedAddrs []string,
|
|
) (servertypes.ExportedApp, error) {
|
|
// Creates context with current height and checks txs for ctx to be usable by start of next block
|
|
ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()})
|
|
|
|
// We export at last height + 1, because that's the height at which
|
|
// Tendermint will start InitChain.
|
|
height := app.LastBlockHeight() + 1
|
|
if forZeroHeight {
|
|
height = 0
|
|
|
|
if err := app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs); err != nil {
|
|
return servertypes.ExportedApp{}, err
|
|
}
|
|
}
|
|
|
|
genState := app.mm.ExportGenesis(ctx, app.appCodec)
|
|
appState, err := json.MarshalIndent(genState, "", " ")
|
|
if err != nil {
|
|
return servertypes.ExportedApp{}, err
|
|
}
|
|
|
|
validators, err := staking.WriteValidators(ctx, app.StakingKeeper)
|
|
if err != nil {
|
|
return servertypes.ExportedApp{}, err
|
|
}
|
|
|
|
return servertypes.ExportedApp{
|
|
AppState: appState,
|
|
Validators: validators,
|
|
Height: height,
|
|
ConsensusParams: app.BaseApp.GetConsensusParams(ctx),
|
|
}, nil
|
|
}
|
|
|
|
// prepare for fresh start at zero height
|
|
// NOTE zero height genesis is a temporary feature which will be deprecated
|
|
// in favor of export at a block height
|
|
func (app *EthermintApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) error {
|
|
applyAllowedAddrs := false
|
|
|
|
// check if there is a allowed address list
|
|
if len(jailAllowedAddrs) > 0 {
|
|
applyAllowedAddrs = true
|
|
}
|
|
|
|
allowedAddrsMap := make(map[string]bool)
|
|
|
|
for _, addr := range jailAllowedAddrs {
|
|
_, err := sdk.ValAddressFromBech32(addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
allowedAddrsMap[addr] = true
|
|
}
|
|
|
|
/* Just to be safe, assert the invariants on current state. */
|
|
app.CrisisKeeper.AssertInvariants(ctx)
|
|
|
|
/* Handle fee distribution state. */
|
|
|
|
// withdraw all validator commission
|
|
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
|
|
_, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator())
|
|
return false
|
|
})
|
|
|
|
// withdraw all delegator rewards
|
|
dels := app.StakingKeeper.GetAllDelegations(ctx)
|
|
for _, delegation := range dels {
|
|
valAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
delAddr, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr)
|
|
}
|
|
|
|
// clear validator slash events
|
|
app.DistrKeeper.DeleteAllValidatorSlashEvents(ctx)
|
|
|
|
// clear validator historical rewards
|
|
app.DistrKeeper.DeleteAllValidatorHistoricalRewards(ctx)
|
|
|
|
// set context height to zero
|
|
height := ctx.BlockHeight()
|
|
ctx = ctx.WithBlockHeight(0)
|
|
|
|
// reinitialize all validators
|
|
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
|
|
// donate any unwithdrawn outstanding reward fraction tokens to the community pool
|
|
scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator())
|
|
feePool := app.DistrKeeper.GetFeePool(ctx)
|
|
feePool.CommunityPool = feePool.CommunityPool.Add(scraps...)
|
|
app.DistrKeeper.SetFeePool(ctx, feePool)
|
|
|
|
if err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()); err != nil {
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
|
|
// reinitialize all delegations
|
|
for _, del := range dels {
|
|
valAddr, err := sdk.ValAddressFromBech32(del.ValidatorAddress)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
delAddr, err := sdk.AccAddressFromBech32(del.DelegatorAddress)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil {
|
|
return err
|
|
}
|
|
if err := app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// reset context height
|
|
ctx = ctx.WithBlockHeight(height)
|
|
|
|
/* Handle staking state. */
|
|
|
|
// iterate through redelegations, reset creation height
|
|
app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) {
|
|
for i := range red.Entries {
|
|
red.Entries[i].CreationHeight = 0
|
|
}
|
|
app.StakingKeeper.SetRedelegation(ctx, red)
|
|
return false
|
|
})
|
|
|
|
// iterate through unbonding delegations, reset creation height
|
|
app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd stakingtypes.UnbondingDelegation) (stop bool) {
|
|
for i := range ubd.Entries {
|
|
ubd.Entries[i].CreationHeight = 0
|
|
}
|
|
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
|
|
return false
|
|
})
|
|
|
|
// Iterate through validators by power descending, reset bond heights, and
|
|
// update bond intra-tx counters.
|
|
store := ctx.KVStore(app.keys[stakingtypes.StoreKey])
|
|
iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey)
|
|
|
|
for ; iter.Valid(); iter.Next() {
|
|
addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key()))
|
|
validator, found := app.StakingKeeper.GetValidator(ctx, addr)
|
|
if !found {
|
|
return fmt.Errorf("expected validator %s not found", addr)
|
|
}
|
|
|
|
validator.UnbondingHeight = 0
|
|
if applyAllowedAddrs && !allowedAddrsMap[addr.String()] {
|
|
validator.Jailed = true
|
|
}
|
|
|
|
app.StakingKeeper.SetValidator(ctx, validator)
|
|
}
|
|
|
|
if err := iter.Close(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx); err != nil {
|
|
return err
|
|
}
|
|
|
|
/* Handle slashing state. */
|
|
|
|
// reset start height on signing infos
|
|
app.SlashingKeeper.IterateValidatorSigningInfos(
|
|
ctx,
|
|
func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) {
|
|
info.StartHeight = 0
|
|
app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info)
|
|
return false
|
|
},
|
|
)
|
|
return nil
|
|
}
|