github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/staking/genesis_test.go (about)

     1  package staking
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/fibonacci-chain/fbc/x/common"
     9  
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply"
    11  
    12  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    13  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
    14  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519"
    15  	"github.com/fibonacci-chain/fbc/x/staking/exported"
    16  	"github.com/fibonacci-chain/fbc/x/staking/types"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  //func tokensFromTendermintPower(power int64) sdk.Int {
    22  //	return sdk.NewInt(power).Mul(sdk.PowerReduction)
    23  //}
    24  
    25  func TestInitGenesis(t *testing.T) {
    26  	ctx, _, mKeeper := CreateTestInput(t, false, 1000)
    27  	keeper := mKeeper.Keeper
    28  	supplyKeeper := mKeeper.SupplyKeeper
    29  	clearNotBondedPool(t, ctx, supplyKeeper)
    30  	valTokens := int64(1)
    31  
    32  	params := keeper.GetParams(ctx)
    33  	validators := make([]Validator, 2)
    34  	// initialize the validators
    35  	validators[0].OperatorAddress = sdk.ValAddress(Addrs[0])
    36  	validators[0].ConsPubKey = PKs[0]
    37  	validators[0].Description = types.NewDescription("hoop", "", "", "")
    38  	validators[0].Status = sdk.Bonded
    39  	validators[0].DelegatorShares = sdk.NewDec(valTokens)
    40  	validators[0].MinSelfDelegation = sdk.OneDec()
    41  	validators[1].OperatorAddress = sdk.ValAddress(Addrs[1])
    42  	validators[1].ConsPubKey = PKs[1]
    43  	validators[1].Description = types.NewDescription("bloop", "", "", "")
    44  	validators[1].Status = sdk.Bonded
    45  	validators[1].DelegatorShares = sdk.NewDec(valTokens)
    46  	validators[1].MinSelfDelegation = sdk.OneDec()
    47  
    48  	delegators := make([]Delegator, 1)
    49  	delegators[0] = types.NewDelegator(Addrs[10])
    50  
    51  	unbondingDelegations := make([]types.UndelegationInfo, 1)
    52  	unbondingDelegations[0] = types.NewUndelegationInfo(Addrs[11], sdk.NewDec(100), time.Now().Add(time.Minute*10))
    53  
    54  	proxysDelegator := make([]ProxyDelegatorKeyExported, 2)
    55  	proxysDelegator[0].DelAddr = Addrs[2]
    56  	proxysDelegator[0].ProxyAddr = Addrs[3]
    57  	proxysDelegator[1].DelAddr = Addrs[4]
    58  	proxysDelegator[1].ProxyAddr = Addrs[5]
    59  
    60  	sharesExportedSlice := make([]types.SharesExported, 2)
    61  	sharesExportedSlice[0] = types.NewSharesExported(Addrs[6], validators[0].OperatorAddress, sdk.NewDec(1))
    62  	sharesExportedSlice[1] = types.NewSharesExported(Addrs[7], validators[1].OperatorAddress, sdk.NewDec(1))
    63  
    64  	genesisState := NewGenesisState(params, validators, delegators)
    65  	genesisState.ProxyDelegatorKeys = proxysDelegator
    66  	genesisState.AllShares = sharesExportedSlice
    67  	genesisState.UnbondingDelegations = unbondingDelegations
    68  	// for the token sum check in staking init-genesis
    69  	//coinsToModuleAcc := sdk.SysCoins{sdk.NewDecCoinFromDec("fibo", sdk.NewDec(100))}.ToCoins()
    70  	coinsToModuleAcc := sdk.NewCoin(common.NativeToken, sdk.NewInt(100)).ToCoins()
    71  	_ = supplyKeeper.SendCoinsFromAccountToModule(ctx, Addrs[11], types.NotBondedPoolName, coinsToModuleAcc)
    72  	vals := InitGenesis(ctx, keeper, nil, supplyKeeper, genesisState)
    73  
    74  	actualGenesis := ExportGenesis(ctx, keeper)
    75  	require.Equal(t, genesisState.Params, actualGenesis.Params)
    76  	require.Equal(t, genesisState.Delegators, actualGenesis.Delegators)
    77  	require.EqualValues(t, keeper.GetAllValidators(ctx).Export(), actualGenesis.Validators)
    78  	require.True(t, actualGenesis.Exported)
    79  	require.Equal(t, genesisState.ProxyDelegatorKeys, actualGenesis.ProxyDelegatorKeys)
    80  
    81  	// now make sure the validators are bonded and intra-tx counters are correct
    82  	resVal, found := keeper.GetValidator(ctx, sdk.ValAddress(Addrs[0]))
    83  	require.True(t, found)
    84  	require.Equal(t, sdk.Bonded, resVal.Status)
    85  
    86  	resVal, found = keeper.GetValidator(ctx, sdk.ValAddress(Addrs[1]))
    87  	require.True(t, found)
    88  	require.Equal(t, sdk.Bonded, resVal.Status)
    89  
    90  	abcivals := make([]abci.ValidatorUpdate, len(vals))
    91  	for i, val := range validators {
    92  		abcivals[i] = val.ABCIValidatorUpdateByShares()
    93  	}
    94  	require.EqualValues(t, abcivals, vals)
    95  
    96  	newCtx, _, newMKeeper := CreateTestInput(t, false, 1000)
    97  	newKeeper := newMKeeper.Keeper
    98  	newSupplyKeeper := newMKeeper.SupplyKeeper
    99  	clearNotBondedPool(t, newCtx, newSupplyKeeper)
   100  	_ = newSupplyKeeper.SendCoinsFromAccountToModule(newCtx, Addrs[11], types.NotBondedPoolName, coinsToModuleAcc)
   101  	InitGenesis(newCtx, newKeeper, nil, newSupplyKeeper, actualGenesis)
   102  	// 0x11
   103  	require.Equal(t, actualGenesis.LastValidatorPowers[0].Power, newKeeper.GetLastValidatorPower(newCtx, actualGenesis.LastValidatorPowers[0].Address))
   104  	require.Equal(t, actualGenesis.LastValidatorPowers[1].Power, newKeeper.GetLastValidatorPower(newCtx, actualGenesis.LastValidatorPowers[1].Address))
   105  	// 0x12
   106  	totalPower := sdk.ZeroInt()
   107  	for _, v := range actualGenesis.LastValidatorPowers {
   108  		totalPower = totalPower.AddRaw(v.Power)
   109  	}
   110  	require.Equal(t, totalPower, newKeeper.GetLastTotalPower(newCtx))
   111  	// 0x21
   112  	resVal, found = newKeeper.GetValidator(newCtx, actualGenesis.Validators[0].OperatorAddress)
   113  	require.True(t, found)
   114  	require.Equal(t, actualGenesis.Validators[0].Import(), resVal)
   115  	resVal, found = newKeeper.GetValidator(newCtx, actualGenesis.Validators[1].OperatorAddress)
   116  	require.True(t, found)
   117  	require.Equal(t, actualGenesis.Validators[1].Import(), resVal)
   118  	// 0x22
   119  	resVal, found = newKeeper.GetValidatorByConsAddr(newCtx,
   120  		sdk.GetConsAddress(types.MustGetConsPubKeyBech32(actualGenesis.Validators[0].ConsPubKey)))
   121  	require.True(t, found)
   122  	require.Equal(t, actualGenesis.Validators[0].Import(), resVal)
   123  	resVal, found = newKeeper.GetValidatorByConsAddr(newCtx,
   124  		sdk.GetConsAddress(types.MustGetConsPubKeyBech32(actualGenesis.Validators[1].ConsPubKey)))
   125  	require.True(t, found)
   126  	require.Equal(t, actualGenesis.Validators[1].Import(), resVal)
   127  	// 0x23
   128  	newKeeper.IterateBondedValidatorsByPower(newCtx, func(index int64, validator exported.ValidatorI) (stop bool) {
   129  		require.Equal(t, actualGenesis.Validators[index].Import(), validator)
   130  		return false
   131  	})
   132  	// 0x51
   133  	require.Equal(t, types.NewSharesResponse(actualGenesis.AllShares[0].DelAddress, actualGenesis.AllShares[0].Shares),
   134  		newKeeper.GetValidatorAllShares(newCtx, actualGenesis.AllShares[0].ValidatorAddress)[0])
   135  	require.Equal(t, types.NewSharesResponse(actualGenesis.AllShares[1].DelAddress, actualGenesis.AllShares[1].Shares),
   136  		newKeeper.GetValidatorAllShares(newCtx, actualGenesis.AllShares[1].ValidatorAddress)[0])
   137  	// 0x52
   138  	delegator, ok := newKeeper.GetDelegator(newCtx, actualGenesis.Delegators[0].DelegatorAddress)
   139  	require.True(t, ok)
   140  	require.Equal(t, actualGenesis.Delegators[0], delegator)
   141  	// 0x53
   142  	unbondingDelegator, ok := newKeeper.GetUndelegating(newCtx, actualGenesis.UnbondingDelegations[0].DelegatorAddress)
   143  	require.True(t, ok)
   144  	require.Equal(t, actualGenesis.UnbondingDelegations[0], unbondingDelegator)
   145  	// 0x54
   146  	newKeeper.IterateKeysBeforeCurrentTime(newCtx, time.Now().Add(time.Hour),
   147  		func(index int64, key []byte) (stop bool) {
   148  			oldTime, delAddr := types.SplitCompleteTimeWithAddrKey(key)
   149  			require.Equal(t, actualGenesis.UnbondingDelegations[index].CompletionTime, oldTime)
   150  			require.Equal(t, actualGenesis.UnbondingDelegations[index].DelegatorAddress, delAddr)
   151  			return false
   152  		})
   153  	// 0x55
   154  	newKeeper.IterateProxy(newCtx, nil, false,
   155  		func(index int64, delAddr, proxyAddr sdk.AccAddress) (stop bool) {
   156  			require.Equal(t, actualGenesis.ProxyDelegatorKeys[index], types.NewProxyDelegatorKeyExported(delAddr, proxyAddr))
   157  			return false
   158  		})
   159  	// 0x60
   160  	// Will never happen in InitGenesis
   161  
   162  	exportGenesis := ExportGenesis(newCtx, newKeeper)
   163  	require.Equal(t, actualGenesis.Params, exportGenesis.Params)
   164  	require.Equal(t, actualGenesis.Delegators, exportGenesis.Delegators)
   165  	require.EqualValues(t, newKeeper.GetAllValidators(newCtx).Export(), exportGenesis.Validators)
   166  	require.True(t, exportGenesis.Exported)
   167  	require.Equal(t, actualGenesis.ProxyDelegatorKeys, exportGenesis.ProxyDelegatorKeys)
   168  
   169  	exportGenesis.Validators[0].UnbondingCompletionTime = time.Now()
   170  	exportGenesis.Validators[0].Status = sdk.Unbonding
   171  	newCtx, _, newMKeeper = CreateTestInput(t, false, 1000)
   172  	newKeeper = newMKeeper.Keeper
   173  	newSupplyKeeper = newMKeeper.SupplyKeeper
   174  	clearNotBondedPool(t, newCtx, newSupplyKeeper)
   175  	_ = newSupplyKeeper.SendCoinsFromAccountToModule(newCtx, Addrs[11], types.NotBondedPoolName, coinsToModuleAcc)
   176  	InitGenesis(newCtx, newKeeper, nil, newSupplyKeeper, exportGenesis)
   177  	// 0x43
   178  	require.Equal(t, []sdk.ValAddress{exportGenesis.Validators[0].OperatorAddress}, newKeeper.GetValidatorQueueTimeSlice(newCtx, exportGenesis.Validators[0].UnbondingCompletionTime))
   179  }
   180  
   181  func clearNotBondedPool(t *testing.T, ctx sdk.Context, supplyKeeper supply.Keeper) {
   182  	notBondedPool := supplyKeeper.GetModuleAccount(ctx, types.NotBondedPoolName)
   183  	zeroCoins := sdk.NewCoins(sdk.NewInt64Coin(common.NativeToken, 0))
   184  	require.NoError(t, notBondedPool.SetCoins(zeroCoins))
   185  	supplyKeeper.SetModuleAccount(ctx, notBondedPool)
   186  }
   187  
   188  func TestInitGenesisLargeValidatorSet(t *testing.T) {
   189  	size := 200
   190  	require.True(t, size > 100)
   191  
   192  	ctx, _, mKeeper := CreateTestInput(t, false, 1000)
   193  	keeper := mKeeper.Keeper
   194  	supplyKeeper := mKeeper.SupplyKeeper
   195  	params := keeper.GetParams(ctx)
   196  	delegators := []Delegator{}
   197  	validators := make([]Validator, size)
   198  
   199  	for i := range validators {
   200  		validators[i] = NewValidator(sdk.ValAddress(Addrs[i]),
   201  			PKs[i], NewDescription(fmt.Sprintf("#%d", i), "", "", ""), types.DefaultMinSelfDelegation)
   202  
   203  		validators[i].Status = sdk.Bonded
   204  
   205  		tokens := int64(1)
   206  		if i < 100 {
   207  			tokens = int64(2)
   208  		}
   209  		//validators[i].Tokens = tokens
   210  		validators[i].DelegatorShares = sdk.NewDec(tokens)
   211  	}
   212  
   213  	genesisState := NewGenesisState(params, validators, delegators)
   214  	vals := InitGenesis(ctx, keeper, nil, supplyKeeper, genesisState)
   215  
   216  	require.EqualValues(t, len(vals), keeper.GetParams(ctx).MaxValidators)
   217  }
   218  
   219  func TestValidateGenesis(t *testing.T) {
   220  	genValidators := make([]Validator, 1, 5)
   221  	pk := ed25519.GenPrivKey().PubKey()
   222  	generatedValDesc := NewDescription("", "", "", "")
   223  	genValidators[0] = NewValidator(sdk.ValAddress(pk.Address()), pk, generatedValDesc, types.DefaultMinSelfDelegation)
   224  	genValidators[0].DelegatorShares = sdk.OneDec()
   225  	genValidatorExported := genValidators[0].Export()
   226  
   227  	tests := []struct {
   228  		name    string
   229  		mutate  func(*GenesisState)
   230  		wantErr bool
   231  	}{
   232  		{"default", func(*GenesisState) {}, false},
   233  		// validate genesis validators
   234  		{"duplicate validator", func(data *types.GenesisState) {
   235  			(*data).Validators = []ValidatorExport{genValidatorExported, genValidatorExported}
   236  		}, true},
   237  		{"no delegator shares", func(data *types.GenesisState) {
   238  			(*data).Validators = []ValidatorExport{genValidatorExported}
   239  			(*data).Validators[0].DelegatorShares = sdk.ZeroDec()
   240  		}, true},
   241  		{"jailed and bonded validator", func(data *types.GenesisState) {
   242  			(*data).Validators = []ValidatorExport{genValidatorExported}
   243  			(*data).Validators[0].Jailed = true
   244  			(*data).Validators[0].Status = sdk.Bonded
   245  		}, true},
   246  	}
   247  
   248  	for _, tt := range tests {
   249  		t.Run(tt.name, func(t *testing.T) {
   250  			genesisState := types.DefaultGenesisState()
   251  			tt.mutate(&genesisState)
   252  			if tt.wantErr {
   253  				assert.Error(t, ValidateGenesis(genesisState))
   254  			} else {
   255  				assert.NoError(t, ValidateGenesis(genesisState))
   256  			}
   257  		})
   258  	}
   259  }