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

     1  package staking
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/fibonacci-chain/fbc/x/staking/types"
     8  
     9  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    10  )
    11  
    12  func TestValidatorSMCreateValidator(t *testing.T) {
    13  
    14  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
    15  
    16  	params := DefaultParams()
    17  	params.MaxValidators = 1
    18  
    19  	startUpValidator := NewValidator(addrVals[0], PKs[0], Description{}, types.DefaultMinSelfDelegation)
    20  	expectDelegatorShares := SharesFromDefaultMSD
    21  
    22  	startUpStatus := baseValidatorStatus{startUpValidator}
    23  
    24  	bAction := baseAction{mk}
    25  	inputActions := []IAction{
    26  		createValidatorAction{bAction, nil},
    27  		endBlockAction{bAction},
    28  		endBlockAction{bAction},
    29  	}
    30  
    31  	actionsAndChecker := []actResChecker{
    32  		validatorStatusChecker(sdk.Unbonded.String()),
    33  		queryValidatorCheck(sdk.Bonded, false, &expectDelegatorShares, &DefaultMSD, nil),
    34  		getLatestGenesisValidatorCheck(1),
    35  	}
    36  
    37  	smTestCase := basicStakingSMTestCase{
    38  		mk,
    39  		params,
    40  		startUpStatus,
    41  		inputActions,
    42  		actionsAndChecker,
    43  		0,
    44  		nil,
    45  		nil,
    46  		t,
    47  	}
    48  
    49  	smTestCase.Run(t)
    50  }
    51  
    52  func TestValidatorSMCreateValidatorWithValidatorSet(t *testing.T) {
    53  
    54  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
    55  
    56  	params := DefaultParams()
    57  	params.MaxValidators = uint16(len(addrVals)) - 1
    58  	params.Epoch = 3
    59  	params.UnbondingTime = time.Millisecond * 300
    60  
    61  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
    62  
    63  	startUpStatus := baseValidatorStatus{startUpValidator}
    64  
    65  	bAction := baseAction{mk}
    66  	inputActions := []IAction{
    67  		createValidatorAction{bAction, nil},
    68  		delegatorsAddSharesAction{bAction, false, true, 0, []sdk.AccAddress{ValidDelegator1}},
    69  		endBlockAction{bAction},
    70  		endBlockAction{bAction},
    71  		endBlockAction{bAction},
    72  	}
    73  
    74  	actionsAndChecker := []actResChecker{
    75  		validatorStatusChecker(sdk.Unbonded.String()),
    76  		queryValidatorCheck(sdk.Unbonded, false, nil, nil, nil),
    77  		validatorStatusChecker(sdk.Unbonded.String()),
    78  		validatorStatusChecker(sdk.Unbonded.String()),
    79  		validatorStatusChecker(sdk.Bonded.String()),
    80  	}
    81  
    82  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
    83  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
    84  	smTestCase.Run(t)
    85  }
    86  
    87  func TestValidatorSMNormalFullLifeCircle(t *testing.T) {
    88  
    89  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
    90  
    91  	params := DefaultParams()
    92  	params.MaxValidators = uint16(len(addrVals)) - 1
    93  	params.Epoch = 2
    94  	params.UnbondingTime = time.Millisecond * 300
    95  
    96  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
    97  
    98  	startUpStatus := baseValidatorStatus{startUpValidator}
    99  
   100  	bAction := baseAction{mk}
   101  	inputActions := []IAction{
   102  		createValidatorAction{bAction, nil},
   103  		// ensure the validator in the val set
   104  		delegatorsAddSharesAction{bAction, false, true, 0, []sdk.AccAddress{ValidDelegator1}},
   105  		endBlockAction{bAction},
   106  		endBlockAction{bAction},
   107  
   108  		destroyValidatorAction{bAction},
   109  
   110  		endBlockAction{bAction},
   111  		// clear the shares on the startUpValidator
   112  		delegatorWithdrawAction{bAction, ValidDelegator1, DelegatedToken1, sdk.DefaultBondDenom},
   113  		endBlockAction{bAction},
   114  		waitUntilUnbondingTimeExpired{bAction},
   115  		endBlockAction{bAction},
   116  	}
   117  
   118  	destroyChecker := andChecker{[]actResChecker{
   119  		validatorDelegatorShareLeft(true),
   120  		validatorKickedOff(true),
   121  		validatorStatusChecker(sdk.Bonded.String()),
   122  		queryValidatorCheck(sdk.Bonded, true, nil, nil, nil),
   123  	}}
   124  
   125  	actionsAndChecker := []actResChecker{
   126  		validatorStatusChecker(sdk.Unbonded.String()),
   127  		validatorDelegatorShareIncreased(true),
   128  		validatorStatusChecker(sdk.Unbonded.String()),
   129  		validatorStatusChecker(sdk.Bonded.String()),
   130  
   131  		// destroyValidatorAction checker
   132  		destroyChecker.GetChecker(),
   133  
   134  		validatorStatusChecker(sdk.Unbonding.String()),
   135  		validatorDelegatorShareLeft(false),
   136  		validatorStatusChecker(sdk.Unbonding.String()),
   137  		queryValidatorCheck(sdk.Unbonding, true, nil, nil, nil),
   138  		validatorRemoved(true),
   139  	}
   140  
   141  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   142  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   143  	smTestCase.Run(t)
   144  
   145  }
   146  
   147  func TestValidatorSMEvilFullLifeCircle(t *testing.T) {
   148  
   149  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
   150  
   151  	params := DefaultParams()
   152  	params.MaxValidators = uint16(len(addrVals)) - 1
   153  	params.Epoch = 2
   154  	params.UnbondingTime = time.Millisecond * 300
   155  
   156  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   157  
   158  	startUpStatus := baseValidatorStatus{startUpValidator}
   159  
   160  	bAction := baseAction{mk}
   161  	inputActions := []IAction{
   162  		createValidatorAction{bAction, nil},
   163  		delegatorsAddSharesAction{bAction, true, false, 0, []sdk.AccAddress{ValidDelegator1}},
   164  		endBlockAction{bAction},
   165  		delegatorsAddSharesAction{bAction, false, true, 0, []sdk.AccAddress{ValidDelegator2}},
   166  		endBlockAction{bAction},
   167  		jailValidatorAction{bAction},
   168  		endBlockAction{bAction},
   169  		endBlockAction{bAction},
   170  		waitUntilUnbondingTimeExpired{bAction},
   171  		endBlockAction{bAction},
   172  	}
   173  
   174  	jailedChecker := andChecker{[]actResChecker{
   175  		validatorDelegatorShareLeft(true),
   176  		validatorKickedOff(true),
   177  		validatorStatusChecker(sdk.Bonded.String()),
   178  		queryValidatorCheck(sdk.Bonded, true, nil, nil, nil),
   179  	}}
   180  
   181  	actionsAndChecker := []actResChecker{
   182  		validatorStatusChecker(sdk.Unbonded.String()),
   183  		validatorDelegatorShareIncreased(false),
   184  		validatorStatusChecker(sdk.Unbonded.String()),
   185  		validatorDelegatorShareIncreased(true),
   186  		validatorStatusChecker(sdk.Bonded.String()),
   187  		jailedChecker.GetChecker(),
   188  		validatorStatusChecker(sdk.Unbonding.String()),
   189  		validatorStatusChecker(sdk.Unbonding.String()),
   190  		validatorStatusChecker(sdk.Unbonding.String()),
   191  		queryValidatorCheck(sdk.Unbonded, true, nil, nil, nil),
   192  	}
   193  
   194  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   195  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   196  	smTestCase.Run(t)
   197  }
   198  
   199  func TestValidatorSMEvilFullLifeCircleWithUnjail(t *testing.T) {
   200  
   201  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
   202  
   203  	params := DefaultParams()
   204  	params.MaxValidators = uint16(len(addrVals)) - 1
   205  	params.Epoch = 2
   206  	params.UnbondingTime = time.Millisecond * 300
   207  
   208  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   209  
   210  	startUpStatus := baseValidatorStatus{startUpValidator}
   211  
   212  	bAction := baseAction{mk}
   213  	inputActions := []IAction{
   214  		createValidatorAction{bAction, nil},
   215  		delegatorsAddSharesAction{bAction, true, false, 0, []sdk.AccAddress{ValidDelegator1}},
   216  		endBlockAction{bAction},
   217  		delegatorsAddSharesAction{bAction, false, true, 0, []sdk.AccAddress{ValidDelegator2}},
   218  		endBlockAction{bAction},
   219  		jailValidatorAction{bAction},
   220  		endBlockAction{bAction},
   221  		endBlockAction{bAction},
   222  		unJailValidatorAction{bAction},
   223  		endBlockAction{bAction},
   224  		waitUntilUnbondingTimeExpired{bAction},
   225  		endBlockAction{bAction},
   226  	}
   227  
   228  	jailedChecker := andChecker{[]actResChecker{
   229  		validatorDelegatorShareLeft(true),
   230  		validatorKickedOff(true),
   231  		validatorStatusChecker(sdk.Bonded.String()),
   232  		queryDelegatorCheck(ValidDelegator1, true, nil, nil, nil, nil),
   233  		queryDelegatorCheck(ValidDelegator2, true, nil, nil, nil, nil),
   234  		queryValidatorCheck(sdk.Bonded, true, nil, nil, nil),
   235  	}}
   236  
   237  	unJailedChecker := andChecker{[]actResChecker{
   238  		validatorDelegatorShareLeft(true),
   239  		validatorKickedOff(false),
   240  		validatorStatusChecker(sdk.Unbonding.String()),
   241  		queryDelegatorCheck(ValidDelegator1, true, nil, nil, nil, nil),
   242  		queryDelegatorCheck(ValidDelegator2, true, nil, nil, nil, nil),
   243  		queryValidatorCheck(sdk.Unbonding, false, nil, nil, nil),
   244  	}}
   245  
   246  	actionsAndChecker := []actResChecker{
   247  		validatorStatusChecker(sdk.Unbonded.String()),
   248  		validatorDelegatorShareIncreased(false),
   249  		validatorStatusChecker(sdk.Unbonded.String()),
   250  		validatorDelegatorShareIncreased(true),
   251  		validatorStatusChecker(sdk.Bonded.String()),
   252  		jailedChecker.GetChecker(),
   253  		validatorStatusChecker(sdk.Unbonding.String()),
   254  		validatorStatusChecker(sdk.Unbonding.String()),
   255  		unJailedChecker.GetChecker(),
   256  		validatorStatusChecker(sdk.Unbonding.String()),
   257  		validatorStatusChecker(sdk.Unbonding.String()),
   258  		queryValidatorCheck(sdk.Bonded, false, nil, nil, nil),
   259  	}
   260  
   261  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   262  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   263  	smTestCase.Run(t)
   264  }
   265  
   266  func TestValidatorSMEvilFullLifeCircleWithUnjail2(t *testing.T) {
   267  
   268  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
   269  
   270  	params := DefaultParams()
   271  	params.MaxValidators = uint16(len(addrVals)) - 1
   272  	params.Epoch = 2
   273  	params.UnbondingTime = time.Millisecond * 300
   274  
   275  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   276  
   277  	startUpStatus := baseValidatorStatus{startUpValidator}
   278  
   279  	bAction := baseAction{mk}
   280  	inputActions := []IAction{
   281  		createValidatorAction{bAction, nil},
   282  		delegatorsAddSharesAction{bAction, true, false, 0, []sdk.AccAddress{ValidDelegator1}},
   283  		endBlockAction{bAction},
   284  		delegatorsAddSharesAction{bAction, false, true, 0, []sdk.AccAddress{ValidDelegator2}},
   285  		endBlockAction{bAction},
   286  		jailValidatorAction{bAction},
   287  		endBlockAction{bAction},
   288  		endBlockAction{bAction},
   289  		waitUntilUnbondingTimeExpired{bAction},
   290  		endBlockAction{bAction},
   291  		unJailValidatorAction{bAction},
   292  		endBlockAction{bAction},
   293  	}
   294  
   295  	jailedChecker := andChecker{[]actResChecker{
   296  		validatorDelegatorShareLeft(true),
   297  		validatorKickedOff(true),
   298  		validatorStatusChecker(sdk.Bonded.String()),
   299  	}}
   300  
   301  	actionsAndChecker := []actResChecker{
   302  		validatorStatusChecker(sdk.Unbonded.String()),
   303  		validatorDelegatorShareIncreased(false),
   304  		validatorStatusChecker(sdk.Unbonded.String()),
   305  		validatorDelegatorShareIncreased(true),
   306  		validatorStatusChecker(sdk.Bonded.String()),
   307  		jailedChecker.GetChecker(),
   308  		validatorStatusChecker(sdk.Unbonding.String()),
   309  		validatorStatusChecker(sdk.Unbonding.String()),
   310  		validatorStatusChecker(sdk.Unbonding.String()),
   311  		validatorStatusChecker(sdk.Unbonded.String()),
   312  		validatorKickedOff(false),
   313  		queryValidatorCheck(sdk.Bonded, false, nil, nil, nil),
   314  	}
   315  
   316  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   317  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   318  	smTestCase.Run(t)
   319  }
   320  
   321  func TestValidatorSMEpochRotate(t *testing.T) {
   322  
   323  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
   324  
   325  	params := DefaultParams()
   326  	params.MaxValidators = 1
   327  	params.Epoch = 2
   328  	params.UnbondingTime = time.Millisecond * 300
   329  
   330  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   331  
   332  	startUpStatus := baseValidatorStatus{startUpValidator}
   333  
   334  	bAction := baseAction{mk}
   335  	inputActions := []IAction{
   336  		createValidatorAction{bAction, nil},
   337  		delegatorsAddSharesAction{bAction, false, true, 0, []sdk.AccAddress{ValidDelegator1}},
   338  		endBlockAction{bAction},
   339  		endBlockAction{bAction},
   340  		otherMostPowerfulValidatorEnter{bAction},
   341  		endBlockAction{bAction},
   342  		endBlockAction{bAction},
   343  	}
   344  
   345  	actionsAndChecker := []actResChecker{
   346  		// startUpValidator created
   347  		validatorStatusChecker(sdk.Unbonded.String()),
   348  		validatorDelegatorShareIncreased(true),
   349  		validatorStatusChecker(sdk.Unbonded.String()),
   350  		validatorStatusChecker(sdk.Bonded.String()),
   351  
   352  		// more powerful validator enter
   353  		validatorStatusChecker(sdk.Bonded.String()),
   354  		validatorStatusChecker(sdk.Bonded.String()),
   355  
   356  		// entering a new epoch
   357  		// startUpValidator fail to keep validator's position
   358  		validatorStatusChecker(sdk.Unbonding.String()),
   359  	}
   360  
   361  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   362  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   363  	smTestCase.Run(t)
   364  
   365  }
   366  
   367  func TestValidatorSMReRankPowerIndex(t *testing.T) {
   368  
   369  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
   370  
   371  	params := DefaultParams()
   372  	params.MaxValidators = uint16(len(addrVals)) - 1
   373  	params.Epoch = 2
   374  	params.UnbondingTime = time.Millisecond * 300
   375  
   376  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   377  
   378  	startUpStatus := baseValidatorStatus{startUpValidator}
   379  
   380  	bAction := baseAction{mk}
   381  
   382  	addSharesChecker := andChecker{[]actResChecker{
   383  		validatorDelegatorShareIncreased(true),
   384  		validatorStatusChecker(sdk.Unbonded.String()),
   385  		queryDelegatorCheck(ValidDelegator1, true, nil, nil, nil, nil),
   386  		queryDelegatorCheck(ValidDelegator2, true, nil, nil, nil, nil),
   387  		queryValidatorCheck(sdk.Unbonded, false, nil, nil, nil),
   388  	}}
   389  
   390  	withdrawChecker1 := andChecker{[]actResChecker{
   391  		validatorDelegatorShareIncreased(false),
   392  		queryValidatorCheck(sdk.Bonded, false, nil, nil, nil),
   393  		queryDelegatorCheck(ValidDelegator1, true, nil, nil, nil, nil),
   394  		queryDelegatorCheck(ValidDelegator2, false, nil, nil, nil, nil),
   395  	}}
   396  
   397  	withdrawChecker2 := andChecker{[]actResChecker{
   398  		validatorDelegatorShareIncreased(false),
   399  		queryValidatorCheck(sdk.Bonded, false, nil, nil, nil),
   400  		queryDelegatorCheck(ValidDelegator2, false, nil, nil, nil, nil),
   401  	}}
   402  
   403  	inputActions := []IAction{
   404  		createValidatorAction{bAction, nil},
   405  		endBlockAction{bAction},
   406  		delegatorsAddSharesAction{bAction, true, false, 0, []sdk.AccAddress{ValidDelegator1}},
   407  		endBlockAction{bAction},
   408  		delegatorsAddSharesAction{bAction, false, true, 0, []sdk.AccAddress{ValidDelegator2}},
   409  		endBlockAction{bAction},
   410  		endBlockAction{bAction},
   411  		delegatorWithdrawAction{bAction, ValidDelegator2, DelegatedToken2, sdk.DefaultBondDenom},
   412  		delegatorWithdrawAction{bAction, ValidDelegator2, DelegatedToken2, sdk.DefaultBondDenom},
   413  		endBlockAction{bAction},
   414  		endBlockAction{bAction},
   415  		waitUntilUnbondingTimeExpired{bAction},
   416  		endBlockAction{bAction},
   417  	}
   418  
   419  	actionsAndChecker := []actResChecker{
   420  		validatorStatusChecker(sdk.Unbonded.String()),
   421  		validatorStatusChecker(sdk.Unbonded.String()),
   422  		validatorDelegatorShareIncreased(false),
   423  		validatorStatusChecker(sdk.Unbonded.String()),
   424  		addSharesChecker.GetChecker(),
   425  		validatorStatusChecker(sdk.Unbonded.String()),
   426  		validatorStatusChecker(sdk.Bonded.String()),
   427  		withdrawChecker1.GetChecker(),
   428  		withdrawChecker2.GetChecker(),
   429  		validatorStatusChecker(sdk.Bonded.String()),
   430  		validatorStatusChecker(sdk.Unbonding.String()),
   431  		validatorStatusChecker(sdk.Unbonding.String()),
   432  		validatorStatusChecker(sdk.Unbonded.String()),
   433  	}
   434  
   435  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   436  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   437  	smTestCase.Run(t)
   438  
   439  }
   440  
   441  // the following case should be designed again carefully, focus on:
   442  // 0. multi-voting (5 validators & 2delegator)
   443  // 1. validator msd, delegatorshares, add shares
   444  // 2. check delegator's token, unbonded token, shares
   445  func TestValidatorSMMultiVoting(t *testing.T) {
   446  
   447  	ctx, _, mk := CreateTestInput(t, false, SufficientInitPower)
   448  	clearNotBondedPool(t, ctx, mk.SupplyKeeper)
   449  
   450  	params := DefaultParams()
   451  
   452  	originVaSet := addrVals[1:]
   453  	params.MaxValidators = uint16(len(originVaSet))
   454  	params.Epoch = 2
   455  	params.UnbondingTime = time.Millisecond * 300
   456  
   457  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   458  
   459  	startUpStatus := baseValidatorStatus{startUpValidator}
   460  
   461  	bAction := baseAction{mk}
   462  
   463  	orgValsLen := len(originVaSet)
   464  	fullVaSet := make([]sdk.ValAddress, orgValsLen+1)
   465  	copy(fullVaSet, originVaSet)
   466  	copy(fullVaSet[orgValsLen:], []sdk.ValAddress{startUpStatus.getValidator().GetOperator()})
   467  
   468  	expZeroDec := sdk.ZeroDec()
   469  	expValsBondedToken := DefaultMSD.MulInt64(int64(len(fullVaSet)))
   470  	expDlgGrpBondedToken := DelegatedToken1.Add(DelegatedToken2)
   471  	expAllBondedToken := expValsBondedToken.Add(expDlgGrpBondedToken)
   472  	startUpCheck := andChecker{[]actResChecker{
   473  		queryPoolCheck(&expAllBondedToken, &expZeroDec),
   474  		noErrorInHandlerResult(true),
   475  	}}
   476  
   477  	// after delegator in group finish adding shares, do following check
   478  	addSharesChecker := andChecker{[]actResChecker{
   479  		validatorDelegatorShareIncreased(true),
   480  		validatorStatusChecker(sdk.Unbonded.String()),
   481  		queryDelegatorCheck(ValidDelegator2, true, fullVaSet, nil, &DelegatedToken2, &expZeroDec),
   482  		queryAllValidatorCheck([]sdk.BondStatus{sdk.Unbonded, sdk.Bonded, sdk.Unbonding}, []int{1, 4, 0}),
   483  		querySharesToCheck(startUpStatus.getValidator().OperatorAddress, 1, []sdk.AccAddress{ValidDelegator2}),
   484  		queryPoolCheck(&expAllBondedToken, &expZeroDec),
   485  		noErrorInHandlerResult(true),
   486  	}}
   487  
   488  	// All Deleagtor Unbond half of the delegation
   489  	expDlgBondedTokens1 := DelegatedToken1.QuoInt64(2)
   490  	expDlgUnbondedToken1 := expDlgBondedTokens1
   491  	expDlgBondedTokens2 := DelegatedToken2.QuoInt64(2)
   492  	expDlgUnbondedToken2 := expDlgBondedTokens2
   493  	expAllUnBondedToken1 := expDlgUnbondedToken1.Add(expDlgUnbondedToken2)
   494  	expAllBondedToken1 := DefaultMSD.MulInt64(int64(len(fullVaSet))).Add(expDlgBondedTokens1).Add(expDlgBondedTokens2)
   495  	withdrawChecker1 := andChecker{[]actResChecker{
   496  		validatorDelegatorShareIncreased(false),
   497  		validatorStatusChecker(sdk.Unbonded.String()),
   498  		queryDelegatorCheck(ValidDelegator1, true, originVaSet, nil, &expDlgBondedTokens1, &expDlgUnbondedToken1),
   499  		queryDelegatorCheck(ValidDelegator2, true, fullVaSet, nil, &expDlgBondedTokens2, &expDlgUnbondedToken2),
   500  		queryAllValidatorCheck([]sdk.BondStatus{sdk.Unbonded, sdk.Bonded, sdk.Unbonding}, []int{1, 4, 0}),
   501  		querySharesToCheck(startUpStatus.getValidator().OperatorAddress, 1, []sdk.AccAddress{ValidDelegator2}),
   502  		queryPoolCheck(&expAllBondedToken1, &expAllUnBondedToken1),
   503  		queryValidatorCheck(sdk.Unbonded, false, nil, nil, nil),
   504  	}}
   505  
   506  	// All Deleagtor Unbond the delegation left
   507  	expDlgGrpUnbonded2 := expZeroDec
   508  	expAllBondedToken2 := DefaultMSD.MulInt64(int64(len(fullVaSet)))
   509  	withdrawChecker2 := andChecker{[]actResChecker{
   510  		// cannot find unbonding token in GetUnbonding info
   511  		queryDelegatorCheck(ValidDelegator1, false, []sdk.ValAddress{}, nil, &expZeroDec, nil),
   512  		queryDelegatorCheck(ValidDelegator2, false, []sdk.ValAddress{}, nil, &expZeroDec, nil),
   513  		queryAllValidatorCheck([]sdk.BondStatus{sdk.Unbonded, sdk.Bonded, sdk.Unbonding}, []int{1, 4, 0}),
   514  		querySharesToCheck(startUpStatus.getValidator().OperatorAddress, 0, []sdk.AccAddress{}),
   515  		queryPoolCheck(&expAllBondedToken2, &expDlgGrpUnbonded2),
   516  		queryValidatorCheck(sdk.Unbonded, false, nil, nil, nil),
   517  	}}
   518  
   519  	inputActions := []IAction{
   520  		createValidatorAction{bAction, nil},
   521  		endBlockAction{bAction},
   522  		delegatorsAddSharesAction{bAction, true, false, 0, []sdk.AccAddress{ValidDelegator1}},
   523  		endBlockAction{bAction},
   524  		delegatorsAddSharesAction{bAction, true, true, 0, []sdk.AccAddress{ValidDelegator2}},
   525  		endBlockAction{bAction},
   526  		endBlockAction{bAction},
   527  		delegatorsWithdrawAction{bAction, true, false},
   528  		endBlockAction{bAction},
   529  		endBlockAction{bAction},
   530  		delegatorsWithdrawAction{bAction, true, true},
   531  		waitUntilUnbondingTimeExpired{bAction},
   532  		endBlockAction{bAction},
   533  	}
   534  
   535  	actionsAndChecker := []actResChecker{
   536  		startUpCheck.GetChecker(),
   537  		validatorStatusChecker(sdk.Unbonded.String()),
   538  		validatorDelegatorShareIncreased(false),
   539  		validatorStatusChecker(sdk.Unbonded.String()),
   540  		addSharesChecker.GetChecker(),
   541  		validatorStatusChecker(sdk.Unbonded.String()),
   542  		validatorStatusChecker(sdk.Unbonded.String()),
   543  		nil,
   544  		withdrawChecker1.GetChecker(),
   545  		validatorStatusChecker(sdk.Unbonded.String()),
   546  		validatorStatusChecker(sdk.Unbonded.String()),
   547  		nil,
   548  		withdrawChecker2.GetChecker(),
   549  	}
   550  
   551  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   552  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   553  	smTestCase.printParticipantSnapshot(t)
   554  	smTestCase.Run(t)
   555  
   556  }
   557  
   558  // 1. apply DestroyValidator action on a Bonded VA x
   559  // 2. Wait for an Unbonded VA x
   560  // 3. Then delegator unbond all tokens to withdraw shares from VA x
   561  // 4. VA is removed
   562  func TestValidatorSMDestroyValidatorUnbonding2UnBonded2Removed(t *testing.T) {
   563  
   564  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
   565  	params := DefaultParams()
   566  
   567  	originVaSet := addrVals[1:]
   568  	params.MaxValidators = uint16(len(originVaSet))
   569  	params.Epoch = 1
   570  	params.UnbondingTime = time.Millisecond * 300
   571  
   572  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   573  
   574  	startUpStatus := baseValidatorStatus{startUpValidator}
   575  
   576  	orgValsLen := len(originVaSet)
   577  	fullVaSet := make([]sdk.ValAddress, orgValsLen+1)
   578  	copy(fullVaSet, originVaSet)
   579  	copy(fullVaSet[orgValsLen:], []sdk.ValAddress{startUpStatus.getValidator().GetOperator()})
   580  
   581  	bAction := baseAction{mk}
   582  	inputActions := []IAction{
   583  		createValidatorAction{bAction, nil},
   584  		endBlockAction{bAction},
   585  		delegatorsAddSharesAction{bAction, false, true, 0, nil},
   586  		endBlockAction{bAction},
   587  		destroyValidatorAction{bAction},
   588  		endBlockAction{bAction},
   589  
   590  		// first unbonding time pass, delegator shares left, validator unbonding --> unbonded
   591  		waitUntilUnbondingTimeExpired{bAction},
   592  		endBlockAction{bAction},
   593  
   594  		// delegators unbond all tokens back, validator has no msd & delegator shares now, delegator removed
   595  		delegatorsWithdrawAction{bAction, true, true},
   596  	}
   597  
   598  	expZeroDec := sdk.ZeroDec()
   599  	dlgAddSharesCheck1 := andChecker{[]actResChecker{
   600  		validatorDelegatorShareIncreased(true),
   601  		validatorRemoved(false),
   602  		validatorDelegatorShareLeft(true),
   603  		validatorStatusChecker(sdk.Bonded.String()),
   604  	}}
   605  
   606  	afterUnbondingTimeExpiredCheck1 := andChecker{[]actResChecker{
   607  		validatorRemoved(false),
   608  		validatorStatusChecker(sdk.Unbonded.String()),
   609  	}}
   610  
   611  	dlgUnbondCheck2 := andChecker{[]actResChecker{
   612  		noErrorInHandlerResult(true),
   613  		validatorStatusChecker(sdk.Unbonded.String()),
   614  		validatorRemoved(true),
   615  		queryDelegatorCheck(ValidDelegator1, false, nil, nil, &expZeroDec, nil),
   616  	}}
   617  
   618  	actionsAndChecker := []actResChecker{
   619  		validatorStatusChecker(sdk.Unbonded.String()),
   620  		queryValidatorCheck(sdk.Bonded, false, &SharesFromDefaultMSD, &startUpValidator.MinSelfDelegation, nil),
   621  		dlgAddSharesCheck1.GetChecker(),
   622  		nil,
   623  		queryValidatorCheck(sdk.Bonded, true, nil, &expZeroDec, nil),
   624  		validatorStatusChecker(sdk.Unbonding.String()),
   625  		validatorStatusChecker(sdk.Unbonding.String()),
   626  		afterUnbondingTimeExpiredCheck1.GetChecker(),
   627  		dlgUnbondCheck2.GetChecker(),
   628  	}
   629  
   630  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   631  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   632  	smTestCase.printParticipantSnapshot(t)
   633  	smTestCase.Run(t)
   634  }
   635  
   636  // 1. apply DestroyValidator action on a Bonded VA x
   637  // 2. Then delegator unbond all tokens to withdraw shares from VA x
   638  // 3. Wait for an Unbonded VA x
   639  // 4. VA is removed
   640  func TestValidatorSMDestroyValidatorUnbonding2Removed(t *testing.T) {
   641  
   642  	_, _, mk := CreateTestInput(t, false, SufficientInitPower)
   643  	params := DefaultParams()
   644  
   645  	originVaSet := addrVals[1:]
   646  	params.MaxValidators = uint16(len(originVaSet))
   647  	params.Epoch = 1
   648  	params.UnbondingTime = time.Millisecond * 300
   649  
   650  	startUpValidator := NewValidator(StartUpValidatorAddr, StartUpValidatorPubkey, Description{}, types.DefaultMinSelfDelegation)
   651  
   652  	startUpStatus := baseValidatorStatus{startUpValidator}
   653  
   654  	orgValsLen := len(originVaSet)
   655  	fullVaSet := make([]sdk.ValAddress, orgValsLen+1)
   656  	copy(fullVaSet, originVaSet)
   657  	copy(fullVaSet[orgValsLen:], []sdk.ValAddress{startUpStatus.getValidator().GetOperator()})
   658  
   659  	bAction := baseAction{mk}
   660  	inputActions := []IAction{
   661  		createValidatorAction{bAction, nil},
   662  		endBlockAction{bAction},
   663  		delegatorsAddSharesAction{bAction, false, true, 0, nil},
   664  		endBlockAction{bAction},
   665  		destroyValidatorAction{bAction},
   666  		endBlockAction{bAction},
   667  
   668  		// delegators unbond all tokens back, validator has no msd & delegator shares now, delegator removed
   669  		delegatorsWithdrawAction{bAction, true, true},
   670  
   671  		// second unbonding time pass, no delegator shares left, unbonding --> validator removed
   672  		waitUntilUnbondingTimeExpired{bAction},
   673  		endBlockAction{bAction},
   674  	}
   675  
   676  	//expZeroInt := sdk.ZeroInt()
   677  	expZeroDec := sdk.ZeroDec()
   678  	dlgAddSharesCheck1 := andChecker{[]actResChecker{
   679  		validatorDelegatorShareIncreased(true),
   680  		validatorRemoved(false),
   681  		validatorDelegatorShareLeft(true),
   682  		validatorStatusChecker(sdk.Bonded.String()),
   683  	}}
   684  
   685  	dlgUnbondCheck2 := andChecker{[]actResChecker{
   686  		noErrorInHandlerResult(true),
   687  		validatorStatusChecker(sdk.Unbonding.String()),
   688  		validatorRemoved(false),
   689  		queryDelegatorCheck(ValidDelegator1, false, nil, nil, &expZeroDec, nil),
   690  	}}
   691  
   692  	afterUnbondingTimeExpiredCheck1 := andChecker{[]actResChecker{
   693  		validatorRemoved(true),
   694  	}}
   695  
   696  	actionsAndChecker := []actResChecker{
   697  		validatorStatusChecker(sdk.Unbonded.String()),
   698  		queryValidatorCheck(sdk.Bonded, false, &SharesFromDefaultMSD, &startUpValidator.MinSelfDelegation, nil),
   699  		dlgAddSharesCheck1.GetChecker(),
   700  		nil,
   701  		queryValidatorCheck(sdk.Bonded, true, nil, &expZeroDec, nil),
   702  		validatorStatusChecker(sdk.Unbonding.String()),
   703  		dlgUnbondCheck2.GetChecker(),
   704  		queryValidatorCheck(sdk.Unbonding, true, nil, &expZeroDec, nil),
   705  		afterUnbondingTimeExpiredCheck1.GetChecker(),
   706  	}
   707  
   708  	smTestCase := newValidatorSMTestCase(mk, params, startUpStatus, inputActions, actionsAndChecker, t)
   709  	smTestCase.SetupValidatorSetAndDelegatorSet(int(params.MaxValidators))
   710  	smTestCase.printParticipantSnapshot(t)
   711  	smTestCase.Run(t)
   712  }