github.com/cosmos/cosmos-sdk@v0.50.10/x/staking/keeper/genesis.go (about)

     1  package keeper
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	abci "github.com/cometbft/cometbft/abci/types"
     8  
     9  	"cosmossdk.io/math"
    10  
    11  	sdk "github.com/cosmos/cosmos-sdk/types"
    12  	"github.com/cosmos/cosmos-sdk/x/staking/types"
    13  )
    14  
    15  // InitGenesis sets the pool and parameters for the provided keeper.  For each
    16  // validator in data, it sets that validator in the keeper along with manually
    17  // setting the indexes. In addition, it also sets any delegations found in
    18  // data. Finally, it updates the bonded validators.
    19  // Returns final validator set after applying all declaration and delegations
    20  func (k Keeper) InitGenesis(ctx context.Context, data *types.GenesisState) (res []abci.ValidatorUpdate) {
    21  	bondedTokens := math.ZeroInt()
    22  	notBondedTokens := math.ZeroInt()
    23  
    24  	// We need to pretend to be "n blocks before genesis", where "n" is the
    25  	// validator update delay, so that e.g. slashing periods are correctly
    26  	// initialized for the validator set e.g. with a one-block offset - the
    27  	// first TM block is at height 1, so state updates applied from
    28  	// genesis.json are in block 0.
    29  	sdkCtx := sdk.UnwrapSDKContext(ctx)
    30  	sdkCtx = sdkCtx.WithBlockHeight(1 - sdk.ValidatorUpdateDelay)
    31  	ctx = sdkCtx
    32  
    33  	if err := k.SetParams(ctx, data.Params); err != nil {
    34  		panic(err)
    35  	}
    36  
    37  	if err := k.SetLastTotalPower(ctx, data.LastTotalPower); err != nil {
    38  		panic(err)
    39  	}
    40  
    41  	for _, validator := range data.Validators {
    42  		if err := k.SetValidator(ctx, validator); err != nil {
    43  			panic(err)
    44  		}
    45  
    46  		// Manually set indices for the first time
    47  		if err := k.SetValidatorByConsAddr(ctx, validator); err != nil {
    48  			panic(err)
    49  		}
    50  
    51  		if err := k.SetValidatorByPowerIndex(ctx, validator); err != nil {
    52  			panic(err)
    53  		}
    54  
    55  		// Call the creation hook if not exported
    56  		if !data.Exported {
    57  			valbz, err := k.ValidatorAddressCodec().StringToBytes(validator.GetOperator())
    58  			if err != nil {
    59  				panic(err)
    60  			}
    61  			if err := k.Hooks().AfterValidatorCreated(ctx, valbz); err != nil {
    62  				panic(err)
    63  			}
    64  		}
    65  
    66  		// update timeslice if necessary
    67  		if validator.IsUnbonding() {
    68  			if err := k.InsertUnbondingValidatorQueue(ctx, validator); err != nil {
    69  				panic(err)
    70  			}
    71  		}
    72  
    73  		switch validator.GetStatus() {
    74  		case types.Bonded:
    75  			bondedTokens = bondedTokens.Add(validator.GetTokens())
    76  
    77  		case types.Unbonding, types.Unbonded:
    78  			notBondedTokens = notBondedTokens.Add(validator.GetTokens())
    79  
    80  		default:
    81  			panic("invalid validator status")
    82  		}
    83  	}
    84  
    85  	for _, delegation := range data.Delegations {
    86  		delegatorAddress, err := k.authKeeper.AddressCodec().StringToBytes(delegation.DelegatorAddress)
    87  		if err != nil {
    88  			panic(fmt.Errorf("invalid delegator address: %s", err))
    89  		}
    90  
    91  		valAddr, err := k.validatorAddressCodec.StringToBytes(delegation.GetValidatorAddr())
    92  		if err != nil {
    93  			panic(err)
    94  		}
    95  
    96  		// Call the before-creation hook if not exported
    97  		if !data.Exported {
    98  			if err := k.Hooks().BeforeDelegationCreated(ctx, delegatorAddress, valAddr); err != nil {
    99  				panic(err)
   100  			}
   101  		}
   102  
   103  		if err := k.SetDelegation(ctx, delegation); err != nil {
   104  			panic(err)
   105  		}
   106  
   107  		// Call the after-modification hook if not exported
   108  		if !data.Exported {
   109  			if err := k.Hooks().AfterDelegationModified(ctx, delegatorAddress, valAddr); err != nil {
   110  				panic(err)
   111  			}
   112  		}
   113  	}
   114  
   115  	for _, ubd := range data.UnbondingDelegations {
   116  		if err := k.SetUnbondingDelegation(ctx, ubd); err != nil {
   117  			panic(err)
   118  		}
   119  
   120  		for _, entry := range ubd.Entries {
   121  			if err := k.InsertUBDQueue(ctx, ubd, entry.CompletionTime); err != nil {
   122  				panic(err)
   123  			}
   124  			notBondedTokens = notBondedTokens.Add(entry.Balance)
   125  		}
   126  	}
   127  
   128  	for _, red := range data.Redelegations {
   129  		if err := k.SetRedelegation(ctx, red); err != nil {
   130  			panic(err)
   131  		}
   132  
   133  		for _, entry := range red.Entries {
   134  			if err := k.InsertRedelegationQueue(ctx, red, entry.CompletionTime); err != nil {
   135  				panic(err)
   136  			}
   137  		}
   138  	}
   139  
   140  	bondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, bondedTokens))
   141  	notBondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, notBondedTokens))
   142  
   143  	// check if the unbonded and bonded pools accounts exists
   144  	bondedPool := k.GetBondedPool(ctx)
   145  	if bondedPool == nil {
   146  		panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName))
   147  	}
   148  
   149  	// TODO: remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862
   150  
   151  	bondedBalance := k.bankKeeper.GetAllBalances(ctx, bondedPool.GetAddress())
   152  	if bondedBalance.IsZero() {
   153  		k.authKeeper.SetModuleAccount(ctx, bondedPool)
   154  	}
   155  
   156  	// if balance is different from bonded coins panic because genesis is most likely malformed
   157  	if !bondedBalance.Equal(bondedCoins) {
   158  		panic(fmt.Sprintf("bonded pool balance is different from bonded coins: %s <-> %s", bondedBalance, bondedCoins))
   159  	}
   160  
   161  	notBondedPool := k.GetNotBondedPool(ctx)
   162  	if notBondedPool == nil {
   163  		panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName))
   164  	}
   165  
   166  	notBondedBalance := k.bankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress())
   167  	if notBondedBalance.IsZero() {
   168  		k.authKeeper.SetModuleAccount(ctx, notBondedPool)
   169  	}
   170  
   171  	// If balance is different from non bonded coins panic because genesis is most
   172  	// likely malformed.
   173  	if !notBondedBalance.Equal(notBondedCoins) {
   174  		panic(fmt.Sprintf("not bonded pool balance is different from not bonded coins: %s <-> %s", notBondedBalance, notBondedCoins))
   175  	}
   176  
   177  	// don't need to run CometBFT updates if we exported
   178  	if data.Exported {
   179  		for _, lv := range data.LastValidatorPowers {
   180  			valAddr, err := k.validatorAddressCodec.StringToBytes(lv.Address)
   181  			if err != nil {
   182  				panic(err)
   183  			}
   184  
   185  			err = k.SetLastValidatorPower(ctx, valAddr, lv.Power)
   186  			if err != nil {
   187  				panic(err)
   188  			}
   189  
   190  			validator, err := k.GetValidator(ctx, valAddr)
   191  			if err != nil {
   192  				panic(fmt.Sprintf("validator %s not found", lv.Address))
   193  			}
   194  
   195  			update := validator.ABCIValidatorUpdate(k.PowerReduction(ctx))
   196  			update.Power = lv.Power // keep the next-val-set offset, use the last power for the first block
   197  			res = append(res, update)
   198  		}
   199  	} else {
   200  		var err error
   201  
   202  		res, err = k.ApplyAndReturnValidatorSetUpdates(ctx)
   203  		if err != nil {
   204  			panic(err)
   205  		}
   206  	}
   207  
   208  	return res
   209  }
   210  
   211  // ExportGenesis returns a GenesisState for a given context and keeper. The
   212  // GenesisState will contain the pool, params, validators, and bonds found in
   213  // the keeper.
   214  func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
   215  	var unbondingDelegations []types.UnbondingDelegation
   216  
   217  	err := k.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
   218  		unbondingDelegations = append(unbondingDelegations, ubd)
   219  		return false
   220  	})
   221  	if err != nil {
   222  		panic(err)
   223  	}
   224  
   225  	var redelegations []types.Redelegation
   226  
   227  	err = k.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) {
   228  		redelegations = append(redelegations, red)
   229  		return false
   230  	})
   231  	if err != nil {
   232  		panic(err)
   233  	}
   234  
   235  	var lastValidatorPowers []types.LastValidatorPower
   236  
   237  	err = k.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) {
   238  		addrStr, err := k.validatorAddressCodec.BytesToString(addr)
   239  		if err != nil {
   240  			panic(err)
   241  		}
   242  		lastValidatorPowers = append(lastValidatorPowers, types.LastValidatorPower{Address: addrStr, Power: power})
   243  		return false
   244  	})
   245  	if err != nil {
   246  		panic(err)
   247  	}
   248  
   249  	params, err := k.GetParams(ctx)
   250  	if err != nil {
   251  		panic(err)
   252  	}
   253  
   254  	totalPower, err := k.GetLastTotalPower(ctx)
   255  	if err != nil {
   256  		panic(err)
   257  	}
   258  
   259  	allDelegations, err := k.GetAllDelegations(ctx)
   260  	if err != nil {
   261  		panic(err)
   262  	}
   263  
   264  	allValidators, err := k.GetAllValidators(ctx)
   265  	if err != nil {
   266  		panic(err)
   267  	}
   268  
   269  	return &types.GenesisState{
   270  		Params:               params,
   271  		LastTotalPower:       totalPower,
   272  		LastValidatorPowers:  lastValidatorPowers,
   273  		Validators:           allValidators,
   274  		Delegations:          allDelegations,
   275  		UnbondingDelegations: unbondingDelegations,
   276  		Redelegations:        redelegations,
   277  		Exported:             true,
   278  	}
   279  }