github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/staking/genesis.go (about)

     1  package staking
     2  
     3  import (
     4  	"fmt"
     5  
     6  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
     7  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types"
     8  
     9  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking/exported"
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking/types"
    12  )
    13  
    14  // InitGenesis sets the pool and parameters for the provided keeper.  For each
    15  // validator in data, it sets that validator in the keeper along with manually
    16  // setting the indexes. In addition, it also sets any delegations found in
    17  // data. 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  
    22  	bondedTokens := sdk.ZeroInt()
    23  	notBondedTokens := sdk.ZeroInt()
    24  
    25  	// We need to pretend to be "n blocks before genesis", where "n" is the
    26  	// validator update delay, so that e.g. slashing periods are correctly
    27  	// initialized for the validator set e.g. with a one-block offset - the
    28  	// first TM block is at height 1, so state updates applied from
    29  	// genesis.json are in block 0.
    30  	ctx.SetBlockHeight(1 - sdk.ValidatorUpdateDelay)
    31  
    32  	keeper.SetParams(ctx, data.Params)
    33  	keeper.SetLastTotalPower(ctx, data.LastTotalPower)
    34  
    35  	for _, validator := range data.Validators {
    36  		keeper.SetValidator(ctx, validator)
    37  
    38  		// Manually set indices for the first time
    39  		keeper.SetValidatorByConsAddr(ctx, validator)
    40  		keeper.SetValidatorByPowerIndex(ctx, validator)
    41  
    42  		// Call the creation hook if not exported
    43  		if !data.Exported {
    44  			keeper.AfterValidatorCreated(ctx, validator.OperatorAddress)
    45  		}
    46  
    47  		// update timeslice if necessary
    48  		if validator.IsUnbonding() {
    49  			keeper.InsertValidatorQueue(ctx, validator)
    50  		}
    51  
    52  		switch validator.GetStatus() {
    53  		case sdk.Bonded:
    54  			bondedTokens = bondedTokens.Add(validator.GetTokens())
    55  		case sdk.Unbonding, sdk.Unbonded:
    56  			notBondedTokens = notBondedTokens.Add(validator.GetTokens())
    57  		default:
    58  			panic("invalid validator status")
    59  		}
    60  	}
    61  
    62  	for _, delegation := range data.Delegations {
    63  		// Call the before-creation hook if not exported
    64  		if !data.Exported {
    65  			keeper.BeforeDelegationCreated(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress)
    66  		}
    67  		keeper.SetDelegation(ctx, delegation)
    68  
    69  		// Call the after-modification hook if not exported
    70  		if !data.Exported {
    71  			keeper.AfterDelegationModified(ctx, delegation.DelegatorAddress, delegation.ValidatorAddress)
    72  		}
    73  	}
    74  
    75  	for _, ubd := range data.UnbondingDelegations {
    76  		keeper.SetUnbondingDelegation(ctx, ubd)
    77  		for _, entry := range ubd.Entries {
    78  			keeper.InsertUBDQueue(ctx, ubd, entry.CompletionTime)
    79  			notBondedTokens = notBondedTokens.Add(entry.Balance)
    80  		}
    81  	}
    82  
    83  	for _, red := range data.Redelegations {
    84  		keeper.SetRedelegation(ctx, red)
    85  		for _, entry := range red.Entries {
    86  			keeper.InsertRedelegationQueue(ctx, red, entry.CompletionTime)
    87  		}
    88  	}
    89  
    90  	bondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, bondedTokens))
    91  	notBondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, notBondedTokens))
    92  
    93  	// check if the unbonded and bonded pools accounts exists
    94  	bondedPool := keeper.GetBondedPool(ctx)
    95  	if bondedPool == nil {
    96  		panic(fmt.Sprintf("%s module account has not been set", types.BondedPoolName))
    97  	}
    98  
    99  	// TODO remove with genesis 2-phases refactor https://github.com/cosmos/cosmos-sdk/issues/2862
   100  	// add coins if not provided on genesis
   101  	if bondedPool.GetCoins().IsZero() {
   102  		if err := bondedPool.SetCoins(bondedCoins); err != nil {
   103  			panic(err)
   104  		}
   105  		supplyKeeper.SetModuleAccount(ctx, bondedPool)
   106  	}
   107  
   108  	notBondedPool := keeper.GetNotBondedPool(ctx)
   109  	if notBondedPool == nil {
   110  		panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName))
   111  	}
   112  
   113  	if notBondedPool.GetCoins().IsZero() {
   114  		if err := notBondedPool.SetCoins(notBondedCoins); err != nil {
   115  			panic(err)
   116  		}
   117  		supplyKeeper.SetModuleAccount(ctx, notBondedPool)
   118  	}
   119  
   120  	// don't need to run Tendermint updates if we exported
   121  	if data.Exported {
   122  		for _, lv := range data.LastValidatorPowers {
   123  			keeper.SetLastValidatorPower(ctx, lv.Address, lv.Power)
   124  			validator, found := keeper.GetValidator(ctx, lv.Address)
   125  			if !found {
   126  				panic(fmt.Sprintf("validator %s not found", lv.Address))
   127  			}
   128  			update := validator.ABCIValidatorUpdate()
   129  			update.Power = lv.Power // keep the next-val-set offset, use the last power for the first block
   130  			res = append(res, update)
   131  		}
   132  	} else {
   133  		res = keeper.ApplyAndReturnValidatorSetUpdates(ctx)
   134  	}
   135  
   136  	return res
   137  }
   138  
   139  // ExportGenesis returns a GenesisState for a given context and keeper. The
   140  // GenesisState will contain the pool, params, validators, and bonds found in
   141  // the keeper.
   142  func ExportGenesis(ctx sdk.Context, keeper Keeper) types.GenesisState {
   143  	params := keeper.GetParams(ctx)
   144  	lastTotalPower := keeper.GetLastTotalPower(ctx)
   145  	validators := keeper.GetAllValidators(ctx)
   146  	delegations := keeper.GetAllDelegations(ctx)
   147  	var unbondingDelegations []types.UnbondingDelegation
   148  	keeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd types.UnbondingDelegation) (stop bool) {
   149  		unbondingDelegations = append(unbondingDelegations, ubd)
   150  		return false
   151  	})
   152  	var redelegations []types.Redelegation
   153  	keeper.IterateRedelegations(ctx, func(_ int64, red types.Redelegation) (stop bool) {
   154  		redelegations = append(redelegations, red)
   155  		return false
   156  	})
   157  	var lastValidatorPowers []types.LastValidatorPower
   158  	keeper.IterateLastValidatorPowers(ctx, func(addr sdk.ValAddress, power int64) (stop bool) {
   159  		lastValidatorPowers = append(lastValidatorPowers, types.LastValidatorPower{Address: addr, Power: power})
   160  		return false
   161  	})
   162  
   163  	return types.GenesisState{
   164  		Params:               params,
   165  		LastTotalPower:       lastTotalPower,
   166  		LastValidatorPowers:  lastValidatorPowers,
   167  		Validators:           validators,
   168  		Delegations:          delegations,
   169  		UnbondingDelegations: unbondingDelegations,
   170  		Redelegations:        redelegations,
   171  		Exported:             true,
   172  	}
   173  }
   174  
   175  // WriteValidators returns a slice of bonded genesis validators.
   176  func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisValidator) {
   177  	keeper.IterateLastValidators(ctx, func(_ int64, validator exported.ValidatorI) (stop bool) {
   178  		vals = append(vals, tmtypes.GenesisValidator{
   179  			PubKey: validator.GetConsPubKey(),
   180  			Power:  validator.GetConsensusPower(),
   181  			Name:   validator.GetMoniker(),
   182  		})
   183  
   184  		return false
   185  	})
   186  
   187  	return
   188  }
   189  
   190  // ValidateGenesis validates the provided staking genesis state to ensure the
   191  // expected invariants holds. (i.e. params in correct bounds, no duplicate validators)
   192  func ValidateGenesis(data types.GenesisState) error {
   193  	err := validateGenesisStateValidators(data.Validators)
   194  	if err != nil {
   195  		return err
   196  	}
   197  	err = data.Params.Validate()
   198  	if err != nil {
   199  		return err
   200  	}
   201  
   202  	return nil
   203  }
   204  
   205  func validateGenesisStateValidators(validators []types.Validator) (err error) {
   206  	addrMap := make(map[string]bool, len(validators))
   207  	for i := 0; i < len(validators); i++ {
   208  		val := validators[i]
   209  		strKey := string(val.ConsPubKey.Bytes())
   210  		if _, ok := addrMap[strKey]; ok {
   211  			return fmt.Errorf("duplicate validator in genesis state: moniker %v, address %v", val.Description.Moniker, val.ConsAddress())
   212  		}
   213  		if val.Jailed && val.IsBonded() {
   214  			return fmt.Errorf("validator is bonded and jailed in genesis state: moniker %v, address %v", val.Description.Moniker, val.ConsAddress())
   215  		}
   216  		if val.DelegatorShares.IsZero() && !val.IsUnbonding() {
   217  			return fmt.Errorf("bonded/unbonded genesis validator cannot have zero delegator shares, validator: %v", val)
   218  		}
   219  		addrMap[strKey] = true
   220  	}
   221  	return
   222  }