github.com/lino-network/lino@v0.6.11/x/validator/manager/manager_test.go (about)

     1  package manager
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  	"time"
     7  
     8  	sdk "github.com/cosmos/cosmos-sdk/types"
     9  	"github.com/stretchr/testify/mock"
    10  	"github.com/stretchr/testify/suite"
    11  	abci "github.com/tendermint/tendermint/abci/types"
    12  	crypto "github.com/tendermint/tendermint/crypto"
    13  	"github.com/tendermint/tendermint/crypto/secp256k1"
    14  	tmtypes "github.com/tendermint/tendermint/types"
    15  
    16  	parammodel "github.com/lino-network/lino/param"
    17  	param "github.com/lino-network/lino/param/mocks"
    18  	"github.com/lino-network/lino/testsuites"
    19  	linotypes "github.com/lino-network/lino/types"
    20  	acc "github.com/lino-network/lino/x/account/mocks"
    21  	global "github.com/lino-network/lino/x/global/mocks"
    22  	"github.com/lino-network/lino/x/validator/model"
    23  	"github.com/lino-network/lino/x/validator/types"
    24  	vote "github.com/lino-network/lino/x/vote/mocks"
    25  	votetypes "github.com/lino-network/lino/x/vote/types"
    26  )
    27  
    28  type ValidatorManagerTestSuite struct {
    29  	testsuites.CtxTestSuite
    30  	vm       ValidatorManager
    31  	baseTime time.Time
    32  	// deps
    33  	ph     *param.ParamKeeper
    34  	global *global.GlobalKeeper
    35  	vote   *vote.VoteKeeper
    36  	acc    *acc.AccountKeeper
    37  }
    38  
    39  func TestValidatorManagerTestSuite(t *testing.T) {
    40  	suite.Run(t, new(ValidatorManagerTestSuite))
    41  }
    42  
    43  func (suite *ValidatorManagerTestSuite) SetupTest() {
    44  	suite.baseTime = time.Now()
    45  	testValidatorKey := sdk.NewKVStoreKey("validator")
    46  	suite.SetupCtx(0, suite.baseTime.Add(3*time.Second), testValidatorKey)
    47  	suite.global = &global.GlobalKeeper{}
    48  	suite.ph = &param.ParamKeeper{}
    49  	suite.vote = &vote.VoteKeeper{}
    50  	suite.acc = &acc.AccountKeeper{}
    51  
    52  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("user1")).Return(linotypes.NewCoinFromInt64(300), nil).Maybe()
    53  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("val")).Return(linotypes.NewCoinFromInt64(300), nil).Maybe()
    54  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("jail1")).Return(linotypes.NewCoinFromInt64(200000*linotypes.Decimals), nil).Maybe()
    55  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("jail2")).Return(linotypes.NewCoinFromInt64(200), nil).Maybe()
    56  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("abs")).Return(linotypes.NewCoinFromInt64(200), nil).Maybe()
    57  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("byz")).Return(linotypes.NewCoinFromInt64(2000000*linotypes.Decimals), nil).Maybe()
    58  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("changedVoter")).Return(linotypes.NewCoinFromInt64(600), nil).Maybe()
    59  	suite.vote.On("GetVoterDuty", suite.Ctx, linotypes.AccountKey("val")).Return(votetypes.DutyVoter, nil).Maybe()
    60  	suite.vote.On("AssignDuty", suite.Ctx, linotypes.AccountKey("val"), votetypes.DutyValidator,
    61  		linotypes.NewCoinFromInt64(200000*linotypes.Decimals)).Return(nil).Maybe()
    62  	suite.vote.On("UnassignDuty", suite.Ctx, linotypes.AccountKey("val"), mock.Anything).Return(nil).Maybe()
    63  	suite.vote.On("SlashStake", suite.Ctx, linotypes.AccountKey("abs"),
    64  		linotypes.NewCoinFromInt64(200*linotypes.Decimals), linotypes.InflationValidatorPool).Return(linotypes.NewCoinFromInt64(200*linotypes.Decimals), nil).Maybe()
    65  	suite.vote.On("SlashStake", suite.Ctx, linotypes.AccountKey("byz"),
    66  		linotypes.NewCoinFromInt64(1000*linotypes.Decimals), linotypes.InflationValidatorPool).Return(linotypes.NewCoinFromInt64(200*linotypes.Decimals), nil).Maybe()
    67  
    68  	suite.vote.On("ClaimInterest", suite.Ctx, mock.Anything).Return(nil).Maybe()
    69  
    70  	suite.vm = NewValidatorManager(testValidatorKey, suite.ph, suite.vote, suite.global, suite.acc)
    71  	suite.vm.InitGenesis(suite.Ctx)
    72  	suite.ph.On("GetValidatorParam", mock.Anything).Return(&parammodel.ValidatorParam{
    73  		ValidatorMinDeposit:            linotypes.NewCoinFromInt64(200000 * linotypes.Decimals),
    74  		ValidatorCoinReturnIntervalSec: int64(7 * 24 * 3600),
    75  		ValidatorCoinReturnTimes:       int64(7),
    76  		PenaltyMissCommit:              linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
    77  		PenaltyByzantine:               linotypes.NewCoinFromInt64(1000 * linotypes.Decimals),
    78  		AbsentCommitLimitation:         int64(600), // 30min
    79  		OncallSize:                     int64(3),
    80  		StandbySize:                    int64(3),
    81  		ValidatorRevokePendingSec:      int64(7 * 24 * 3600),
    82  		OncallInflationWeight:          int64(2),
    83  		StandbyInflationWeight:         int64(1),
    84  		MaxVotedValidators:             int64(3),
    85  		SlashLimitation:                int64(5),
    86  	}, nil).Maybe()
    87  
    88  }
    89  
    90  func (suite *ValidatorManagerTestSuite) SetupValidatorAndVotes(m map[linotypes.AccountKey]linotypes.Coin) {
    91  	for name, votes := range m {
    92  		pub := secp256k1.GenPrivKey().PubKey()
    93  		val := model.Validator{
    94  			ABCIValidator: abci.Validator{
    95  				Address: pub.Address(),
    96  				Power:   0},
    97  			PubKey:        pub,
    98  			Username:      name,
    99  			ReceivedVotes: votes,
   100  		}
   101  		suite.vm.storage.SetValidator(suite.Ctx, name, &val)
   102  	}
   103  }
   104  func (suite *ValidatorManagerTestSuite) TestAddValidatortToOncallList() {
   105  	testCases := []struct {
   106  		testName    string
   107  		username    linotypes.AccountKey
   108  		prevList    model.ValidatorList
   109  		prevVal     model.Validator
   110  		expectList  model.ValidatorList
   111  		expectPower int64
   112  	}{
   113  		{
   114  			testName: "add user to oncall",
   115  			username: linotypes.AccountKey("test"),
   116  			prevVal: model.Validator{
   117  				ABCIValidator: abci.Validator{
   118  					Address: secp256k1.GenPrivKey().PubKey().Address(),
   119  					Power:   0},
   120  				Username:      linotypes.AccountKey("test"),
   121  				ReceivedVotes: linotypes.NewCoinFromInt64(100000000),
   122  			},
   123  			prevList: model.ValidatorList{
   124  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   125  				LowestOncall:       linotypes.AccountKey(""),
   126  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   127  				LowestStandby:      linotypes.AccountKey(""),
   128  			},
   129  			expectList: model.ValidatorList{
   130  				Oncall:             []linotypes.AccountKey{linotypes.AccountKey("test")},
   131  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   132  				LowestOncall:       linotypes.AccountKey(""),
   133  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   134  				LowestStandby:      linotypes.AccountKey(""),
   135  			},
   136  			expectPower: 1000,
   137  		},
   138  		{
   139  			testName: "add user to oncall2",
   140  			username: linotypes.AccountKey("test"),
   141  			prevVal: model.Validator{
   142  				ABCIValidator: abci.Validator{
   143  					Address: secp256k1.GenPrivKey().PubKey().Address(),
   144  					Power:   0},
   145  				Username:      linotypes.AccountKey("test"),
   146  				ReceivedVotes: linotypes.NewCoinFromInt64(900000000000 * linotypes.Decimals),
   147  			},
   148  			prevList: model.ValidatorList{
   149  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   150  				LowestOncall:       linotypes.AccountKey(""),
   151  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   152  				LowestStandby:      linotypes.AccountKey(""),
   153  			},
   154  			expectList: model.ValidatorList{
   155  				Oncall:             []linotypes.AccountKey{linotypes.AccountKey("test")},
   156  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   157  				LowestOncall:       linotypes.AccountKey(""),
   158  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   159  				LowestStandby:      linotypes.AccountKey(""),
   160  			},
   161  			expectPower: 100000000000,
   162  		},
   163  	}
   164  
   165  	for _, tc := range testCases {
   166  		suite.vm.storage.SetValidator(suite.Ctx, tc.username, &tc.prevVal)
   167  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   168  		err := suite.vm.addValidatortToOncallList(suite.Ctx, tc.username)
   169  		suite.Require().Nil(err)
   170  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   171  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   172  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
   173  		suite.NoError(err)
   174  		suite.Equal(tc.expectPower, val.ABCIValidator.Power, "%s", tc.testName)
   175  	}
   176  }
   177  
   178  func (suite *ValidatorManagerTestSuite) TestAddValidatortToStandbyList() {
   179  	testCases := []struct {
   180  		testName    string
   181  		username    linotypes.AccountKey
   182  		prevList    model.ValidatorList
   183  		prevVal     model.Validator
   184  		expectList  model.ValidatorList
   185  		expectPower int64
   186  	}{
   187  		{
   188  			testName: "add user to standby",
   189  			username: linotypes.AccountKey("test"),
   190  			prevVal: model.Validator{
   191  				ABCIValidator: abci.Validator{
   192  					Address: secp256k1.GenPrivKey().PubKey().Address(),
   193  					Power:   1000},
   194  				Username:      linotypes.AccountKey("test"),
   195  				ReceivedVotes: linotypes.NewCoinFromInt64(100000000),
   196  			},
   197  			prevList: model.ValidatorList{
   198  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   199  				LowestOncall:       linotypes.AccountKey(""),
   200  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   201  				LowestStandby:      linotypes.AccountKey(""),
   202  			},
   203  			expectList: model.ValidatorList{
   204  				Standby:            []linotypes.AccountKey{linotypes.AccountKey("test")},
   205  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   206  				LowestOncall:       linotypes.AccountKey(""),
   207  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   208  				LowestStandby:      linotypes.AccountKey(""),
   209  			},
   210  			expectPower: 1,
   211  		},
   212  	}
   213  
   214  	for _, tc := range testCases {
   215  		suite.vm.storage.SetValidator(suite.Ctx, tc.username, &tc.prevVal)
   216  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   217  		err := suite.vm.addValidatortToStandbyList(suite.Ctx, tc.username)
   218  		suite.Require().Nil(err)
   219  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   220  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   221  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
   222  		suite.NoError(err)
   223  		suite.Equal(tc.expectPower, val.ABCIValidator.Power, "%s", tc.testName)
   224  	}
   225  }
   226  
   227  func (suite *ValidatorManagerTestSuite) TestAddValidatortToCandidateList() {
   228  	testCases := []struct {
   229  		testName    string
   230  		username    linotypes.AccountKey
   231  		prevList    model.ValidatorList
   232  		prevVal     model.Validator
   233  		expectList  model.ValidatorList
   234  		expectPower int64
   235  	}{
   236  		{
   237  			testName: "add user to candidate",
   238  			username: linotypes.AccountKey("test"),
   239  			prevVal: model.Validator{
   240  				ABCIValidator: abci.Validator{
   241  					Address: secp256k1.GenPrivKey().PubKey().Address(),
   242  					Power:   1000},
   243  				Username:      linotypes.AccountKey("test"),
   244  				ReceivedVotes: linotypes.NewCoinFromInt64(100000000),
   245  			},
   246  			prevList: model.ValidatorList{
   247  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   248  				LowestOncall:       linotypes.AccountKey(""),
   249  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   250  				LowestStandby:      linotypes.AccountKey(""),
   251  			},
   252  			expectList: model.ValidatorList{
   253  				Candidates:         []linotypes.AccountKey{linotypes.AccountKey("test")},
   254  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   255  				LowestOncall:       linotypes.AccountKey(""),
   256  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   257  				LowestStandby:      linotypes.AccountKey(""),
   258  			},
   259  			expectPower: 0,
   260  		},
   261  	}
   262  
   263  	for _, tc := range testCases {
   264  		suite.vm.storage.SetValidator(suite.Ctx, tc.username, &tc.prevVal)
   265  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   266  		err := suite.vm.addValidatortToCandidateList(suite.Ctx, tc.username)
   267  		suite.Require().Nil(err)
   268  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   269  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   270  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
   271  		suite.NoError(err)
   272  		suite.Equal(tc.expectPower, val.ABCIValidator.Power, "%s", tc.testName)
   273  	}
   274  }
   275  
   276  func (suite *ValidatorManagerTestSuite) TestRmValidatortFromCandidateList() {
   277  	testCases := []struct {
   278  		testName   string
   279  		username   linotypes.AccountKey
   280  		prevList   model.ValidatorList
   281  		expectList model.ValidatorList
   282  	}{
   283  		{
   284  			testName: "rm user from candidate",
   285  			username: linotypes.AccountKey("test1"),
   286  			prevList: model.ValidatorList{
   287  				Candidates: []linotypes.AccountKey{
   288  					linotypes.AccountKey("test1"),
   289  					linotypes.AccountKey("test2")},
   290  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   291  				LowestOncall:       linotypes.AccountKey(""),
   292  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   293  				LowestStandby:      linotypes.AccountKey(""),
   294  			},
   295  			expectList: model.ValidatorList{
   296  				Candidates:         []linotypes.AccountKey{linotypes.AccountKey("test2")},
   297  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   298  				LowestOncall:       linotypes.AccountKey(""),
   299  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   300  				LowestStandby:      linotypes.AccountKey(""),
   301  			},
   302  		},
   303  	}
   304  
   305  	for _, tc := range testCases {
   306  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   307  		suite.vm.removeValidatorFromCandidateList(suite.Ctx, tc.username)
   308  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   309  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   310  	}
   311  }
   312  
   313  func (suite *ValidatorManagerTestSuite) TestRmValidatortFromOncallList() {
   314  	testCases := []struct {
   315  		testName   string
   316  		username   linotypes.AccountKey
   317  		prevList   model.ValidatorList
   318  		expectList model.ValidatorList
   319  	}{
   320  		{
   321  			testName: "rm user from oncall",
   322  			username: linotypes.AccountKey("test1"),
   323  			prevList: model.ValidatorList{
   324  				Oncall: []linotypes.AccountKey{
   325  					linotypes.AccountKey("test1"),
   326  					linotypes.AccountKey("test2")},
   327  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   328  				LowestOncall:       linotypes.AccountKey(""),
   329  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   330  				LowestStandby:      linotypes.AccountKey(""),
   331  			},
   332  			expectList: model.ValidatorList{
   333  				Oncall:             []linotypes.AccountKey{linotypes.AccountKey("test2")},
   334  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   335  				LowestOncall:       linotypes.AccountKey(""),
   336  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   337  				LowestStandby:      linotypes.AccountKey(""),
   338  			},
   339  		},
   340  	}
   341  
   342  	for _, tc := range testCases {
   343  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   344  		suite.vm.removeValidatorFromOncallList(suite.Ctx, tc.username)
   345  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   346  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   347  	}
   348  }
   349  
   350  func (suite *ValidatorManagerTestSuite) TestRmValidatortFromStandbyList() {
   351  	testCases := []struct {
   352  		testName   string
   353  		username   linotypes.AccountKey
   354  		prevList   model.ValidatorList
   355  		expectList model.ValidatorList
   356  	}{
   357  		{
   358  			testName: "rm user from standby",
   359  			username: linotypes.AccountKey("test1"),
   360  			prevList: model.ValidatorList{
   361  				Standby: []linotypes.AccountKey{
   362  					linotypes.AccountKey("test1"),
   363  					linotypes.AccountKey("test2")},
   364  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   365  				LowestOncall:       linotypes.AccountKey(""),
   366  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   367  				LowestStandby:      linotypes.AccountKey(""),
   368  			},
   369  			expectList: model.ValidatorList{
   370  				Standby:            []linotypes.AccountKey{linotypes.AccountKey("test2")},
   371  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   372  				LowestOncall:       linotypes.AccountKey(""),
   373  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   374  				LowestStandby:      linotypes.AccountKey(""),
   375  			},
   376  		},
   377  	}
   378  
   379  	for _, tc := range testCases {
   380  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   381  		suite.vm.removeValidatorFromStandbyList(suite.Ctx, tc.username)
   382  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   383  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   384  	}
   385  }
   386  
   387  func (suite *ValidatorManagerTestSuite) TestRmValidatortFromAllList() {
   388  	testCases := []struct {
   389  		testName   string
   390  		username   linotypes.AccountKey
   391  		prevList   model.ValidatorList
   392  		expectList model.ValidatorList
   393  	}{
   394  		{
   395  			testName: "rm user from all list",
   396  			username: linotypes.AccountKey("test1"),
   397  			prevList: model.ValidatorList{
   398  				Standby:            []linotypes.AccountKey{linotypes.AccountKey("test1")},
   399  				Oncall:             []linotypes.AccountKey{linotypes.AccountKey("test2")},
   400  				Candidates:         []linotypes.AccountKey{linotypes.AccountKey("test3")},
   401  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   402  				LowestOncall:       linotypes.AccountKey(""),
   403  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   404  				LowestStandby:      linotypes.AccountKey(""),
   405  			},
   406  			expectList: model.ValidatorList{
   407  				Oncall:             []linotypes.AccountKey{linotypes.AccountKey("test2")},
   408  				Candidates:         []linotypes.AccountKey{linotypes.AccountKey("test3")},
   409  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   410  				LowestOncall:       linotypes.AccountKey(""),
   411  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   412  				LowestStandby:      linotypes.AccountKey(""),
   413  			},
   414  		},
   415  	}
   416  
   417  	for _, tc := range testCases {
   418  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   419  		err := suite.vm.removeValidatorFromAllLists(suite.Ctx, tc.username)
   420  		suite.Require().Nil(err)
   421  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   422  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   423  	}
   424  }
   425  
   426  func (suite *ValidatorManagerTestSuite) TestUpdateLowestOncall() {
   427  	testCases := []struct {
   428  		testName   string
   429  		validators map[linotypes.AccountKey]linotypes.Coin
   430  		prevList   model.ValidatorList
   431  		expectList model.ValidatorList
   432  	}{
   433  		{
   434  			testName: "update lowest oncall",
   435  			validators: map[linotypes.AccountKey]linotypes.Coin{
   436  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(1000),
   437  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(100),
   438  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(2000),
   439  			},
   440  			prevList: model.ValidatorList{
   441  				Oncall: []linotypes.AccountKey{
   442  					linotypes.AccountKey("test1"),
   443  					linotypes.AccountKey("test2"),
   444  					linotypes.AccountKey("test3"),
   445  				},
   446  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   447  				LowestOncall:       linotypes.AccountKey(""),
   448  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   449  				LowestStandby:      linotypes.AccountKey(""),
   450  			},
   451  			expectList: model.ValidatorList{
   452  				Oncall: []linotypes.AccountKey{
   453  					linotypes.AccountKey("test1"),
   454  					linotypes.AccountKey("test2"),
   455  					linotypes.AccountKey("test3"),
   456  				},
   457  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
   458  				LowestOncall:       linotypes.AccountKey("test2"),
   459  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   460  				LowestStandby:      linotypes.AccountKey(""),
   461  			},
   462  		},
   463  		{
   464  			testName: "update lowest oncall2",
   465  			validators: map[linotypes.AccountKey]linotypes.Coin{
   466  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(10000000),
   467  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(100),
   468  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(1),
   469  			},
   470  			prevList: model.ValidatorList{
   471  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
   472  				LowestOncall:       linotypes.AccountKey("test2"),
   473  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   474  				LowestStandby:      linotypes.AccountKey(""),
   475  			},
   476  			expectList: model.ValidatorList{
   477  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   478  				LowestStandby:      linotypes.AccountKey(""),
   479  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   480  				LowestOncall:       linotypes.AccountKey(""),
   481  			},
   482  		},
   483  	}
   484  
   485  	for _, tc := range testCases {
   486  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   487  		suite.SetupValidatorAndVotes(tc.validators)
   488  		err := suite.vm.updateLowestOncall(suite.Ctx)
   489  		suite.Require().Nil(err)
   490  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   491  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   492  	}
   493  }
   494  
   495  func (suite *ValidatorManagerTestSuite) TestUpdateLowestStandby() {
   496  	testCases := []struct {
   497  		testName   string
   498  		validators map[linotypes.AccountKey]linotypes.Coin
   499  		prevList   model.ValidatorList
   500  		expectList model.ValidatorList
   501  	}{
   502  		{
   503  			testName: "update lowest standby",
   504  			validators: map[linotypes.AccountKey]linotypes.Coin{
   505  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(10000000),
   506  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(100),
   507  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(1),
   508  			},
   509  			prevList: model.ValidatorList{
   510  				Standby: []linotypes.AccountKey{
   511  					linotypes.AccountKey("test1"),
   512  					linotypes.AccountKey("test2"),
   513  					linotypes.AccountKey("test3"),
   514  				},
   515  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   516  				LowestOncall:       linotypes.AccountKey(""),
   517  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   518  				LowestStandby:      linotypes.AccountKey(""),
   519  			},
   520  			expectList: model.ValidatorList{
   521  				Standby: []linotypes.AccountKey{
   522  					linotypes.AccountKey("test1"),
   523  					linotypes.AccountKey("test2"),
   524  					linotypes.AccountKey("test3"),
   525  				},
   526  				LowestStandbyVotes: linotypes.NewCoinFromInt64(1),
   527  				LowestStandby:      linotypes.AccountKey("test3"),
   528  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   529  				LowestOncall:       linotypes.AccountKey(""),
   530  			},
   531  		},
   532  		{
   533  			testName: "update lowest standby2",
   534  			validators: map[linotypes.AccountKey]linotypes.Coin{
   535  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(10000000),
   536  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(100),
   537  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(1),
   538  			},
   539  			prevList: model.ValidatorList{
   540  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   541  				LowestOncall:       linotypes.AccountKey(""),
   542  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
   543  				LowestStandby:      linotypes.AccountKey("test2"),
   544  			},
   545  			expectList: model.ValidatorList{
   546  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   547  				LowestStandby:      linotypes.AccountKey(""),
   548  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   549  				LowestOncall:       linotypes.AccountKey(""),
   550  			},
   551  		},
   552  	}
   553  
   554  	for _, tc := range testCases {
   555  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   556  		suite.SetupValidatorAndVotes(tc.validators)
   557  		err := suite.vm.updateLowestStandby(suite.Ctx)
   558  		suite.Require().Nil(err)
   559  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   560  		suite.NoError(err)
   561  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   562  	}
   563  }
   564  
   565  func (suite *ValidatorManagerTestSuite) TestGetHighestVotesAndValidator() {
   566  	testCases := []struct {
   567  		testName      string
   568  		validators    map[linotypes.AccountKey]linotypes.Coin
   569  		lst           []linotypes.AccountKey
   570  		expectValName linotypes.AccountKey
   571  		expectVotes   linotypes.Coin
   572  	}{
   573  		{
   574  			testName: "get highest votes and val",
   575  			validators: map[linotypes.AccountKey]linotypes.Coin{
   576  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(10000000),
   577  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(100),
   578  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(1),
   579  			},
   580  			lst: []linotypes.AccountKey{
   581  				linotypes.AccountKey("test1"),
   582  				linotypes.AccountKey("test2"),
   583  				linotypes.AccountKey("test3"),
   584  			},
   585  			expectValName: linotypes.AccountKey("test1"),
   586  			expectVotes:   linotypes.NewCoinFromInt64(10000000),
   587  		},
   588  		{
   589  			testName: "get highest votes and val2",
   590  			validators: map[linotypes.AccountKey]linotypes.Coin{
   591  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(0),
   592  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(0),
   593  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(0),
   594  			},
   595  			lst: []linotypes.AccountKey{
   596  				linotypes.AccountKey("test1"),
   597  				linotypes.AccountKey("test2"),
   598  				linotypes.AccountKey("test3"),
   599  			},
   600  			expectValName: linotypes.AccountKey("test3"),
   601  			expectVotes:   linotypes.NewCoinFromInt64(0),
   602  		},
   603  	}
   604  
   605  	for _, tc := range testCases {
   606  		suite.SetupValidatorAndVotes(tc.validators)
   607  		name, votes, err := suite.vm.getHighestVotesAndValidator(suite.Ctx, tc.lst)
   608  		suite.Require().Nil(err)
   609  		suite.Equal(tc.expectValName, name, "%s", tc.testName)
   610  		suite.Equal(tc.expectVotes, votes, "%s", tc.testName)
   611  	}
   612  }
   613  
   614  func (suite *ValidatorManagerTestSuite) TestGetLowestVotesAndValidator() {
   615  	testCases := []struct {
   616  		testName      string
   617  		validators    map[linotypes.AccountKey]linotypes.Coin
   618  		lst           []linotypes.AccountKey
   619  		expectValName linotypes.AccountKey
   620  		expectVotes   linotypes.Coin
   621  	}{
   622  		{
   623  			testName: "get lowest votes and val",
   624  			validators: map[linotypes.AccountKey]linotypes.Coin{
   625  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(10000000),
   626  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(100),
   627  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(1),
   628  			},
   629  			lst: []linotypes.AccountKey{
   630  				linotypes.AccountKey("test1"),
   631  				linotypes.AccountKey("test2"),
   632  				linotypes.AccountKey("test3"),
   633  			},
   634  			expectValName: linotypes.AccountKey("test3"),
   635  			expectVotes:   linotypes.NewCoinFromInt64(1),
   636  		},
   637  		{
   638  			testName: "get lowest votes and val2",
   639  			validators: map[linotypes.AccountKey]linotypes.Coin{
   640  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(math.MaxInt64),
   641  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(math.MaxInt64),
   642  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(math.MaxInt64),
   643  			},
   644  			lst: []linotypes.AccountKey{
   645  				linotypes.AccountKey("test1"),
   646  				linotypes.AccountKey("test2"),
   647  				linotypes.AccountKey("test3"),
   648  			},
   649  			expectValName: linotypes.AccountKey("test3"),
   650  			expectVotes:   linotypes.NewCoinFromInt64(math.MaxInt64),
   651  		},
   652  	}
   653  
   654  	for _, tc := range testCases {
   655  		suite.SetupValidatorAndVotes(tc.validators)
   656  		name, votes, err := suite.vm.getLowestVotesAndValidator(suite.Ctx, tc.lst)
   657  		suite.Require().Nil(err)
   658  		suite.Equal(tc.expectValName, name, "%s", tc.testName)
   659  		suite.Equal(tc.expectVotes, votes, "%s", tc.testName)
   660  	}
   661  }
   662  
   663  func (suite *ValidatorManagerTestSuite) TestRemoveExtraOncall() {
   664  	testCases := []struct {
   665  		testName   string
   666  		validators map[linotypes.AccountKey]linotypes.Coin
   667  		prevList   model.ValidatorList
   668  		expectList model.ValidatorList
   669  	}{
   670  		{
   671  			testName: "rm extra oncall",
   672  			validators: map[linotypes.AccountKey]linotypes.Coin{
   673  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(6),
   674  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(5),
   675  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(3),
   676  				linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(4),
   677  				linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(2),
   678  				linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(1),
   679  			},
   680  			prevList: model.ValidatorList{
   681  				Oncall: []linotypes.AccountKey{
   682  					linotypes.AccountKey("test1"),
   683  					linotypes.AccountKey("test2"),
   684  					linotypes.AccountKey("test3"),
   685  					linotypes.AccountKey("test4"),
   686  					linotypes.AccountKey("test5"),
   687  				},
   688  				Standby: []linotypes.AccountKey{
   689  
   690  					linotypes.AccountKey("test6"),
   691  				},
   692  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   693  				LowestOncall:       linotypes.AccountKey(""),
   694  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   695  				LowestStandby:      linotypes.AccountKey(""),
   696  			},
   697  			expectList: model.ValidatorList{
   698  				Oncall: []linotypes.AccountKey{
   699  					linotypes.AccountKey("test1"),
   700  					linotypes.AccountKey("test2"),
   701  					linotypes.AccountKey("test4"),
   702  				},
   703  				Standby: []linotypes.AccountKey{
   704  					linotypes.AccountKey("test6"),
   705  					linotypes.AccountKey("test5"),
   706  					linotypes.AccountKey("test3"),
   707  				},
   708  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   709  				LowestStandby:      linotypes.AccountKey(""),
   710  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   711  				LowestOncall:       linotypes.AccountKey(""),
   712  			},
   713  		},
   714  	}
   715  
   716  	for _, tc := range testCases {
   717  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   718  		suite.SetupValidatorAndVotes(tc.validators)
   719  		err := suite.vm.removeExtraOncall(suite.Ctx)
   720  		suite.Require().Nil(err)
   721  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   722  		suite.NoError(err)
   723  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   724  	}
   725  }
   726  
   727  func (suite *ValidatorManagerTestSuite) TestRemoveExtraStandby() {
   728  	validators := map[linotypes.AccountKey]linotypes.Coin{
   729  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(6),
   730  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(5),
   731  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(3),
   732  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(4),
   733  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(2),
   734  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(1),
   735  	}
   736  	suite.SetupValidatorAndVotes(validators)
   737  	testCases := []struct {
   738  		testName   string
   739  		prevList   model.ValidatorList
   740  		expectList model.ValidatorList
   741  	}{
   742  		{
   743  			testName: "rm extra standby",
   744  			prevList: model.ValidatorList{
   745  				Standby: []linotypes.AccountKey{
   746  					linotypes.AccountKey("test1"),
   747  					linotypes.AccountKey("test2"),
   748  					linotypes.AccountKey("test3"),
   749  					linotypes.AccountKey("test4"),
   750  					linotypes.AccountKey("test5"),
   751  				},
   752  				Candidates: []linotypes.AccountKey{
   753  					linotypes.AccountKey("test6"),
   754  				},
   755  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   756  				LowestOncall:       linotypes.AccountKey(""),
   757  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   758  				LowestStandby:      linotypes.AccountKey(""),
   759  			},
   760  			expectList: model.ValidatorList{
   761  				Standby: []linotypes.AccountKey{
   762  					linotypes.AccountKey("test1"),
   763  					linotypes.AccountKey("test2"),
   764  					linotypes.AccountKey("test4"),
   765  				},
   766  				Candidates: []linotypes.AccountKey{
   767  					linotypes.AccountKey("test6"),
   768  					linotypes.AccountKey("test5"),
   769  					linotypes.AccountKey("test3"),
   770  				},
   771  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   772  				LowestStandby:      linotypes.AccountKey(""),
   773  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   774  				LowestOncall:       linotypes.AccountKey(""),
   775  			},
   776  		},
   777  	}
   778  
   779  	for _, tc := range testCases {
   780  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   781  		err := suite.vm.removeExtraStandby(suite.Ctx)
   782  		suite.Require().Nil(err)
   783  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   784  		suite.NoError(err)
   785  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   786  	}
   787  }
   788  
   789  func (suite *ValidatorManagerTestSuite) TestFillEmptyStandby() {
   790  	validators := map[linotypes.AccountKey]linotypes.Coin{
   791  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(6),
   792  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(5),
   793  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(3),
   794  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(4),
   795  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(2),
   796  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(1),
   797  	}
   798  	suite.SetupValidatorAndVotes(validators)
   799  	testCases := []struct {
   800  		testName   string
   801  		prevList   model.ValidatorList
   802  		expectList model.ValidatorList
   803  	}{
   804  		{
   805  			testName: "fill empty standby",
   806  			prevList: model.ValidatorList{
   807  				Standby: []linotypes.AccountKey{},
   808  				Candidates: []linotypes.AccountKey{
   809  					linotypes.AccountKey("test1"),
   810  					linotypes.AccountKey("test2"),
   811  					linotypes.AccountKey("test3"),
   812  					linotypes.AccountKey("test4"),
   813  					linotypes.AccountKey("test5"),
   814  					linotypes.AccountKey("test6"),
   815  				},
   816  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   817  				LowestOncall:       linotypes.AccountKey(""),
   818  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   819  				LowestStandby:      linotypes.AccountKey(""),
   820  			},
   821  			expectList: model.ValidatorList{
   822  				Standby: []linotypes.AccountKey{
   823  					linotypes.AccountKey("test1"),
   824  					linotypes.AccountKey("test2"),
   825  					linotypes.AccountKey("test4"),
   826  				},
   827  				Candidates: []linotypes.AccountKey{
   828  					linotypes.AccountKey("test3"),
   829  					linotypes.AccountKey("test5"),
   830  					linotypes.AccountKey("test6"),
   831  				},
   832  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   833  				LowestStandby:      linotypes.AccountKey(""),
   834  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   835  				LowestOncall:       linotypes.AccountKey(""),
   836  			},
   837  		},
   838  		{
   839  			testName: "fill empty standby2",
   840  			prevList: model.ValidatorList{
   841  				Standby: []linotypes.AccountKey{},
   842  				Candidates: []linotypes.AccountKey{
   843  					linotypes.AccountKey("test1"),
   844  				},
   845  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   846  				LowestOncall:       linotypes.AccountKey(""),
   847  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   848  				LowestStandby:      linotypes.AccountKey(""),
   849  			},
   850  			expectList: model.ValidatorList{
   851  				Standby: []linotypes.AccountKey{
   852  					linotypes.AccountKey("test1"),
   853  				},
   854  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   855  				LowestStandby:      linotypes.AccountKey(""),
   856  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   857  				LowestOncall:       linotypes.AccountKey(""),
   858  			},
   859  		},
   860  	}
   861  
   862  	for _, tc := range testCases {
   863  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   864  		err := suite.vm.fillEmptyStandby(suite.Ctx)
   865  		suite.Require().Nil(err)
   866  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   867  		suite.NoError(err)
   868  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   869  	}
   870  }
   871  
   872  func (suite *ValidatorManagerTestSuite) TestFillEmptyOncall() {
   873  	validators := map[linotypes.AccountKey]linotypes.Coin{
   874  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(6),
   875  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(5),
   876  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(3),
   877  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(4),
   878  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(2),
   879  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(1),
   880  	}
   881  	suite.SetupValidatorAndVotes(validators)
   882  	testCases := []struct {
   883  		testName   string
   884  		prevList   model.ValidatorList
   885  		expectList model.ValidatorList
   886  	}{
   887  		{
   888  			testName: "fill empty standby",
   889  			prevList: model.ValidatorList{
   890  				Oncall:  []linotypes.AccountKey{},
   891  				Standby: []linotypes.AccountKey{linotypes.AccountKey("test1")},
   892  				Candidates: []linotypes.AccountKey{
   893  					linotypes.AccountKey("test2"),
   894  					linotypes.AccountKey("test3"),
   895  					linotypes.AccountKey("test4"),
   896  					linotypes.AccountKey("test5"),
   897  					linotypes.AccountKey("test6"),
   898  				},
   899  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   900  				LowestOncall:       linotypes.AccountKey(""),
   901  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   902  				LowestStandby:      linotypes.AccountKey(""),
   903  			},
   904  			expectList: model.ValidatorList{
   905  				Oncall: []linotypes.AccountKey{
   906  					linotypes.AccountKey("test1"),
   907  					linotypes.AccountKey("test2"),
   908  					linotypes.AccountKey("test4"),
   909  				},
   910  				Candidates: []linotypes.AccountKey{
   911  					linotypes.AccountKey("test3"),
   912  					linotypes.AccountKey("test5"),
   913  					linotypes.AccountKey("test6"),
   914  				},
   915  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   916  				LowestStandby:      linotypes.AccountKey(""),
   917  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   918  				LowestOncall:       linotypes.AccountKey(""),
   919  			},
   920  		},
   921  		{
   922  			testName: "fill empty oncall2",
   923  			prevList: model.ValidatorList{
   924  				Oncall:  []linotypes.AccountKey{},
   925  				Standby: []linotypes.AccountKey{},
   926  				Candidates: []linotypes.AccountKey{
   927  					linotypes.AccountKey("test1"),
   928  				},
   929  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   930  				LowestOncall:       linotypes.AccountKey(""),
   931  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   932  				LowestStandby:      linotypes.AccountKey(""),
   933  			},
   934  			expectList: model.ValidatorList{
   935  				Oncall: []linotypes.AccountKey{
   936  					linotypes.AccountKey("test1"),
   937  				},
   938  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   939  				LowestStandby:      linotypes.AccountKey(""),
   940  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   941  				LowestOncall:       linotypes.AccountKey(""),
   942  			},
   943  		},
   944  		{
   945  			testName: "fill empty oncall3",
   946  			prevList: model.ValidatorList{
   947  				Oncall: []linotypes.AccountKey{
   948  					linotypes.AccountKey("test1"),
   949  				},
   950  				Standby: []linotypes.AccountKey{
   951  					linotypes.AccountKey("test2"),
   952  					linotypes.AccountKey("test3"),
   953  					linotypes.AccountKey("test4"),
   954  				},
   955  				Candidates: []linotypes.AccountKey{
   956  					linotypes.AccountKey("test5"),
   957  					linotypes.AccountKey("test6"),
   958  				},
   959  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   960  				LowestOncall:       linotypes.AccountKey(""),
   961  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   962  				LowestStandby:      linotypes.AccountKey(""),
   963  			},
   964  			expectList: model.ValidatorList{
   965  				Oncall: []linotypes.AccountKey{
   966  					linotypes.AccountKey("test1"),
   967  					linotypes.AccountKey("test2"),
   968  					linotypes.AccountKey("test4"),
   969  				},
   970  				Standby: []linotypes.AccountKey{
   971  					linotypes.AccountKey("test3"),
   972  				},
   973  				Candidates: []linotypes.AccountKey{
   974  					linotypes.AccountKey("test5"),
   975  					linotypes.AccountKey("test6"),
   976  				},
   977  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
   978  				LowestStandby:      linotypes.AccountKey(""),
   979  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
   980  				LowestOncall:       linotypes.AccountKey(""),
   981  			},
   982  		},
   983  	}
   984  
   985  	for _, tc := range testCases {
   986  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
   987  		err := suite.vm.fillEmptyOncall(suite.Ctx)
   988  		suite.Require().Nil(err)
   989  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
   990  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
   991  	}
   992  }
   993  
   994  func (suite *ValidatorManagerTestSuite) TestGetAllValidators() {
   995  	testCases := []struct {
   996  		testName  string
   997  		prevList  model.ValidatorList
   998  		expectRes []linotypes.AccountKey
   999  	}{
  1000  		{
  1001  			testName: "get all validators",
  1002  			prevList: model.ValidatorList{
  1003  				Oncall: []linotypes.AccountKey{
  1004  					linotypes.AccountKey("test1"),
  1005  					linotypes.AccountKey("test2"),
  1006  					linotypes.AccountKey("test3"),
  1007  				},
  1008  				Standby: []linotypes.AccountKey{
  1009  					linotypes.AccountKey("test4"),
  1010  					linotypes.AccountKey("test5"),
  1011  					linotypes.AccountKey("test6"),
  1012  				},
  1013  				Candidates: []linotypes.AccountKey{
  1014  					linotypes.AccountKey("test7"),
  1015  				},
  1016  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1017  				LowestOncall:       linotypes.AccountKey(""),
  1018  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1019  				LowestStandby:      linotypes.AccountKey(""),
  1020  			},
  1021  			expectRes: []linotypes.AccountKey{
  1022  				linotypes.AccountKey("test1"),
  1023  				linotypes.AccountKey("test2"),
  1024  				linotypes.AccountKey("test3"),
  1025  				linotypes.AccountKey("test4"),
  1026  				linotypes.AccountKey("test5"),
  1027  				linotypes.AccountKey("test6"),
  1028  				linotypes.AccountKey("test7"),
  1029  			},
  1030  		},
  1031  		{
  1032  			testName: "get all validators2",
  1033  			prevList: model.ValidatorList{
  1034  				Oncall: []linotypes.AccountKey{
  1035  					linotypes.AccountKey("test1"),
  1036  				},
  1037  				Standby: []linotypes.AccountKey{
  1038  					linotypes.AccountKey("test4"),
  1039  				},
  1040  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1041  				LowestOncall:       linotypes.AccountKey(""),
  1042  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1043  				LowestStandby:      linotypes.AccountKey(""),
  1044  			},
  1045  			expectRes: []linotypes.AccountKey{
  1046  				linotypes.AccountKey("test1"),
  1047  				linotypes.AccountKey("test4"),
  1048  			},
  1049  		},
  1050  		{
  1051  			testName: "get all validators3",
  1052  			prevList: model.ValidatorList{
  1053  				Oncall: []linotypes.AccountKey{
  1054  					linotypes.AccountKey("test1"),
  1055  				},
  1056  				Candidates: []linotypes.AccountKey{
  1057  					linotypes.AccountKey("test4"),
  1058  				},
  1059  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1060  				LowestOncall:       linotypes.AccountKey(""),
  1061  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1062  				LowestStandby:      linotypes.AccountKey(""),
  1063  			},
  1064  			expectRes: []linotypes.AccountKey{
  1065  				linotypes.AccountKey("test1"),
  1066  				linotypes.AccountKey("test4"),
  1067  			},
  1068  		},
  1069  	}
  1070  
  1071  	for _, tc := range testCases {
  1072  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  1073  		lst := suite.vm.GetAllValidators(suite.Ctx)
  1074  		suite.Equal(tc.expectRes, lst, "%s", tc.testName)
  1075  	}
  1076  }
  1077  
  1078  func (suite *ValidatorManagerTestSuite) TestGetCommittingValidators() {
  1079  	testCases := []struct {
  1080  		testName  string
  1081  		prevList  model.ValidatorList
  1082  		expectRes []linotypes.AccountKey
  1083  	}{
  1084  		{
  1085  			testName: "get committing validators",
  1086  			prevList: model.ValidatorList{
  1087  				Oncall: []linotypes.AccountKey{
  1088  					linotypes.AccountKey("test1"),
  1089  					linotypes.AccountKey("test2"),
  1090  					linotypes.AccountKey("test3"),
  1091  				},
  1092  				Standby: []linotypes.AccountKey{
  1093  					linotypes.AccountKey("test4"),
  1094  					linotypes.AccountKey("test5"),
  1095  					linotypes.AccountKey("test6"),
  1096  				},
  1097  				Candidates: []linotypes.AccountKey{
  1098  					linotypes.AccountKey("test7"),
  1099  				},
  1100  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1101  				LowestOncall:       linotypes.AccountKey(""),
  1102  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1103  				LowestStandby:      linotypes.AccountKey(""),
  1104  			},
  1105  			expectRes: []linotypes.AccountKey{
  1106  				linotypes.AccountKey("test1"),
  1107  				linotypes.AccountKey("test2"),
  1108  				linotypes.AccountKey("test3"),
  1109  				linotypes.AccountKey("test4"),
  1110  				linotypes.AccountKey("test5"),
  1111  				linotypes.AccountKey("test6"),
  1112  			},
  1113  		},
  1114  		{
  1115  			testName: "get committing validators2",
  1116  			prevList: model.ValidatorList{
  1117  				Oncall: []linotypes.AccountKey{
  1118  					linotypes.AccountKey("test1"),
  1119  				},
  1120  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1121  				LowestOncall:       linotypes.AccountKey(""),
  1122  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1123  				LowestStandby:      linotypes.AccountKey(""),
  1124  			},
  1125  			expectRes: []linotypes.AccountKey{
  1126  				linotypes.AccountKey("test1"),
  1127  			},
  1128  		},
  1129  	}
  1130  
  1131  	for _, tc := range testCases {
  1132  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  1133  		lst := suite.vm.GetCommittingValidators(suite.Ctx)
  1134  		suite.Equal(tc.expectRes, lst, "%s", tc.testName)
  1135  	}
  1136  }
  1137  
  1138  func (suite *ValidatorManagerTestSuite) TestOnCandidateVotesInc() {
  1139  	validators := map[linotypes.AccountKey]linotypes.Coin{
  1140  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100),
  1141  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200),
  1142  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  1143  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(400),
  1144  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(500),
  1145  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(600),
  1146  		linotypes.AccountKey("test7"): linotypes.NewCoinFromInt64(700),
  1147  	}
  1148  	suite.SetupValidatorAndVotes(validators)
  1149  
  1150  	testCases := []struct {
  1151  		testName      string
  1152  		prevList      model.ValidatorList
  1153  		increasedUser linotypes.AccountKey
  1154  		expectList    model.ValidatorList
  1155  	}{
  1156  		{
  1157  			testName: "on candidate votes inc",
  1158  			prevList: model.ValidatorList{
  1159  				Candidates: []linotypes.AccountKey{
  1160  					linotypes.AccountKey("test1"),
  1161  				},
  1162  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1163  				LowestOncall:       linotypes.AccountKey(""),
  1164  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1165  				LowestStandby:      linotypes.AccountKey(""),
  1166  			},
  1167  			increasedUser: linotypes.AccountKey("test1"),
  1168  			expectList: model.ValidatorList{
  1169  				Oncall: []linotypes.AccountKey{
  1170  					linotypes.AccountKey("test1"),
  1171  				},
  1172  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1173  				LowestStandby:      linotypes.AccountKey(""),
  1174  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  1175  				LowestOncall:       linotypes.AccountKey("test1"),
  1176  			},
  1177  		},
  1178  		{
  1179  			testName: "on candidate votes inc2",
  1180  			prevList: model.ValidatorList{
  1181  				Standby: []linotypes.AccountKey{
  1182  					linotypes.AccountKey("test1"),
  1183  					linotypes.AccountKey("test2"),
  1184  				},
  1185  				Oncall: []linotypes.AccountKey{
  1186  					linotypes.AccountKey("test3"),
  1187  					linotypes.AccountKey("test4"),
  1188  					linotypes.AccountKey("test5"),
  1189  				},
  1190  				Candidates: []linotypes.AccountKey{
  1191  					linotypes.AccountKey("test6"),
  1192  				},
  1193  				LowestOncallVotes:  linotypes.NewCoinFromInt64(300),
  1194  				LowestOncall:       linotypes.AccountKey("test3"),
  1195  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  1196  				LowestStandby:      linotypes.AccountKey("test1"),
  1197  			},
  1198  			increasedUser: linotypes.AccountKey("test6"),
  1199  			expectList: model.ValidatorList{
  1200  				Standby: []linotypes.AccountKey{
  1201  					linotypes.AccountKey("test1"),
  1202  					linotypes.AccountKey("test2"),
  1203  					linotypes.AccountKey("test3"),
  1204  				},
  1205  				Oncall: []linotypes.AccountKey{
  1206  					linotypes.AccountKey("test4"),
  1207  					linotypes.AccountKey("test5"),
  1208  					linotypes.AccountKey("test6"),
  1209  				},
  1210  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  1211  				LowestStandby:      linotypes.AccountKey("test1"),
  1212  				LowestOncallVotes:  linotypes.NewCoinFromInt64(400),
  1213  				LowestOncall:       linotypes.AccountKey("test4"),
  1214  			},
  1215  		},
  1216  		{
  1217  			testName: "on candidate votes inc3",
  1218  			prevList: model.ValidatorList{
  1219  				Standby: []linotypes.AccountKey{
  1220  					linotypes.AccountKey("test1"),
  1221  					linotypes.AccountKey("test2"),
  1222  					linotypes.AccountKey("test3"),
  1223  				},
  1224  				Oncall: []linotypes.AccountKey{
  1225  					linotypes.AccountKey("test4"),
  1226  					linotypes.AccountKey("test5"),
  1227  					linotypes.AccountKey("test6"),
  1228  				},
  1229  				Candidates: []linotypes.AccountKey{
  1230  					linotypes.AccountKey("test7"),
  1231  				},
  1232  				LowestOncallVotes:  linotypes.NewCoinFromInt64(400),
  1233  				LowestOncall:       linotypes.AccountKey("test4"),
  1234  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  1235  				LowestStandby:      linotypes.AccountKey("test1"),
  1236  			},
  1237  			increasedUser: linotypes.AccountKey("test7"),
  1238  			expectList: model.ValidatorList{
  1239  				Standby: []linotypes.AccountKey{
  1240  					linotypes.AccountKey("test2"),
  1241  					linotypes.AccountKey("test3"),
  1242  					linotypes.AccountKey("test4"),
  1243  				},
  1244  				Oncall: []linotypes.AccountKey{
  1245  
  1246  					linotypes.AccountKey("test5"),
  1247  					linotypes.AccountKey("test6"),
  1248  					linotypes.AccountKey("test7"),
  1249  				},
  1250  				Candidates: []linotypes.AccountKey{
  1251  					linotypes.AccountKey("test1"),
  1252  				},
  1253  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200),
  1254  				LowestStandby:      linotypes.AccountKey("test2"),
  1255  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1256  				LowestOncall:       linotypes.AccountKey("test5"),
  1257  			},
  1258  		},
  1259  		{
  1260  			testName: "on candidate votes inc4",
  1261  			prevList: model.ValidatorList{
  1262  				Standby: []linotypes.AccountKey{
  1263  					linotypes.AccountKey("test1"),
  1264  					linotypes.AccountKey("test3"),
  1265  					linotypes.AccountKey("test4"),
  1266  				},
  1267  				Oncall: []linotypes.AccountKey{
  1268  					linotypes.AccountKey("test7"),
  1269  					linotypes.AccountKey("test6"),
  1270  					linotypes.AccountKey("test5"),
  1271  				},
  1272  				Candidates: []linotypes.AccountKey{
  1273  					linotypes.AccountKey("test2"),
  1274  				},
  1275  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1276  				LowestOncall:       linotypes.AccountKey("test5"),
  1277  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  1278  				LowestStandby:      linotypes.AccountKey("test1"),
  1279  			},
  1280  			increasedUser: linotypes.AccountKey("test2"),
  1281  			expectList: model.ValidatorList{
  1282  				Standby: []linotypes.AccountKey{
  1283  					linotypes.AccountKey("test3"),
  1284  					linotypes.AccountKey("test4"),
  1285  					linotypes.AccountKey("test2"),
  1286  				},
  1287  				Oncall: []linotypes.AccountKey{
  1288  					linotypes.AccountKey("test7"),
  1289  					linotypes.AccountKey("test6"),
  1290  					linotypes.AccountKey("test5"),
  1291  				},
  1292  				Candidates: []linotypes.AccountKey{
  1293  					linotypes.AccountKey("test1"),
  1294  				},
  1295  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200),
  1296  				LowestStandby:      linotypes.AccountKey("test2"),
  1297  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1298  				LowestOncall:       linotypes.AccountKey("test5"),
  1299  			},
  1300  		},
  1301  		{
  1302  			testName: "on candidate votes inc5",
  1303  			prevList: model.ValidatorList{
  1304  				Standby: []linotypes.AccountKey{
  1305  					linotypes.AccountKey("test1"),
  1306  				},
  1307  				Oncall: []linotypes.AccountKey{
  1308  					linotypes.AccountKey("test6"),
  1309  				},
  1310  				Candidates: []linotypes.AccountKey{
  1311  					linotypes.AccountKey("test3"),
  1312  				},
  1313  				LowestOncallVotes:  linotypes.NewCoinFromInt64(600),
  1314  				LowestOncall:       linotypes.AccountKey("test6"),
  1315  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  1316  				LowestStandby:      linotypes.AccountKey("test1"),
  1317  			},
  1318  			increasedUser: linotypes.AccountKey("test3"),
  1319  			expectList: model.ValidatorList{
  1320  				Oncall: []linotypes.AccountKey{
  1321  					linotypes.AccountKey("test6"),
  1322  					linotypes.AccountKey("test3"),
  1323  					linotypes.AccountKey("test1"),
  1324  				},
  1325  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1326  				LowestStandby:      linotypes.AccountKey(""),
  1327  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  1328  				LowestOncall:       linotypes.AccountKey("test1"),
  1329  			},
  1330  		},
  1331  		{
  1332  			testName: "on candidate votes inc6",
  1333  			prevList: model.ValidatorList{
  1334  				Standby: []linotypes.AccountKey{
  1335  					linotypes.AccountKey("test2"),
  1336  					linotypes.AccountKey("test3"),
  1337  					linotypes.AccountKey("test4"),
  1338  				},
  1339  				Oncall: []linotypes.AccountKey{
  1340  					linotypes.AccountKey("test5"),
  1341  					linotypes.AccountKey("test6"),
  1342  					linotypes.AccountKey("test7"),
  1343  				},
  1344  				Candidates: []linotypes.AccountKey{
  1345  					linotypes.AccountKey("test1"),
  1346  				},
  1347  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1348  				LowestOncall:       linotypes.AccountKey("test5"),
  1349  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200),
  1350  				LowestStandby:      linotypes.AccountKey("test2"),
  1351  			},
  1352  			increasedUser: linotypes.AccountKey("test1"),
  1353  			expectList: model.ValidatorList{
  1354  				Standby: []linotypes.AccountKey{
  1355  					linotypes.AccountKey("test2"),
  1356  					linotypes.AccountKey("test3"),
  1357  					linotypes.AccountKey("test4"),
  1358  				},
  1359  				Oncall: []linotypes.AccountKey{
  1360  					linotypes.AccountKey("test5"),
  1361  					linotypes.AccountKey("test6"),
  1362  					linotypes.AccountKey("test7"),
  1363  				},
  1364  				Candidates: []linotypes.AccountKey{
  1365  					linotypes.AccountKey("test1"),
  1366  				},
  1367  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1368  				LowestOncall:       linotypes.AccountKey("test5"),
  1369  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200),
  1370  				LowestStandby:      linotypes.AccountKey("test2"),
  1371  			},
  1372  		},
  1373  		{
  1374  			testName: "on candidate votes inc7",
  1375  			prevList: model.ValidatorList{
  1376  				Standby: []linotypes.AccountKey{
  1377  					linotypes.AccountKey("test5"),
  1378  				},
  1379  				Oncall: []linotypes.AccountKey{
  1380  					linotypes.AccountKey("test6"),
  1381  				},
  1382  				Candidates: []linotypes.AccountKey{
  1383  					linotypes.AccountKey("test3"),
  1384  				},
  1385  				LowestOncallVotes:  linotypes.NewCoinFromInt64(600),
  1386  				LowestOncall:       linotypes.AccountKey("test6"),
  1387  				LowestStandbyVotes: linotypes.NewCoinFromInt64(500),
  1388  				LowestStandby:      linotypes.AccountKey("test5"),
  1389  			},
  1390  			increasedUser: linotypes.AccountKey("test3"),
  1391  			expectList: model.ValidatorList{
  1392  				Oncall: []linotypes.AccountKey{
  1393  					linotypes.AccountKey("test6"),
  1394  					linotypes.AccountKey("test5"),
  1395  					linotypes.AccountKey("test3"),
  1396  				},
  1397  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1398  				LowestStandby:      linotypes.AccountKey(""),
  1399  				LowestOncallVotes:  linotypes.NewCoinFromInt64(300),
  1400  				LowestOncall:       linotypes.AccountKey("test3"),
  1401  			},
  1402  		},
  1403  		{
  1404  			testName: "on candidate votes inc8",
  1405  			prevList: model.ValidatorList{
  1406  				Standby: []linotypes.AccountKey{
  1407  					linotypes.AccountKey("test4"),
  1408  					linotypes.AccountKey("test3"),
  1409  				},
  1410  				Oncall: []linotypes.AccountKey{
  1411  					linotypes.AccountKey("test7"),
  1412  					linotypes.AccountKey("test6"),
  1413  					linotypes.AccountKey("test5"),
  1414  				},
  1415  				Candidates: []linotypes.AccountKey{
  1416  					linotypes.AccountKey("test1"),
  1417  				},
  1418  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1419  				LowestOncall:       linotypes.AccountKey("test5"),
  1420  				LowestStandbyVotes: linotypes.NewCoinFromInt64(300),
  1421  				LowestStandby:      linotypes.AccountKey("test3"),
  1422  			},
  1423  			increasedUser: linotypes.AccountKey("test1"),
  1424  			expectList: model.ValidatorList{
  1425  				Standby: []linotypes.AccountKey{
  1426  					linotypes.AccountKey("test4"),
  1427  					linotypes.AccountKey("test3"),
  1428  					linotypes.AccountKey("test1"),
  1429  				},
  1430  				Oncall: []linotypes.AccountKey{
  1431  					linotypes.AccountKey("test7"),
  1432  					linotypes.AccountKey("test6"),
  1433  					linotypes.AccountKey("test5"),
  1434  				},
  1435  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  1436  				LowestStandby:      linotypes.AccountKey("test1"),
  1437  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1438  				LowestOncall:       linotypes.AccountKey("test5"),
  1439  			},
  1440  		},
  1441  	}
  1442  	for _, tc := range testCases {
  1443  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  1444  		err := suite.vm.onCandidateVotesInc(suite.Ctx, tc.increasedUser)
  1445  		suite.Require().Nil(err)
  1446  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  1447  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  1448  	}
  1449  }
  1450  
  1451  func (suite *ValidatorManagerTestSuite) TestOnStandbyVotesInc() {
  1452  	validators := map[linotypes.AccountKey]linotypes.Coin{
  1453  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100),
  1454  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200),
  1455  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  1456  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(400),
  1457  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(500),
  1458  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(600),
  1459  		linotypes.AccountKey("test7"): linotypes.NewCoinFromInt64(700),
  1460  	}
  1461  	suite.SetupValidatorAndVotes(validators)
  1462  
  1463  	testCases := []struct {
  1464  		testName      string
  1465  		prevList      model.ValidatorList
  1466  		increasedUser linotypes.AccountKey
  1467  		expectList    model.ValidatorList
  1468  	}{
  1469  		{
  1470  			testName: "on standby votes inc",
  1471  			prevList: model.ValidatorList{
  1472  				Standby: []linotypes.AccountKey{
  1473  					linotypes.AccountKey("test1"),
  1474  				},
  1475  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1476  				LowestOncall:       linotypes.AccountKey(""),
  1477  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1478  				LowestStandby:      linotypes.AccountKey(""),
  1479  			},
  1480  			increasedUser: linotypes.AccountKey("test1"),
  1481  			expectList: model.ValidatorList{
  1482  				Oncall: []linotypes.AccountKey{
  1483  					linotypes.AccountKey("test1"),
  1484  				},
  1485  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1486  				LowestStandby:      linotypes.AccountKey(""),
  1487  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  1488  				LowestOncall:       linotypes.AccountKey("test1"),
  1489  			},
  1490  		},
  1491  		{
  1492  			testName: "on standby votes inc2",
  1493  			prevList: model.ValidatorList{
  1494  				Oncall: []linotypes.AccountKey{
  1495  					linotypes.AccountKey("test6"),
  1496  					linotypes.AccountKey("test5"),
  1497  					linotypes.AccountKey("test4"),
  1498  				},
  1499  				Standby: []linotypes.AccountKey{
  1500  					linotypes.AccountKey("test7"),
  1501  				},
  1502  				LowestOncallVotes:  linotypes.NewCoinFromInt64(400),
  1503  				LowestOncall:       linotypes.AccountKey("test4"),
  1504  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1505  				LowestStandby:      linotypes.AccountKey(""),
  1506  			},
  1507  			increasedUser: linotypes.AccountKey("test7"),
  1508  			expectList: model.ValidatorList{
  1509  				Oncall: []linotypes.AccountKey{
  1510  					linotypes.AccountKey("test6"),
  1511  					linotypes.AccountKey("test5"),
  1512  					linotypes.AccountKey("test7"),
  1513  				},
  1514  				Standby: []linotypes.AccountKey{
  1515  					linotypes.AccountKey("test4"),
  1516  				},
  1517  				LowestStandbyVotes: linotypes.NewCoinFromInt64(400),
  1518  				LowestStandby:      linotypes.AccountKey("test4"),
  1519  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1520  				LowestOncall:       linotypes.AccountKey("test5"),
  1521  			},
  1522  		},
  1523  		{
  1524  			testName: "on standby votes inc3",
  1525  			prevList: model.ValidatorList{
  1526  				Oncall: []linotypes.AccountKey{
  1527  					linotypes.AccountKey("test6"),
  1528  					linotypes.AccountKey("test5"),
  1529  					linotypes.AccountKey("test4"),
  1530  				},
  1531  				Standby: []linotypes.AccountKey{
  1532  					linotypes.AccountKey("test3"),
  1533  				},
  1534  				LowestOncallVotes:  linotypes.NewCoinFromInt64(400),
  1535  				LowestOncall:       linotypes.AccountKey("test4"),
  1536  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1537  				LowestStandby:      linotypes.AccountKey(""),
  1538  			},
  1539  			increasedUser: linotypes.AccountKey("test3"),
  1540  			expectList: model.ValidatorList{
  1541  				Oncall: []linotypes.AccountKey{
  1542  					linotypes.AccountKey("test6"),
  1543  					linotypes.AccountKey("test5"),
  1544  					linotypes.AccountKey("test4"),
  1545  				},
  1546  				Standby: []linotypes.AccountKey{
  1547  					linotypes.AccountKey("test3"),
  1548  				},
  1549  				LowestStandbyVotes: linotypes.NewCoinFromInt64(300),
  1550  				LowestStandby:      linotypes.AccountKey("test3"),
  1551  				LowestOncallVotes:  linotypes.NewCoinFromInt64(400),
  1552  				LowestOncall:       linotypes.AccountKey("test4"),
  1553  			},
  1554  		},
  1555  	}
  1556  	for _, tc := range testCases {
  1557  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  1558  		err := suite.vm.onStandbyVotesInc(suite.Ctx, tc.increasedUser)
  1559  		suite.Require().Nil(err)
  1560  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  1561  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  1562  	}
  1563  }
  1564  
  1565  func (suite *ValidatorManagerTestSuite) TestOnOncallVotesInc() {
  1566  	validators := map[linotypes.AccountKey]linotypes.Coin{
  1567  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(600 * linotypes.Decimals),
  1568  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  1569  	}
  1570  	suite.SetupValidatorAndVotes(validators)
  1571  
  1572  	testCases := []struct {
  1573  		testName      string
  1574  		prevList      model.ValidatorList
  1575  		increasedUser linotypes.AccountKey
  1576  		expectList    model.ValidatorList
  1577  		expectPower   int64
  1578  	}{
  1579  		{
  1580  			testName: "on oncall votes inc",
  1581  			prevList: model.ValidatorList{
  1582  				Oncall: []linotypes.AccountKey{
  1583  					linotypes.AccountKey("test6"),
  1584  				},
  1585  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1586  				LowestOncall:       linotypes.AccountKey(""),
  1587  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1588  				LowestStandby:      linotypes.AccountKey(""),
  1589  			},
  1590  			increasedUser: linotypes.AccountKey("test6"),
  1591  			expectList: model.ValidatorList{
  1592  				Oncall: []linotypes.AccountKey{
  1593  					linotypes.AccountKey("test6"),
  1594  				},
  1595  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1596  				LowestStandby:      linotypes.AccountKey(""),
  1597  				LowestOncallVotes:  linotypes.NewCoinFromInt64(600 * linotypes.Decimals),
  1598  				LowestOncall:       linotypes.AccountKey("test6"),
  1599  			},
  1600  			expectPower: 600,
  1601  		},
  1602  		{
  1603  			testName: "on oncall votes inc2",
  1604  			prevList: model.ValidatorList{
  1605  				Oncall: []linotypes.AccountKey{
  1606  					linotypes.AccountKey("test6"),
  1607  				},
  1608  				Standby: []linotypes.AccountKey{
  1609  					linotypes.AccountKey("test3"),
  1610  				},
  1611  				LowestOncallVotes:  linotypes.NewCoinFromInt64(600 * linotypes.Decimals),
  1612  				LowestOncall:       linotypes.AccountKey("test6"),
  1613  				LowestStandbyVotes: linotypes.NewCoinFromInt64(300),
  1614  				LowestStandby:      linotypes.AccountKey("test3"),
  1615  			},
  1616  			increasedUser: linotypes.AccountKey("test6"),
  1617  			expectList: model.ValidatorList{
  1618  				Oncall: []linotypes.AccountKey{
  1619  					linotypes.AccountKey("test6"),
  1620  					linotypes.AccountKey("test3"),
  1621  				},
  1622  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1623  				LowestStandby:      linotypes.AccountKey(""),
  1624  				LowestOncallVotes:  linotypes.NewCoinFromInt64(300),
  1625  				LowestOncall:       linotypes.AccountKey("test3"),
  1626  			},
  1627  			expectPower: 600,
  1628  		},
  1629  	}
  1630  	for _, tc := range testCases {
  1631  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  1632  		err := suite.vm.onOncallVotesInc(suite.Ctx, tc.increasedUser)
  1633  		suite.Require().Nil(err)
  1634  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  1635  		suite.NoError(err)
  1636  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  1637  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.increasedUser)
  1638  		suite.NoError(err)
  1639  		suite.Equal(tc.expectPower, val.ABCIValidator.Power, "%s", tc.testName)
  1640  	}
  1641  }
  1642  
  1643  func (suite *ValidatorManagerTestSuite) TestCheckDupPubKey() {
  1644  	key1 := secp256k1.GenPrivKey().PubKey()
  1645  	key2 := secp256k1.GenPrivKey().PubKey()
  1646  	testCases := []struct {
  1647  		testName    string
  1648  		newKey      crypto.PubKey
  1649  		existVal    model.Validator
  1650  		prevList    model.ValidatorList
  1651  		expectedRes sdk.Error
  1652  	}{
  1653  		{
  1654  			testName: "check dup pubkey",
  1655  			newKey:   key1,
  1656  			existVal: model.Validator{
  1657  				ABCIValidator: abci.Validator{
  1658  					Address: key2.Address(),
  1659  					Power:   0},
  1660  				Username: linotypes.AccountKey("test1"),
  1661  			},
  1662  			prevList: model.ValidatorList{
  1663  				Oncall: []linotypes.AccountKey{
  1664  					linotypes.AccountKey("test1"),
  1665  				},
  1666  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1667  				LowestOncall:       linotypes.AccountKey(""),
  1668  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1669  				LowestStandby:      linotypes.AccountKey(""),
  1670  			},
  1671  			expectedRes: nil,
  1672  		},
  1673  		{
  1674  			testName: "check dup pubkey2",
  1675  			newKey:   key2,
  1676  			existVal: model.Validator{
  1677  				ABCIValidator: abci.Validator{
  1678  					Address: key2.Address(),
  1679  					Power:   0},
  1680  				Username: linotypes.AccountKey("test1"),
  1681  			},
  1682  			prevList: model.ValidatorList{
  1683  				Oncall: []linotypes.AccountKey{
  1684  					linotypes.AccountKey("test1"),
  1685  				},
  1686  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1687  				LowestOncall:       linotypes.AccountKey(""),
  1688  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1689  				LowestStandby:      linotypes.AccountKey(""),
  1690  			},
  1691  			expectedRes: types.ErrValidatorPubKeyAlreadyExist(),
  1692  		},
  1693  	}
  1694  	for _, tc := range testCases {
  1695  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  1696  		suite.vm.storage.SetValidator(suite.Ctx, tc.existVal.Username, &tc.existVal)
  1697  		err := suite.vm.checkDupPubKey(suite.Ctx, tc.newKey)
  1698  		suite.Equal(tc.expectedRes, err, "%s", tc.testName)
  1699  	}
  1700  }
  1701  
  1702  func (suite *ValidatorManagerTestSuite) TestGetElectionVoteListUpdates() {
  1703  	testCases := []struct {
  1704  		testName        string
  1705  		username        linotypes.AccountKey
  1706  		votedValidators []linotypes.AccountKey
  1707  		prevList        model.ElectionVoteList
  1708  		expectedUpdates []*model.ElectionVote
  1709  	}{
  1710  		{
  1711  			testName: "get election vote list updates",
  1712  			username: linotypes.AccountKey("user1"),
  1713  			votedValidators: []linotypes.AccountKey{
  1714  				linotypes.AccountKey("val4"),
  1715  				linotypes.AccountKey("val5"),
  1716  				linotypes.AccountKey("val6"),
  1717  			},
  1718  			prevList: model.ElectionVoteList{
  1719  				ElectionVotes: []model.ElectionVote{
  1720  					{
  1721  						ValidatorName: linotypes.AccountKey("val1"),
  1722  						Vote:          linotypes.NewCoinFromInt64(100),
  1723  					},
  1724  					{
  1725  						ValidatorName: linotypes.AccountKey("val2"),
  1726  						Vote:          linotypes.NewCoinFromInt64(100),
  1727  					},
  1728  					{
  1729  						ValidatorName: linotypes.AccountKey("val3"),
  1730  						Vote:          linotypes.NewCoinFromInt64(100),
  1731  					},
  1732  				},
  1733  			},
  1734  			expectedUpdates: []*model.ElectionVote{
  1735  				{
  1736  					ValidatorName: linotypes.AccountKey("val1"),
  1737  					Vote:          linotypes.NewCoinFromInt64(-100),
  1738  				},
  1739  				{
  1740  					ValidatorName: linotypes.AccountKey("val2"),
  1741  					Vote:          linotypes.NewCoinFromInt64(-100),
  1742  				},
  1743  				{
  1744  					ValidatorName: linotypes.AccountKey("val3"),
  1745  					Vote:          linotypes.NewCoinFromInt64(-100),
  1746  				},
  1747  				{
  1748  					ValidatorName: linotypes.AccountKey("val4"),
  1749  					Vote:          linotypes.NewCoinFromInt64(100),
  1750  				},
  1751  				{
  1752  					ValidatorName: linotypes.AccountKey("val5"),
  1753  					Vote:          linotypes.NewCoinFromInt64(100),
  1754  				},
  1755  				{
  1756  					ValidatorName: linotypes.AccountKey("val6"),
  1757  					Vote:          linotypes.NewCoinFromInt64(100),
  1758  				},
  1759  			},
  1760  		},
  1761  		{
  1762  			testName: "get election vote list updates2",
  1763  			username: linotypes.AccountKey("user1"),
  1764  			votedValidators: []linotypes.AccountKey{
  1765  				linotypes.AccountKey("val1"),
  1766  			},
  1767  			prevList: model.ElectionVoteList{},
  1768  			expectedUpdates: []*model.ElectionVote{
  1769  				{
  1770  					ValidatorName: linotypes.AccountKey("val1"),
  1771  					Vote:          linotypes.NewCoinFromInt64(300),
  1772  				},
  1773  			},
  1774  		},
  1775  		{
  1776  			testName: "get election vote list updates3",
  1777  			username: linotypes.AccountKey("user1"),
  1778  			votedValidators: []linotypes.AccountKey{
  1779  				linotypes.AccountKey("val1"),
  1780  				linotypes.AccountKey("val2"),
  1781  			},
  1782  			prevList: model.ElectionVoteList{
  1783  				ElectionVotes: []model.ElectionVote{
  1784  					{
  1785  						ValidatorName: linotypes.AccountKey("val1"),
  1786  						Vote:          linotypes.NewCoinFromInt64(300),
  1787  					},
  1788  				},
  1789  			},
  1790  			expectedUpdates: []*model.ElectionVote{
  1791  				{
  1792  					ValidatorName: linotypes.AccountKey("val1"),
  1793  					Vote:          linotypes.NewCoinFromInt64(-150),
  1794  				},
  1795  				{
  1796  					ValidatorName: linotypes.AccountKey("val2"),
  1797  					Vote:          linotypes.NewCoinFromInt64(150),
  1798  				},
  1799  			},
  1800  		},
  1801  		{
  1802  			testName: "get election vote list updates4",
  1803  			username: linotypes.AccountKey("user1"),
  1804  			votedValidators: []linotypes.AccountKey{
  1805  				linotypes.AccountKey("val1"),
  1806  				linotypes.AccountKey("val2"),
  1807  			},
  1808  			prevList: model.ElectionVoteList{
  1809  				ElectionVotes: []model.ElectionVote{
  1810  					{
  1811  						ValidatorName: linotypes.AccountKey("val1"),
  1812  						Vote:          linotypes.NewCoinFromInt64(100),
  1813  					},
  1814  					{
  1815  						ValidatorName: linotypes.AccountKey("val2"),
  1816  						Vote:          linotypes.NewCoinFromInt64(100),
  1817  					},
  1818  				},
  1819  			},
  1820  			expectedUpdates: []*model.ElectionVote{
  1821  				{
  1822  					ValidatorName: linotypes.AccountKey("val1"),
  1823  					Vote:          linotypes.NewCoinFromInt64(50),
  1824  				},
  1825  				{
  1826  					ValidatorName: linotypes.AccountKey("val2"),
  1827  					Vote:          linotypes.NewCoinFromInt64(50),
  1828  				},
  1829  			},
  1830  		},
  1831  		{
  1832  			testName: "get election vote list updates5",
  1833  			username: linotypes.AccountKey("user1"),
  1834  			votedValidators: []linotypes.AccountKey{
  1835  				linotypes.AccountKey("val1"),
  1836  			},
  1837  			prevList: model.ElectionVoteList{
  1838  				ElectionVotes: []model.ElectionVote{
  1839  					{
  1840  						ValidatorName: linotypes.AccountKey("val1"),
  1841  						Vote:          linotypes.NewCoinFromInt64(300),
  1842  					},
  1843  				},
  1844  			},
  1845  			expectedUpdates: []*model.ElectionVote{
  1846  				{
  1847  					ValidatorName: linotypes.AccountKey("val1"),
  1848  					Vote: linotypes.NewCoinFromInt64(300).Plus(
  1849  						linotypes.NewCoinFromInt64(300).Neg()),
  1850  				},
  1851  			},
  1852  		},
  1853  	}
  1854  	for _, tc := range testCases {
  1855  		suite.vm.storage.SetElectionVoteList(suite.Ctx, tc.username, &tc.prevList)
  1856  		updates, err := suite.vm.getElectionVoteListUpdates(suite.Ctx, tc.username, tc.votedValidators)
  1857  		suite.NoError(err)
  1858  		suite.Equal(tc.expectedUpdates, updates, "%s", tc.testName)
  1859  	}
  1860  }
  1861  
  1862  func (suite *ValidatorManagerTestSuite) TestSetNewElectionVoteList() {
  1863  	testCases := []struct {
  1864  		testName        string
  1865  		username        linotypes.AccountKey
  1866  		votedValidators []linotypes.AccountKey
  1867  		prevList        model.ElectionVoteList
  1868  		expectedList    model.ElectionVoteList
  1869  	}{
  1870  		{
  1871  			testName: "set new election vote list",
  1872  			username: linotypes.AccountKey("user1"),
  1873  			votedValidators: []linotypes.AccountKey{
  1874  				linotypes.AccountKey("val1"),
  1875  				linotypes.AccountKey("val2"),
  1876  			},
  1877  			prevList: model.ElectionVoteList{
  1878  				ElectionVotes: []model.ElectionVote{
  1879  					{
  1880  						ValidatorName: linotypes.AccountKey("val6"),
  1881  						Vote:          linotypes.NewCoinFromInt64(100),
  1882  					},
  1883  				},
  1884  			},
  1885  			expectedList: model.ElectionVoteList{
  1886  				ElectionVotes: []model.ElectionVote{
  1887  					{
  1888  						ValidatorName: linotypes.AccountKey("val1"),
  1889  						Vote:          linotypes.NewCoinFromInt64(150),
  1890  					},
  1891  					{
  1892  						ValidatorName: linotypes.AccountKey("val2"),
  1893  						Vote:          linotypes.NewCoinFromInt64(150),
  1894  					},
  1895  				},
  1896  			},
  1897  		},
  1898  		{
  1899  			testName:        "set new election vote list2",
  1900  			username:        linotypes.AccountKey("user1"),
  1901  			votedValidators: []linotypes.AccountKey{},
  1902  			prevList: model.ElectionVoteList{
  1903  				ElectionVotes: []model.ElectionVote{
  1904  					{
  1905  						ValidatorName: linotypes.AccountKey("val6"),
  1906  						Vote:          linotypes.NewCoinFromInt64(100),
  1907  					},
  1908  				},
  1909  			},
  1910  			expectedList: model.ElectionVoteList{
  1911  				ElectionVotes: []model.ElectionVote{
  1912  					{
  1913  						ValidatorName: linotypes.AccountKey("val6"),
  1914  						Vote:          linotypes.NewCoinFromInt64(100),
  1915  					},
  1916  				},
  1917  			},
  1918  		},
  1919  	}
  1920  	for _, tc := range testCases {
  1921  		suite.vm.storage.SetElectionVoteList(suite.Ctx, tc.username, &tc.prevList)
  1922  		err := suite.vm.setNewElectionVoteList(suite.Ctx, tc.username, tc.votedValidators)
  1923  		suite.NoError(err)
  1924  		lst := suite.vm.storage.GetElectionVoteList(suite.Ctx, tc.username)
  1925  		suite.Equal(tc.expectedList, *lst, "%s", tc.testName)
  1926  	}
  1927  }
  1928  
  1929  func (suite *ValidatorManagerTestSuite) TestOnStandbyVotesDec() {
  1930  	validators := map[linotypes.AccountKey]linotypes.Coin{
  1931  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100),
  1932  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200),
  1933  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  1934  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(400),
  1935  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(500),
  1936  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(600),
  1937  		linotypes.AccountKey("test7"): linotypes.NewCoinFromInt64(700),
  1938  	}
  1939  	suite.SetupValidatorAndVotes(validators)
  1940  
  1941  	testCases := []struct {
  1942  		testName      string
  1943  		prevList      model.ValidatorList
  1944  		decreasedUser linotypes.AccountKey
  1945  		expectList    model.ValidatorList
  1946  	}{
  1947  		{
  1948  			testName: "on standby votes dec1",
  1949  			prevList: model.ValidatorList{
  1950  				Standby: []linotypes.AccountKey{
  1951  					linotypes.AccountKey("test3"),
  1952  					linotypes.AccountKey("test2"),
  1953  				},
  1954  				Candidates: []linotypes.AccountKey{
  1955  					linotypes.AccountKey("test4"),
  1956  				},
  1957  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  1958  				LowestOncall:       linotypes.AccountKey(""),
  1959  				LowestStandbyVotes: linotypes.NewCoinFromInt64(300),
  1960  				LowestStandby:      linotypes.AccountKey("test3"),
  1961  			},
  1962  			decreasedUser: linotypes.AccountKey("test2"),
  1963  			expectList: model.ValidatorList{
  1964  				Oncall: []linotypes.AccountKey{
  1965  					linotypes.AccountKey("test3"),
  1966  					linotypes.AccountKey("test4"),
  1967  					linotypes.AccountKey("test2"),
  1968  				},
  1969  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  1970  				LowestStandby:      linotypes.AccountKey(""),
  1971  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  1972  				LowestOncall:       linotypes.AccountKey("test2"),
  1973  			},
  1974  		},
  1975  		{
  1976  			testName: "on standby votes dec2",
  1977  			prevList: model.ValidatorList{
  1978  				Oncall: []linotypes.AccountKey{
  1979  					linotypes.AccountKey("test7"),
  1980  					linotypes.AccountKey("test6"),
  1981  					linotypes.AccountKey("test5"),
  1982  				},
  1983  				Standby: []linotypes.AccountKey{
  1984  					linotypes.AccountKey("test4"),
  1985  					linotypes.AccountKey("test3"),
  1986  					linotypes.AccountKey("test1"),
  1987  				},
  1988  				Candidates: []linotypes.AccountKey{
  1989  					linotypes.AccountKey("test2"),
  1990  				},
  1991  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  1992  				LowestOncall:       linotypes.AccountKey("test5"),
  1993  				LowestStandbyVotes: linotypes.NewCoinFromInt64(300),
  1994  				LowestStandby:      linotypes.AccountKey("test3"),
  1995  			},
  1996  			decreasedUser: linotypes.AccountKey("test1"),
  1997  			expectList: model.ValidatorList{
  1998  				Oncall: []linotypes.AccountKey{
  1999  					linotypes.AccountKey("test7"),
  2000  					linotypes.AccountKey("test6"),
  2001  					linotypes.AccountKey("test5"),
  2002  				},
  2003  				Standby: []linotypes.AccountKey{
  2004  					linotypes.AccountKey("test4"),
  2005  					linotypes.AccountKey("test3"),
  2006  					linotypes.AccountKey("test2"),
  2007  				},
  2008  				Candidates: []linotypes.AccountKey{
  2009  					linotypes.AccountKey("test1"),
  2010  				},
  2011  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200),
  2012  				LowestStandby:      linotypes.AccountKey("test2"),
  2013  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  2014  				LowestOncall:       linotypes.AccountKey("test5"),
  2015  			},
  2016  		},
  2017  		{
  2018  			testName: "on standby votes dec3",
  2019  			prevList: model.ValidatorList{
  2020  				Oncall: []linotypes.AccountKey{
  2021  					linotypes.AccountKey("test7"),
  2022  					linotypes.AccountKey("test6"),
  2023  					linotypes.AccountKey("test5"),
  2024  				},
  2025  				Standby: []linotypes.AccountKey{
  2026  					linotypes.AccountKey("test4"),
  2027  					linotypes.AccountKey("test3"),
  2028  					linotypes.AccountKey("test2"),
  2029  				},
  2030  				Candidates: []linotypes.AccountKey{
  2031  					linotypes.AccountKey("test1"),
  2032  				},
  2033  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  2034  				LowestOncall:       linotypes.AccountKey("test5"),
  2035  				LowestStandbyVotes: linotypes.NewCoinFromInt64(300),
  2036  				LowestStandby:      linotypes.AccountKey("test3"),
  2037  			},
  2038  			decreasedUser: linotypes.AccountKey("test2"),
  2039  			expectList: model.ValidatorList{
  2040  				Oncall: []linotypes.AccountKey{
  2041  					linotypes.AccountKey("test7"),
  2042  					linotypes.AccountKey("test6"),
  2043  					linotypes.AccountKey("test5"),
  2044  				},
  2045  				Standby: []linotypes.AccountKey{
  2046  					linotypes.AccountKey("test4"),
  2047  					linotypes.AccountKey("test3"),
  2048  					linotypes.AccountKey("test2"),
  2049  				},
  2050  				Candidates: []linotypes.AccountKey{
  2051  					linotypes.AccountKey("test1"),
  2052  				},
  2053  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200),
  2054  				LowestStandby:      linotypes.AccountKey("test2"),
  2055  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500),
  2056  				LowestOncall:       linotypes.AccountKey("test5"),
  2057  			},
  2058  		},
  2059  		{
  2060  			testName: "on standby votes dec4",
  2061  			prevList: model.ValidatorList{
  2062  				Standby: []linotypes.AccountKey{
  2063  					linotypes.AccountKey("test3"),
  2064  					linotypes.AccountKey("test2"),
  2065  				},
  2066  				Candidates: []linotypes.AccountKey{
  2067  					linotypes.AccountKey("test4"),
  2068  				},
  2069  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  2070  				LowestOncall:       linotypes.AccountKey(""),
  2071  				LowestStandbyVotes: linotypes.NewCoinFromInt64(300),
  2072  				LowestStandby:      linotypes.AccountKey("test3"),
  2073  			},
  2074  			decreasedUser: linotypes.AccountKey("test3"),
  2075  			expectList: model.ValidatorList{
  2076  				Oncall: []linotypes.AccountKey{
  2077  					linotypes.AccountKey("test3"),
  2078  					linotypes.AccountKey("test2"),
  2079  					linotypes.AccountKey("test4"),
  2080  				},
  2081  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2082  				LowestStandby:      linotypes.AccountKey(""),
  2083  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  2084  				LowestOncall:       linotypes.AccountKey("test2"),
  2085  			},
  2086  		},
  2087  	}
  2088  	for _, tc := range testCases {
  2089  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  2090  		err := suite.vm.onStandbyVotesDec(suite.Ctx, tc.decreasedUser)
  2091  		suite.Require().Nil(err)
  2092  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  2093  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  2094  	}
  2095  }
  2096  
  2097  func (suite *ValidatorManagerTestSuite) TestOnOncallVotesDec() {
  2098  	validators := map[linotypes.AccountKey]linotypes.Coin{
  2099  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  2100  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
  2101  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300 * linotypes.Decimals),
  2102  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(400 * linotypes.Decimals),
  2103  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(500 * linotypes.Decimals),
  2104  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(600 * linotypes.Decimals),
  2105  		linotypes.AccountKey("test7"): linotypes.NewCoinFromInt64(700 * linotypes.Decimals),
  2106  	}
  2107  	suite.SetupValidatorAndVotes(validators)
  2108  
  2109  	testCases := []struct {
  2110  		testName      string
  2111  		prevList      model.ValidatorList
  2112  		decreasedUser linotypes.AccountKey
  2113  		expectList    model.ValidatorList
  2114  		expectPower   int64
  2115  	}{
  2116  		{
  2117  			testName: "on oncall votes dec",
  2118  			prevList: model.ValidatorList{
  2119  				Oncall: []linotypes.AccountKey{
  2120  					linotypes.AccountKey("test7"),
  2121  					linotypes.AccountKey("test6"),
  2122  					linotypes.AccountKey("test1"),
  2123  				},
  2124  				Standby: []linotypes.AccountKey{
  2125  					linotypes.AccountKey("test5"),
  2126  					linotypes.AccountKey("test4"),
  2127  					linotypes.AccountKey("test3"),
  2128  				},
  2129  				Candidates: []linotypes.AccountKey{
  2130  					linotypes.AccountKey("test2"),
  2131  				},
  2132  				LowestOncallVotes:  linotypes.NewCoinFromInt64(600 * linotypes.Decimals),
  2133  				LowestOncall:       linotypes.AccountKey("test6"),
  2134  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
  2135  				LowestStandby:      linotypes.AccountKey("test2"),
  2136  			},
  2137  			decreasedUser: linotypes.AccountKey("test1"),
  2138  			expectPower:   0,
  2139  			expectList: model.ValidatorList{
  2140  				Oncall: []linotypes.AccountKey{
  2141  					linotypes.AccountKey("test7"),
  2142  					linotypes.AccountKey("test6"),
  2143  					linotypes.AccountKey("test5"),
  2144  				},
  2145  				Standby: []linotypes.AccountKey{
  2146  					linotypes.AccountKey("test4"),
  2147  					linotypes.AccountKey("test3"),
  2148  					linotypes.AccountKey("test2"),
  2149  				},
  2150  				Candidates: []linotypes.AccountKey{
  2151  					linotypes.AccountKey("test1"),
  2152  				},
  2153  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
  2154  				LowestStandby:      linotypes.AccountKey("test2"),
  2155  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500 * linotypes.Decimals),
  2156  				LowestOncall:       linotypes.AccountKey("test5"),
  2157  			},
  2158  		},
  2159  		{
  2160  			testName: "on oncall votes dec2",
  2161  			prevList: model.ValidatorList{
  2162  				Oncall: []linotypes.AccountKey{
  2163  					linotypes.AccountKey("test2"),
  2164  				},
  2165  				LowestOncallVotes:  linotypes.NewCoinFromInt64(300 * linotypes.Decimals),
  2166  				LowestOncall:       linotypes.AccountKey("test2"),
  2167  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2168  				LowestStandby:      linotypes.AccountKey(""),
  2169  			},
  2170  			decreasedUser: linotypes.AccountKey("test2"),
  2171  			expectPower:   200,
  2172  			expectList: model.ValidatorList{
  2173  				Oncall: []linotypes.AccountKey{
  2174  					linotypes.AccountKey("test2"),
  2175  				},
  2176  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2177  				LowestStandby:      linotypes.AccountKey(""),
  2178  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
  2179  				LowestOncall:       linotypes.AccountKey("test2"),
  2180  			},
  2181  		},
  2182  		{
  2183  			testName: "on oncall votes dec3",
  2184  			prevList: model.ValidatorList{
  2185  				Oncall: []linotypes.AccountKey{
  2186  					linotypes.AccountKey("test7"),
  2187  					linotypes.AccountKey("test6"),
  2188  					linotypes.AccountKey("test3"),
  2189  				},
  2190  				Standby: []linotypes.AccountKey{
  2191  					linotypes.AccountKey("test5"),
  2192  					linotypes.AccountKey("test4"),
  2193  					linotypes.AccountKey("test2"),
  2194  				},
  2195  				Candidates: []linotypes.AccountKey{
  2196  					linotypes.AccountKey("test1"),
  2197  				},
  2198  				LowestOncallVotes:  linotypes.NewCoinFromInt64(600 * linotypes.Decimals),
  2199  				LowestOncall:       linotypes.AccountKey("test6"),
  2200  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
  2201  				LowestStandby:      linotypes.AccountKey("test2"),
  2202  			},
  2203  			decreasedUser: linotypes.AccountKey("test3"),
  2204  			expectPower:   1,
  2205  			expectList: model.ValidatorList{
  2206  				Oncall: []linotypes.AccountKey{
  2207  					linotypes.AccountKey("test7"),
  2208  					linotypes.AccountKey("test6"),
  2209  					linotypes.AccountKey("test5"),
  2210  				},
  2211  				Standby: []linotypes.AccountKey{
  2212  					linotypes.AccountKey("test4"),
  2213  					linotypes.AccountKey("test3"),
  2214  					linotypes.AccountKey("test2"),
  2215  				},
  2216  				Candidates: []linotypes.AccountKey{
  2217  					linotypes.AccountKey("test1"),
  2218  				},
  2219  				LowestStandbyVotes: linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
  2220  				LowestStandby:      linotypes.AccountKey("test2"),
  2221  				LowestOncallVotes:  linotypes.NewCoinFromInt64(500 * linotypes.Decimals),
  2222  				LowestOncall:       linotypes.AccountKey("test5"),
  2223  			},
  2224  		},
  2225  		{
  2226  			testName: "on oncall votes dec4",
  2227  			prevList: model.ValidatorList{
  2228  				Oncall: []linotypes.AccountKey{
  2229  					linotypes.AccountKey("test2"),
  2230  					linotypes.AccountKey("test1"),
  2231  				},
  2232  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  2233  				LowestOncall:       linotypes.AccountKey("test1"),
  2234  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2235  				LowestStandby:      linotypes.AccountKey(""),
  2236  			},
  2237  			decreasedUser: linotypes.AccountKey("test2"),
  2238  			expectPower:   200,
  2239  			expectList: model.ValidatorList{
  2240  				Oncall: []linotypes.AccountKey{
  2241  					linotypes.AccountKey("test2"),
  2242  					linotypes.AccountKey("test1"),
  2243  				},
  2244  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2245  				LowestStandby:      linotypes.AccountKey(""),
  2246  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  2247  				LowestOncall:       linotypes.AccountKey("test1"),
  2248  			},
  2249  		},
  2250  		{
  2251  			testName: "on oncall votes dec5",
  2252  			prevList: model.ValidatorList{
  2253  				Oncall: []linotypes.AccountKey{
  2254  					linotypes.AccountKey("test2"),
  2255  				},
  2256  				Standby: []linotypes.AccountKey{
  2257  					linotypes.AccountKey("test1"),
  2258  				},
  2259  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200 * linotypes.Decimals),
  2260  				LowestOncall:       linotypes.AccountKey("test2"),
  2261  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2262  				LowestStandby:      linotypes.AccountKey(""),
  2263  			},
  2264  			decreasedUser: linotypes.AccountKey("test2"),
  2265  			expectPower:   200,
  2266  			expectList: model.ValidatorList{
  2267  				Oncall: []linotypes.AccountKey{
  2268  					linotypes.AccountKey("test2"),
  2269  					linotypes.AccountKey("test1"),
  2270  				},
  2271  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2272  				LowestStandby:      linotypes.AccountKey(""),
  2273  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  2274  				LowestOncall:       linotypes.AccountKey("test1"),
  2275  			},
  2276  		},
  2277  	}
  2278  	for _, tc := range testCases {
  2279  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  2280  		err := suite.vm.onOncallVotesDec(suite.Ctx, tc.decreasedUser)
  2281  		suite.Require().Nil(err)
  2282  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  2283  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  2284  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.decreasedUser)
  2285  		suite.NoError(err)
  2286  		suite.Equal(tc.expectPower, val.ABCIValidator.Power, "%s", tc.testName)
  2287  	}
  2288  }
  2289  
  2290  func (suite *ValidatorManagerTestSuite) TestGetValidatorUpdates() {
  2291  	valKey1 := secp256k1.GenPrivKey().PubKey()
  2292  	valKey2 := secp256k1.GenPrivKey().PubKey()
  2293  
  2294  	user1 := linotypes.AccountKey("user1")
  2295  	user2 := linotypes.AccountKey("user2")
  2296  	validator1 := model.Validator{
  2297  		ABCIValidator: abci.Validator{
  2298  			Address: valKey1.Address(),
  2299  			Power:   linotypes.TendermintValidatorPower,
  2300  		},
  2301  		PubKey:        valKey1,
  2302  		Username:      user1,
  2303  		ReceivedVotes: linotypes.NewCoinFromInt64(0),
  2304  	}
  2305  	validator2 := model.Validator{
  2306  		ABCIValidator: abci.Validator{
  2307  			Address: valKey2.Address(),
  2308  			Power:   linotypes.TendermintValidatorPower,
  2309  		},
  2310  		PubKey:        valKey2,
  2311  		Username:      user2,
  2312  		ReceivedVotes: linotypes.NewCoinFromInt64(0),
  2313  	}
  2314  	suite.vm.storage.SetValidator(suite.Ctx, user1, &validator1)
  2315  	suite.vm.storage.SetValidator(suite.Ctx, user2, &validator2)
  2316  
  2317  	val1 := abci.ValidatorUpdate{
  2318  		PubKey: tmtypes.TM2PB.PubKey(valKey1),
  2319  		Power:  linotypes.TendermintValidatorPower,
  2320  	}
  2321  
  2322  	val2 := abci.ValidatorUpdate{
  2323  		PubKey: tmtypes.TM2PB.PubKey(valKey2),
  2324  		Power:  linotypes.TendermintValidatorPower,
  2325  	}
  2326  
  2327  	val1NoPower := abci.ValidatorUpdate{
  2328  		PubKey: tmtypes.TM2PB.PubKey(valKey1),
  2329  		Power:  0,
  2330  	}
  2331  
  2332  	val2NoPower := abci.ValidatorUpdate{
  2333  		PubKey: tmtypes.TM2PB.PubKey(valKey2),
  2334  		Power:  0,
  2335  	}
  2336  
  2337  	testCases := []struct {
  2338  		testName            string
  2339  		oncallValidators    []linotypes.AccountKey
  2340  		preBlockValidators  []linotypes.AccountKey
  2341  		expectedUpdatedList []abci.ValidatorUpdate
  2342  	}{
  2343  		{
  2344  			testName:            "only one oncall validator",
  2345  			oncallValidators:    []linotypes.AccountKey{user1},
  2346  			preBlockValidators:  []linotypes.AccountKey{},
  2347  			expectedUpdatedList: []abci.ValidatorUpdate{val1},
  2348  		},
  2349  		{
  2350  			testName:            "two oncall validators and one pre block validator",
  2351  			oncallValidators:    []linotypes.AccountKey{user1, user2},
  2352  			preBlockValidators:  []linotypes.AccountKey{user1},
  2353  			expectedUpdatedList: []abci.ValidatorUpdate{val1, val2},
  2354  		},
  2355  		{
  2356  			testName:            "two oncall validatos and two pre block validators",
  2357  			oncallValidators:    []linotypes.AccountKey{user1, user2},
  2358  			preBlockValidators:  []linotypes.AccountKey{user1, user2},
  2359  			expectedUpdatedList: []abci.ValidatorUpdate{val1, val2},
  2360  		},
  2361  		{
  2362  			testName:            "one oncall validator and two pre block validators",
  2363  			oncallValidators:    []linotypes.AccountKey{user2},
  2364  			preBlockValidators:  []linotypes.AccountKey{user1, user2},
  2365  			expectedUpdatedList: []abci.ValidatorUpdate{val1NoPower, val2},
  2366  		},
  2367  		{
  2368  			testName:            "only one pre block validator",
  2369  			oncallValidators:    []linotypes.AccountKey{},
  2370  			preBlockValidators:  []linotypes.AccountKey{user2},
  2371  			expectedUpdatedList: []abci.ValidatorUpdate{val2NoPower},
  2372  		},
  2373  	}
  2374  
  2375  	for _, tc := range testCases {
  2376  		lst := &model.ValidatorList{
  2377  			Oncall:             tc.oncallValidators,
  2378  			PreBlockValidators: tc.preBlockValidators,
  2379  		}
  2380  		suite.vm.storage.SetValidatorList(suite.Ctx, lst)
  2381  
  2382  		actualList, err := suite.vm.GetValidatorUpdates(suite.Ctx)
  2383  		suite.NoError(err)
  2384  		suite.Equal(tc.expectedUpdatedList, actualList, "%s", tc.testName)
  2385  	}
  2386  }
  2387  
  2388  func (suite *ValidatorManagerTestSuite) TestRejoinFromJail() {
  2389  	validators := map[linotypes.AccountKey]linotypes.Coin{
  2390  		linotypes.AccountKey("jail1"): linotypes.NewCoinFromInt64(100),
  2391  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(200),
  2392  	}
  2393  	suite.SetupValidatorAndVotes(validators)
  2394  
  2395  	testCases := []struct {
  2396  		testName   string
  2397  		prevList   model.ValidatorList
  2398  		rejoinUser linotypes.AccountKey
  2399  		expectList model.ValidatorList
  2400  		expectRes  sdk.Error
  2401  	}{
  2402  		{
  2403  			testName: "rejoin from jail",
  2404  			prevList: model.ValidatorList{
  2405  				Oncall: []linotypes.AccountKey{
  2406  					linotypes.AccountKey("test1"),
  2407  				},
  2408  				Jail: []linotypes.AccountKey{
  2409  					linotypes.AccountKey("jail1"),
  2410  				},
  2411  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  2412  				LowestOncall:       linotypes.AccountKey("test1"),
  2413  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2414  				LowestStandby:      linotypes.AccountKey(""),
  2415  			},
  2416  			rejoinUser: linotypes.AccountKey("jail1"),
  2417  			expectList: model.ValidatorList{
  2418  				Oncall: []linotypes.AccountKey{
  2419  					linotypes.AccountKey("test1"),
  2420  					linotypes.AccountKey("jail1"),
  2421  				},
  2422  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2423  				LowestStandby:      linotypes.AccountKey(""),
  2424  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  2425  				LowestOncall:       linotypes.AccountKey("jail1"),
  2426  			},
  2427  			expectRes: nil,
  2428  		},
  2429  		{
  2430  			testName: "rejoin from jail2",
  2431  			prevList: model.ValidatorList{
  2432  				Oncall: []linotypes.AccountKey{
  2433  					linotypes.AccountKey("test1"),
  2434  				},
  2435  				Jail: []linotypes.AccountKey{
  2436  					linotypes.AccountKey("jail2"),
  2437  				},
  2438  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  2439  				LowestOncall:       linotypes.AccountKey("test1"),
  2440  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2441  				LowestStandby:      linotypes.AccountKey(""),
  2442  			},
  2443  			rejoinUser: linotypes.AccountKey("jail2"),
  2444  			expectList: model.ValidatorList{
  2445  				Oncall: []linotypes.AccountKey{
  2446  					linotypes.AccountKey("test1"),
  2447  				},
  2448  				Jail: []linotypes.AccountKey{
  2449  					linotypes.AccountKey("jail2"),
  2450  				},
  2451  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2452  				LowestStandby:      linotypes.AccountKey(""),
  2453  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  2454  				LowestOncall:       linotypes.AccountKey("test1"),
  2455  			},
  2456  			expectRes: types.ErrInsufficientDeposit(),
  2457  		},
  2458  	}
  2459  	for _, tc := range testCases {
  2460  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  2461  		err := suite.vm.rejoinFromJail(suite.Ctx, tc.rejoinUser)
  2462  		suite.Equal(tc.expectRes, err, "%s", tc.testName)
  2463  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  2464  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  2465  	}
  2466  }
  2467  
  2468  func (suite *ValidatorManagerTestSuite) TestVoteValidator() {
  2469  	validators := map[linotypes.AccountKey]linotypes.Coin{
  2470  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100),
  2471  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200),
  2472  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  2473  	}
  2474  	suite.SetupValidatorAndVotes(validators)
  2475  
  2476  	testCases := []struct {
  2477  		testName           string
  2478  		prevValList        model.ValidatorList
  2479  		voter              linotypes.AccountKey
  2480  		votedValidators    []linotypes.AccountKey
  2481  		expectElectionList model.ElectionVoteList
  2482  		expectValAndVotes  map[linotypes.AccountKey]linotypes.Coin
  2483  		expectRes          sdk.Error
  2484  	}{
  2485  		{
  2486  			testName: "vote validator",
  2487  			prevValList: model.ValidatorList{
  2488  				Oncall: []linotypes.AccountKey{
  2489  					linotypes.AccountKey("test1"),
  2490  					linotypes.AccountKey("test2"),
  2491  					linotypes.AccountKey("test3"),
  2492  				},
  2493  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  2494  				LowestOncall:       linotypes.AccountKey("test1"),
  2495  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2496  				LowestStandby:      linotypes.AccountKey(""),
  2497  			},
  2498  			voter: linotypes.AccountKey("user1"),
  2499  			votedValidators: []linotypes.AccountKey{
  2500  				linotypes.AccountKey("test1"),
  2501  				linotypes.AccountKey("test2"),
  2502  				linotypes.AccountKey("test3"),
  2503  			},
  2504  			expectElectionList: model.ElectionVoteList{
  2505  				ElectionVotes: []model.ElectionVote{
  2506  					{
  2507  						ValidatorName: linotypes.AccountKey("test1"),
  2508  						Vote:          linotypes.NewCoinFromInt64(100),
  2509  					},
  2510  					{
  2511  						ValidatorName: linotypes.AccountKey("test2"),
  2512  						Vote:          linotypes.NewCoinFromInt64(100),
  2513  					},
  2514  					{
  2515  						ValidatorName: linotypes.AccountKey("test3"),
  2516  						Vote:          linotypes.NewCoinFromInt64(100),
  2517  					},
  2518  				},
  2519  			},
  2520  			expectValAndVotes: map[linotypes.AccountKey]linotypes.Coin{
  2521  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(200),
  2522  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(300),
  2523  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(400),
  2524  			},
  2525  			expectRes: nil,
  2526  		},
  2527  		{
  2528  			testName: "vote validator2",
  2529  			prevValList: model.ValidatorList{
  2530  				Oncall: []linotypes.AccountKey{
  2531  					linotypes.AccountKey("test1"),
  2532  					linotypes.AccountKey("test2"),
  2533  					linotypes.AccountKey("test3"),
  2534  				},
  2535  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  2536  				LowestOncall:       linotypes.AccountKey("test1"),
  2537  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2538  				LowestStandby:      linotypes.AccountKey(""),
  2539  			},
  2540  			voter: linotypes.AccountKey("user1"),
  2541  			votedValidators: []linotypes.AccountKey{
  2542  				linotypes.AccountKey("test1"),
  2543  				linotypes.AccountKey("test2"),
  2544  				linotypes.AccountKey("dummy"),
  2545  			},
  2546  			expectElectionList: model.ElectionVoteList{
  2547  				ElectionVotes: []model.ElectionVote{
  2548  					{
  2549  						ValidatorName: linotypes.AccountKey("test1"),
  2550  						Vote:          linotypes.NewCoinFromInt64(100),
  2551  					},
  2552  					{
  2553  						ValidatorName: linotypes.AccountKey("test2"),
  2554  						Vote:          linotypes.NewCoinFromInt64(100),
  2555  					},
  2556  					{
  2557  						ValidatorName: linotypes.AccountKey("test3"),
  2558  						Vote:          linotypes.NewCoinFromInt64(100),
  2559  					},
  2560  				},
  2561  			},
  2562  			expectValAndVotes: map[linotypes.AccountKey]linotypes.Coin{
  2563  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(200),
  2564  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(300),
  2565  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(400),
  2566  			},
  2567  			expectRes: types.ErrValidatorNotFound(linotypes.AccountKey("dummy")),
  2568  		},
  2569  	}
  2570  	for _, tc := range testCases {
  2571  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevValList)
  2572  		err := suite.vm.VoteValidator(suite.Ctx, tc.voter, tc.votedValidators)
  2573  		suite.Equal(tc.expectRes, err, "%s", tc.testName)
  2574  		lst := suite.vm.storage.GetElectionVoteList(suite.Ctx, tc.voter)
  2575  		suite.Equal(tc.expectElectionList, *lst, "%s", tc.testName)
  2576  		for k, v := range tc.expectValAndVotes {
  2577  			val, _ := suite.vm.storage.GetValidator(suite.Ctx, k)
  2578  			suite.Equal(v, val.ReceivedVotes, "%s", tc.testName)
  2579  		}
  2580  	}
  2581  }
  2582  
  2583  func (suite *ValidatorManagerTestSuite) TestGetInitValidators() {
  2584  	valKey1 := secp256k1.GenPrivKey().PubKey()
  2585  	valKey2 := secp256k1.GenPrivKey().PubKey()
  2586  
  2587  	user1 := linotypes.AccountKey("user1")
  2588  	user2 := linotypes.AccountKey("user2")
  2589  	validator1 := model.Validator{
  2590  		ABCIValidator: abci.Validator{
  2591  			Address: valKey1.Address(),
  2592  			Power:   linotypes.TendermintValidatorPower,
  2593  		},
  2594  		PubKey:        valKey1,
  2595  		Username:      user1,
  2596  		ReceivedVotes: linotypes.NewCoinFromInt64(0),
  2597  	}
  2598  	validator2 := model.Validator{
  2599  		ABCIValidator: abci.Validator{
  2600  			Address: valKey2.Address(),
  2601  			Power:   linotypes.TendermintValidatorPower,
  2602  		},
  2603  		PubKey:        valKey2,
  2604  		Username:      user2,
  2605  		ReceivedVotes: linotypes.NewCoinFromInt64(0),
  2606  	}
  2607  	suite.vm.storage.SetValidator(suite.Ctx, user1, &validator1)
  2608  	suite.vm.storage.SetValidator(suite.Ctx, user2, &validator2)
  2609  
  2610  	val1 := abci.ValidatorUpdate{
  2611  		PubKey: tmtypes.TM2PB.PubKey(valKey1),
  2612  		Power:  linotypes.TendermintValidatorPower,
  2613  	}
  2614  
  2615  	val2 := abci.ValidatorUpdate{
  2616  		PubKey: tmtypes.TM2PB.PubKey(valKey2),
  2617  		Power:  linotypes.TendermintValidatorPower,
  2618  	}
  2619  
  2620  	testCases := []struct {
  2621  		testName            string
  2622  		oncallValidators    []linotypes.AccountKey
  2623  		expectedUpdatedList []abci.ValidatorUpdate
  2624  	}{
  2625  		{
  2626  			testName:            "only one oncall validator",
  2627  			oncallValidators:    []linotypes.AccountKey{user1},
  2628  			expectedUpdatedList: []abci.ValidatorUpdate{val1},
  2629  		},
  2630  		{
  2631  			testName:            "two oncall validators",
  2632  			oncallValidators:    []linotypes.AccountKey{user1, user2},
  2633  			expectedUpdatedList: []abci.ValidatorUpdate{val1, val2},
  2634  		},
  2635  		{
  2636  			testName:            "no validators exists",
  2637  			oncallValidators:    []linotypes.AccountKey{},
  2638  			expectedUpdatedList: []abci.ValidatorUpdate{},
  2639  		},
  2640  	}
  2641  
  2642  	for _, tc := range testCases {
  2643  		lst := &model.ValidatorList{
  2644  			Oncall: tc.oncallValidators,
  2645  		}
  2646  		suite.vm.storage.SetValidatorList(suite.Ctx, lst)
  2647  
  2648  		actualList, err := suite.vm.GetInitValidators(suite.Ctx)
  2649  		suite.NoError(err)
  2650  		suite.Equal(tc.expectedUpdatedList, actualList, "%s", tc.testName)
  2651  	}
  2652  }
  2653  
  2654  func (suite *ValidatorManagerTestSuite) TestFireIncompetentValidator() {
  2655  	validators := map[linotypes.AccountKey]linotypes.Coin{
  2656  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100),
  2657  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200),
  2658  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  2659  	}
  2660  	suite.SetupValidatorAndVotes(validators)
  2661  
  2662  	byzKey := secp256k1.GenPrivKey().PubKey()
  2663  	byz := linotypes.AccountKey("byz")
  2664  	byzVal := model.Validator{
  2665  		ABCIValidator: abci.Validator{
  2666  			Address: byzKey.Address(),
  2667  			Power:   linotypes.TendermintValidatorPower,
  2668  		},
  2669  		PubKey:        byzKey,
  2670  		Username:      byz,
  2671  		ReceivedVotes: linotypes.NewCoinFromInt64(2000),
  2672  	}
  2673  
  2674  	absKey := secp256k1.GenPrivKey().PubKey()
  2675  	abs := linotypes.AccountKey("abs")
  2676  	absVal := model.Validator{
  2677  		ABCIValidator: abci.Validator{
  2678  			Address: absKey.Address(),
  2679  			Power:   linotypes.TendermintValidatorPower,
  2680  		},
  2681  		PubKey:        absKey,
  2682  		Username:      abs,
  2683  		ReceivedVotes: linotypes.NewCoinFromInt64(2000),
  2684  		AbsentCommit:  20000,
  2685  	}
  2686  	suite.vm.storage.SetValidator(suite.Ctx, byz, &byzVal)
  2687  	suite.vm.storage.SetValidator(suite.Ctx, abs, &absVal)
  2688  
  2689  	testCases := []struct {
  2690  		testName            string
  2691  		prevList            model.ValidatorList
  2692  		expectedList        model.ValidatorList
  2693  		byzantineValidators []abci.Evidence
  2694  	}{
  2695  		{
  2696  			testName: "fire validator",
  2697  			prevList: model.ValidatorList{
  2698  				Oncall: []linotypes.AccountKey{
  2699  					linotypes.AccountKey("test3"),
  2700  					linotypes.AccountKey("test2"),
  2701  					linotypes.AccountKey("abs"),
  2702  				},
  2703  				Standby: []linotypes.AccountKey{
  2704  					linotypes.AccountKey("test1"),
  2705  				},
  2706  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  2707  				LowestOncall:       linotypes.AccountKey("test2"),
  2708  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  2709  				LowestStandby:      linotypes.AccountKey("test1"),
  2710  			},
  2711  			expectedList: model.ValidatorList{
  2712  				Oncall: []linotypes.AccountKey{
  2713  					linotypes.AccountKey("test3"),
  2714  					linotypes.AccountKey("test2"),
  2715  					linotypes.AccountKey("test1"),
  2716  				},
  2717  				Jail: []linotypes.AccountKey{
  2718  					linotypes.AccountKey("abs"),
  2719  				},
  2720  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  2721  				LowestOncall:       linotypes.AccountKey("test1"),
  2722  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2723  				LowestStandby:      linotypes.AccountKey(""),
  2724  			},
  2725  			byzantineValidators: []abci.Evidence{},
  2726  		},
  2727  		{
  2728  			testName: "fire validator2",
  2729  			prevList: model.ValidatorList{
  2730  				Oncall: []linotypes.AccountKey{
  2731  					linotypes.AccountKey("test3"),
  2732  					linotypes.AccountKey("test2"),
  2733  					linotypes.AccountKey("byz"),
  2734  				},
  2735  				Standby: []linotypes.AccountKey{
  2736  					linotypes.AccountKey("test1"),
  2737  				},
  2738  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  2739  				LowestOncall:       linotypes.AccountKey("test2"),
  2740  				LowestStandbyVotes: linotypes.NewCoinFromInt64(100),
  2741  				LowestStandby:      linotypes.AccountKey("test1"),
  2742  			},
  2743  			expectedList: model.ValidatorList{
  2744  				Oncall: []linotypes.AccountKey{
  2745  					linotypes.AccountKey("test3"),
  2746  					linotypes.AccountKey("test2"),
  2747  					linotypes.AccountKey("test1"),
  2748  				},
  2749  				Jail: []linotypes.AccountKey{
  2750  					linotypes.AccountKey("byz"),
  2751  				},
  2752  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  2753  				LowestOncall:       linotypes.AccountKey("test1"),
  2754  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2755  				LowestStandby:      linotypes.AccountKey(""),
  2756  			},
  2757  			byzantineValidators: []abci.Evidence{
  2758  				{
  2759  					Validator: abci.Validator{
  2760  						Address: byzKey.Address(),
  2761  					},
  2762  				},
  2763  			},
  2764  		},
  2765  	}
  2766  
  2767  	for _, tc := range testCases {
  2768  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  2769  		err := suite.vm.fireIncompetentValidator(suite.Ctx, tc.byzantineValidators)
  2770  		suite.NoError(err)
  2771  		actualList := suite.vm.storage.GetValidatorList(suite.Ctx)
  2772  		suite.Equal(tc.expectedList, *actualList, "%s", tc.testName)
  2773  	}
  2774  }
  2775  
  2776  func (suite *ValidatorManagerTestSuite) TestOnStakeChange() {
  2777  	validators := map[linotypes.AccountKey]linotypes.Coin{
  2778  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100),
  2779  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200),
  2780  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  2781  	}
  2782  	suite.SetupValidatorAndVotes(validators)
  2783  
  2784  	testCases := []struct {
  2785  		testName           string
  2786  		prevValList        model.ValidatorList
  2787  		voter              linotypes.AccountKey
  2788  		prevElectionList   model.ElectionVoteList
  2789  		expectElectionList model.ElectionVoteList
  2790  		expectValAndVotes  map[linotypes.AccountKey]linotypes.Coin
  2791  		expectRes          sdk.Error
  2792  	}{
  2793  		{
  2794  			testName: "vote validator",
  2795  			prevValList: model.ValidatorList{
  2796  				Oncall: []linotypes.AccountKey{
  2797  					linotypes.AccountKey("test1"),
  2798  					linotypes.AccountKey("test2"),
  2799  					linotypes.AccountKey("test3"),
  2800  				},
  2801  				LowestOncallVotes:  linotypes.NewCoinFromInt64(100),
  2802  				LowestOncall:       linotypes.AccountKey("test1"),
  2803  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2804  				LowestStandby:      linotypes.AccountKey(""),
  2805  			},
  2806  			voter: linotypes.AccountKey("changedVoter"),
  2807  			prevElectionList: model.ElectionVoteList{
  2808  				ElectionVotes: []model.ElectionVote{
  2809  					{
  2810  						ValidatorName: linotypes.AccountKey("test1"),
  2811  						Vote:          linotypes.NewCoinFromInt64(100),
  2812  					},
  2813  					{
  2814  						ValidatorName: linotypes.AccountKey("test2"),
  2815  						Vote:          linotypes.NewCoinFromInt64(100),
  2816  					},
  2817  					{
  2818  						ValidatorName: linotypes.AccountKey("test3"),
  2819  						Vote:          linotypes.NewCoinFromInt64(100),
  2820  					},
  2821  				},
  2822  			},
  2823  			expectElectionList: model.ElectionVoteList{
  2824  				ElectionVotes: []model.ElectionVote{
  2825  					{
  2826  						ValidatorName: linotypes.AccountKey("test1"),
  2827  						Vote:          linotypes.NewCoinFromInt64(200),
  2828  					},
  2829  					{
  2830  						ValidatorName: linotypes.AccountKey("test2"),
  2831  						Vote:          linotypes.NewCoinFromInt64(200),
  2832  					},
  2833  					{
  2834  						ValidatorName: linotypes.AccountKey("test3"),
  2835  						Vote:          linotypes.NewCoinFromInt64(200),
  2836  					},
  2837  				},
  2838  			},
  2839  			expectValAndVotes: map[linotypes.AccountKey]linotypes.Coin{
  2840  				linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(200),
  2841  				linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(300),
  2842  				linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(400),
  2843  			},
  2844  			expectRes: nil,
  2845  		},
  2846  	}
  2847  	for _, tc := range testCases {
  2848  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevValList)
  2849  		suite.vm.storage.SetElectionVoteList(suite.Ctx, tc.voter, &tc.prevElectionList)
  2850  		err := suite.vm.onStakeChange(suite.Ctx, tc.voter)
  2851  		suite.Equal(tc.expectRes, err, "%s", tc.testName)
  2852  		lst := suite.vm.storage.GetElectionVoteList(suite.Ctx, tc.voter)
  2853  		suite.Equal(tc.expectElectionList, *lst, "%s", tc.testName)
  2854  		for k, v := range tc.expectValAndVotes {
  2855  			val, _ := suite.vm.storage.GetValidator(suite.Ctx, k)
  2856  			suite.Equal(v, val.ReceivedVotes, "%s", tc.testName)
  2857  		}
  2858  	}
  2859  }
  2860  
  2861  func (suite *ValidatorManagerTestSuite) TestRegisterValidator() {
  2862  	valKey := secp256k1.GenPrivKey().PubKey()
  2863  	val := linotypes.AccountKey("val")
  2864  
  2865  	testCases := []struct {
  2866  		testName   string
  2867  		username   linotypes.AccountKey
  2868  		link       string
  2869  		expectList model.ValidatorList
  2870  		expectVal  model.Validator
  2871  		expectRes  sdk.Error
  2872  	}{
  2873  		{
  2874  			testName: "vote validator",
  2875  			link:     "web1",
  2876  			expectList: model.ValidatorList{
  2877  				Oncall:             []linotypes.AccountKey{val},
  2878  				LowestOncallVotes:  linotypes.NewCoinFromInt64(300),
  2879  				LowestOncall:       linotypes.AccountKey("val"),
  2880  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  2881  				LowestStandby:      linotypes.AccountKey(""),
  2882  			},
  2883  			username: val,
  2884  			expectVal: model.Validator{
  2885  				ABCIValidator: abci.Validator{
  2886  					Address: valKey.Address(),
  2887  					Power:   1,
  2888  				},
  2889  				Link:          "web1",
  2890  				PubKey:        valKey,
  2891  				Username:      val,
  2892  				ReceivedVotes: linotypes.NewCoinFromInt64(300),
  2893  			},
  2894  			expectRes: nil,
  2895  		},
  2896  	}
  2897  	for _, tc := range testCases {
  2898  		err := suite.vm.RegisterValidator(suite.Ctx, tc.username, valKey, tc.link)
  2899  		suite.Equal(tc.expectRes, err, "%s", tc.testName)
  2900  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  2901  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  2902  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
  2903  		suite.NoError(err)
  2904  		suite.Equal(tc.expectVal, *val, "%s", tc.testName)
  2905  	}
  2906  }
  2907  
  2908  func (suite *ValidatorManagerTestSuite) TestRegisterFromRevoked() {
  2909  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("valx")).Return(linotypes.NewCoinFromInt64(1), nil).Maybe()
  2910  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("valy")).Return(linotypes.NewCoinFromInt64(2), nil).Maybe()
  2911  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("valz")).Return(linotypes.NewCoinFromInt64(3), nil).Maybe()
  2912  	suite.vote.On("GetVoterDuty", suite.Ctx, linotypes.AccountKey("valx")).Return(votetypes.DutyVoter, nil).Maybe()
  2913  	suite.vote.On("GetVoterDuty", suite.Ctx, linotypes.AccountKey("valy")).Return(votetypes.DutyVoter, nil).Maybe()
  2914  	suite.vote.On("GetVoterDuty", suite.Ctx, linotypes.AccountKey("valz")).Return(votetypes.DutyVoter, nil).Maybe()
  2915  	suite.vote.On("AssignDuty", suite.Ctx, linotypes.AccountKey("valx"), votetypes.DutyValidator,
  2916  		linotypes.NewCoinFromInt64(200000*linotypes.Decimals)).Return(nil).Maybe()
  2917  	suite.vote.On("AssignDuty", suite.Ctx, linotypes.AccountKey("valy"), votetypes.DutyValidator,
  2918  		linotypes.NewCoinFromInt64(200000*linotypes.Decimals)).Return(nil).Maybe()
  2919  	suite.vote.On("AssignDuty", suite.Ctx, linotypes.AccountKey("valz"), votetypes.DutyValidator,
  2920  		linotypes.NewCoinFromInt64(200000*linotypes.Decimals)).Return(nil).Maybe()
  2921  
  2922  	err := suite.vm.RegisterValidator(suite.Ctx, linotypes.AccountKey("valx"), secp256k1.GenPrivKey().PubKey(), "link")
  2923  	suite.NoError(err)
  2924  	err = suite.vm.RegisterValidator(suite.Ctx, linotypes.AccountKey("valy"), secp256k1.GenPrivKey().PubKey(), "link")
  2925  	suite.NoError(err)
  2926  	err = suite.vm.RegisterValidator(suite.Ctx, linotypes.AccountKey("valz"), secp256k1.GenPrivKey().PubKey(), "link")
  2927  	suite.NoError(err)
  2928  
  2929  	valKey := secp256k1.GenPrivKey().PubKey()
  2930  	valName := linotypes.AccountKey("val")
  2931  	val := model.Validator{
  2932  		ABCIValidator: abci.Validator{
  2933  			Address: valKey.Address(),
  2934  			Power:   linotypes.TendermintValidatorPower,
  2935  		},
  2936  		PubKey:        valKey,
  2937  		Username:      valName,
  2938  		ReceivedVotes: linotypes.NewCoinFromInt64(300),
  2939  		HasRevoked:    true,
  2940  	}
  2941  	suite.vm.storage.SetValidator(suite.Ctx, valName, &val)
  2942  	suite.vm.storage.SetElectionVoteList(suite.Ctx, valName, &model.ElectionVoteList{
  2943  		ElectionVotes: []model.ElectionVote{
  2944  			{
  2945  				ValidatorName: linotypes.AccountKey("val"),
  2946  				Vote:          linotypes.NewCoinFromInt64(300),
  2947  			},
  2948  		},
  2949  	})
  2950  
  2951  	testCases := []struct {
  2952  		testName   string
  2953  		username   linotypes.AccountKey
  2954  		link       string
  2955  		expectList model.ValidatorList
  2956  		expectVal  model.Validator
  2957  		expectRes  sdk.Error
  2958  	}{
  2959  		{
  2960  			testName: "register a revoked one",
  2961  			link:     "web1",
  2962  			expectList: model.ValidatorList{
  2963  				Oncall: []linotypes.AccountKey{
  2964  					linotypes.AccountKey("valy"),
  2965  					linotypes.AccountKey("valz"),
  2966  					linotypes.AccountKey("val"),
  2967  				},
  2968  				Standby: []linotypes.AccountKey{
  2969  					linotypes.AccountKey("valx"),
  2970  				},
  2971  				LowestOncallVotes:  linotypes.NewCoinFromInt64(2),
  2972  				LowestOncall:       linotypes.AccountKey("valy"),
  2973  				LowestStandbyVotes: linotypes.NewCoinFromInt64(1),
  2974  				LowestStandby:      linotypes.AccountKey("valx"),
  2975  			},
  2976  			username: valName,
  2977  			expectVal: model.Validator{
  2978  				ABCIValidator: abci.Validator{
  2979  					Address: valKey.Address(),
  2980  					Power:   1,
  2981  				},
  2982  				Link:          "web1",
  2983  				PubKey:        valKey,
  2984  				Username:      valName,
  2985  				ReceivedVotes: linotypes.NewCoinFromInt64(300),
  2986  			},
  2987  			expectRes: nil,
  2988  		},
  2989  	}
  2990  	for _, tc := range testCases {
  2991  		err := suite.vm.RegisterValidator(suite.Ctx, tc.username, valKey, tc.link)
  2992  		suite.Equal(tc.expectRes, err, "%s", tc.testName)
  2993  		lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  2994  		suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  2995  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
  2996  		suite.NoError(err)
  2997  		suite.Equal(tc.expectVal, *val, "%s", tc.testName)
  2998  	}
  2999  }
  3000  
  3001  func (suite *ValidatorManagerTestSuite) TestDistributeInflationToValidator() {
  3002  	suite.acc.On("GetPool", mock.Anything, linotypes.InflationValidatorPool).Return(
  3003  		(linotypes.NewCoinFromInt64(6)), nil).Once()
  3004  	for _, v := range []struct {
  3005  		validator linotypes.AccountKey
  3006  		amount    linotypes.Coin
  3007  	}{
  3008  		{
  3009  			linotypes.AccountKey("oncall1"),
  3010  			linotypes.NewCoinFromInt64(2),
  3011  		},
  3012  		{
  3013  			linotypes.AccountKey("oncall2"),
  3014  			linotypes.NewCoinFromInt64(2),
  3015  		},
  3016  		{
  3017  			linotypes.AccountKey("standby1"),
  3018  			linotypes.NewCoinFromInt64(1),
  3019  		},
  3020  		{
  3021  			linotypes.AccountKey("standby2"),
  3022  			linotypes.NewCoinFromInt64(1),
  3023  		},
  3024  	} {
  3025  		suite.acc.On(
  3026  			"MoveFromPool", mock.Anything, linotypes.InflationValidatorPool,
  3027  			linotypes.NewAccOrAddrFromAcc(v.validator), v.amount).Return(nil).Once()
  3028  	}
  3029  
  3030  	testCases := []struct {
  3031  		testName string
  3032  		prevList model.ValidatorList
  3033  	}{
  3034  		{
  3035  			testName: "distribute inflation",
  3036  			prevList: model.ValidatorList{
  3037  				Oncall: []linotypes.AccountKey{
  3038  					linotypes.AccountKey("oncall1"),
  3039  					linotypes.AccountKey("oncall2"),
  3040  				},
  3041  				Standby: []linotypes.AccountKey{
  3042  					linotypes.AccountKey("standby1"),
  3043  					linotypes.AccountKey("standby2"),
  3044  				},
  3045  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  3046  				LowestOncall:       linotypes.AccountKey(""),
  3047  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  3048  				LowestStandby:      linotypes.AccountKey(""),
  3049  			},
  3050  		},
  3051  	}
  3052  	for _, tc := range testCases {
  3053  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  3054  		err := suite.vm.DistributeInflationToValidator(suite.Ctx)
  3055  		suite.NoError(err)
  3056  		suite.acc.AssertExpectations(suite.T())
  3057  	}
  3058  }
  3059  
  3060  func (suite *ValidatorManagerTestSuite) TestRevokeValidator() {
  3061  	valKey := secp256k1.GenPrivKey().PubKey()
  3062  	val := linotypes.AccountKey("val")
  3063  	err := suite.vm.RegisterValidator(suite.Ctx, val, valKey, "link")
  3064  	suite.NoError(err)
  3065  
  3066  	testCases := []struct {
  3067  		testName   string
  3068  		username   linotypes.AccountKey
  3069  		expectList model.ValidatorList
  3070  		expectVal  model.Validator
  3071  		expectRes  sdk.Error
  3072  	}{
  3073  		{
  3074  			testName: "revoke validator",
  3075  			expectList: model.ValidatorList{
  3076  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  3077  				LowestOncall:       linotypes.AccountKey(""),
  3078  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  3079  				LowestStandby:      linotypes.AccountKey(""),
  3080  			},
  3081  			username: val,
  3082  			expectVal: model.Validator{
  3083  				ABCIValidator: abci.Validator{
  3084  					Address: valKey.Address(),
  3085  					Power:   1,
  3086  				},
  3087  				Link:          "link",
  3088  				PubKey:        valKey,
  3089  				Username:      val,
  3090  				ReceivedVotes: linotypes.NewCoinFromInt64(300),
  3091  				HasRevoked:    true,
  3092  			},
  3093  			expectRes: nil,
  3094  		},
  3095  		{
  3096  			testName: "revoke validator2",
  3097  			expectList: model.ValidatorList{
  3098  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  3099  				LowestOncall:       linotypes.AccountKey(""),
  3100  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  3101  				LowestStandby:      linotypes.AccountKey(""),
  3102  			},
  3103  			username: val,
  3104  			expectVal: model.Validator{
  3105  				ABCIValidator: abci.Validator{
  3106  					Address: valKey.Address(),
  3107  					Power:   1,
  3108  				},
  3109  				Link:          "link",
  3110  				PubKey:        valKey,
  3111  				Username:      val,
  3112  				ReceivedVotes: linotypes.NewCoinFromInt64(300),
  3113  				HasRevoked:    true,
  3114  			},
  3115  			expectRes: types.ErrInvalidValidator(),
  3116  		},
  3117  	}
  3118  	for _, tc := range testCases {
  3119  		err := suite.vm.RevokeValidator(suite.Ctx, tc.username)
  3120  		suite.Equal(tc.expectRes, err, "%s", tc.testName)
  3121  
  3122  		if tc.expectRes == nil {
  3123  			lst := suite.vm.storage.GetValidatorList(suite.Ctx)
  3124  			suite.Equal(tc.expectList, *lst, "%s", tc.testName)
  3125  			val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
  3126  			suite.NoError(err)
  3127  			suite.Equal(tc.expectVal, *val, "%s", tc.testName)
  3128  		}
  3129  
  3130  	}
  3131  }
  3132  
  3133  func (suite *ValidatorManagerTestSuite) TestGetCommittingValidatorsVotes() {
  3134  	validators := map[linotypes.AccountKey]linotypes.Coin{
  3135  		linotypes.AccountKey("test1"): linotypes.NewCoinFromInt64(100),
  3136  		linotypes.AccountKey("test2"): linotypes.NewCoinFromInt64(200),
  3137  		linotypes.AccountKey("test3"): linotypes.NewCoinFromInt64(300),
  3138  		linotypes.AccountKey("test4"): linotypes.NewCoinFromInt64(400),
  3139  		linotypes.AccountKey("test5"): linotypes.NewCoinFromInt64(500),
  3140  		linotypes.AccountKey("test6"): linotypes.NewCoinFromInt64(600),
  3141  		linotypes.AccountKey("test7"): linotypes.NewCoinFromInt64(700),
  3142  	}
  3143  	suite.SetupValidatorAndVotes(validators)
  3144  
  3145  	testCases := []struct {
  3146  		testName  string
  3147  		prevList  model.ValidatorList
  3148  		expectRes []model.ReceivedVotesStatus
  3149  	}{
  3150  		{
  3151  			testName: "get committing validators votes status",
  3152  			prevList: model.ValidatorList{
  3153  				Oncall: []linotypes.AccountKey{
  3154  					linotypes.AccountKey("test1"),
  3155  					linotypes.AccountKey("test2"),
  3156  					linotypes.AccountKey("test3"),
  3157  				},
  3158  				Standby: []linotypes.AccountKey{
  3159  					linotypes.AccountKey("test4"),
  3160  					linotypes.AccountKey("test5"),
  3161  					linotypes.AccountKey("test6"),
  3162  				},
  3163  				Candidates: []linotypes.AccountKey{
  3164  					linotypes.AccountKey("test7"),
  3165  				},
  3166  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  3167  				LowestOncall:       linotypes.AccountKey(""),
  3168  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  3169  				LowestStandby:      linotypes.AccountKey(""),
  3170  			},
  3171  			expectRes: []model.ReceivedVotesStatus{
  3172  				{
  3173  					ValidatorName: linotypes.AccountKey("test1"),
  3174  					ReceivedVotes: linotypes.NewCoinFromInt64(100),
  3175  				},
  3176  				{
  3177  					ValidatorName: linotypes.AccountKey("test2"),
  3178  					ReceivedVotes: linotypes.NewCoinFromInt64(200),
  3179  				},
  3180  				{
  3181  					ValidatorName: linotypes.AccountKey("test3"),
  3182  					ReceivedVotes: linotypes.NewCoinFromInt64(300),
  3183  				},
  3184  				{
  3185  					ValidatorName: linotypes.AccountKey("test4"),
  3186  					ReceivedVotes: linotypes.NewCoinFromInt64(400),
  3187  				},
  3188  				{
  3189  					ValidatorName: linotypes.AccountKey("test5"),
  3190  					ReceivedVotes: linotypes.NewCoinFromInt64(500),
  3191  				},
  3192  				{
  3193  					ValidatorName: linotypes.AccountKey("test6"),
  3194  					ReceivedVotes: linotypes.NewCoinFromInt64(600),
  3195  				},
  3196  			},
  3197  		},
  3198  	}
  3199  
  3200  	for _, tc := range testCases {
  3201  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  3202  		lst := suite.vm.GetCommittingValidatorVoteStatus(suite.Ctx)
  3203  		suite.Equal(tc.expectRes, lst, "%s", tc.testName)
  3204  	}
  3205  }
  3206  
  3207  func (suite *ValidatorManagerTestSuite) TestUpdateValidator() {
  3208  	valKey := secp256k1.GenPrivKey().PubKey()
  3209  	val := linotypes.AccountKey("val")
  3210  
  3211  	testCases := []struct {
  3212  		testName  string
  3213  		username  linotypes.AccountKey
  3214  		link      string
  3215  		expectVal model.Validator
  3216  	}{
  3217  		{
  3218  			testName: "update validator",
  3219  			link:     "web1111111",
  3220  			username: val,
  3221  			expectVal: model.Validator{
  3222  				ABCIValidator: abci.Validator{
  3223  					Address: valKey.Address(),
  3224  					Power:   1,
  3225  				},
  3226  				Link:          "web1111111",
  3227  				PubKey:        valKey,
  3228  				Username:      val,
  3229  				ReceivedVotes: linotypes.NewCoinFromInt64(300),
  3230  			},
  3231  		},
  3232  	}
  3233  	for _, tc := range testCases {
  3234  		err := suite.vm.RegisterValidator(suite.Ctx, tc.username, valKey, tc.link)
  3235  		suite.NoError(err)
  3236  
  3237  		err = suite.vm.UpdateValidator(suite.Ctx, tc.username, tc.link)
  3238  		suite.NoError(err)
  3239  
  3240  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
  3241  		suite.NoError(err)
  3242  		suite.Equal(tc.expectVal, *val, "%s", tc.testName)
  3243  	}
  3244  }
  3245  func (suite *ValidatorManagerTestSuite) TestPunishCommittingValidator() {
  3246  	suite.vote.On("GetLinoStake", suite.Ctx, linotypes.AccountKey("abs2")).Return(
  3247  		linotypes.NewCoinFromInt64(200000*linotypes.Decimals), nil).Maybe()
  3248  	suite.vote.On("SlashStake", suite.Ctx, linotypes.AccountKey("abs2"),
  3249  		linotypes.NewCoinFromInt64(200*linotypes.Decimals),
  3250  		linotypes.InflationValidatorPool).Return(
  3251  		linotypes.NewCoinFromInt64(200*linotypes.Decimals), nil).Maybe()
  3252  	absKey := secp256k1.GenPrivKey().PubKey()
  3253  	abs := linotypes.AccountKey("abs2")
  3254  	absVal := model.Validator{
  3255  		ABCIValidator: abci.Validator{
  3256  			Address: absKey.Address(),
  3257  			Power:   linotypes.TendermintValidatorPower,
  3258  		},
  3259  		PubKey:        absKey,
  3260  		Username:      abs,
  3261  		ReceivedVotes: linotypes.NewCoinFromInt64(2000),
  3262  		AbsentCommit:  1,
  3263  		NumSlash:      5,
  3264  	}
  3265  	suite.vm.storage.SetValidator(suite.Ctx, abs, &absVal)
  3266  
  3267  	testCases := []struct {
  3268  		testName     string
  3269  		prevList     model.ValidatorList
  3270  		expectedList model.ValidatorList
  3271  		expectedVal  model.Validator
  3272  		username     linotypes.AccountKey
  3273  	}{
  3274  		{
  3275  			testName: "punish validator",
  3276  			prevList: model.ValidatorList{
  3277  				Oncall: []linotypes.AccountKey{
  3278  					linotypes.AccountKey("abs2"),
  3279  				},
  3280  				LowestOncallVotes:  linotypes.NewCoinFromInt64(200),
  3281  				LowestOncall:       linotypes.AccountKey("abs2"),
  3282  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  3283  				LowestStandby:      linotypes.AccountKey(""),
  3284  			},
  3285  			expectedList: model.ValidatorList{
  3286  				Jail: []linotypes.AccountKey{
  3287  					linotypes.AccountKey("abs2"),
  3288  				},
  3289  				LowestOncallVotes:  linotypes.NewCoinFromInt64(0),
  3290  				LowestOncall:       linotypes.AccountKey(""),
  3291  				LowestStandbyVotes: linotypes.NewCoinFromInt64(0),
  3292  				LowestStandby:      linotypes.AccountKey(""),
  3293  			},
  3294  			expectedVal: model.Validator{
  3295  				ABCIValidator: abci.Validator{
  3296  					Address: absKey.Address(),
  3297  					Power:   0,
  3298  				},
  3299  				PubKey:        absKey,
  3300  				Username:      abs,
  3301  				ReceivedVotes: linotypes.NewCoinFromInt64(2000),
  3302  				AbsentCommit:  0,
  3303  				NumSlash:      0,
  3304  			},
  3305  			username: linotypes.AccountKey("abs2"),
  3306  		},
  3307  	}
  3308  
  3309  	for _, tc := range testCases {
  3310  		suite.vm.storage.SetValidatorList(suite.Ctx, &tc.prevList)
  3311  		err := suite.vm.PunishCommittingValidator(suite.Ctx, tc.username, linotypes.NewCoinFromInt64(200*linotypes.Decimals), linotypes.PunishNoPriceFed)
  3312  		suite.NoError(err)
  3313  		actualList := suite.vm.storage.GetValidatorList(suite.Ctx)
  3314  		suite.Equal(tc.expectedList, *actualList, "%s", tc.testName)
  3315  		val, err := suite.vm.storage.GetValidator(suite.Ctx, tc.username)
  3316  		suite.NoError(err)
  3317  		suite.Equal(tc.expectedVal, *val, "%s", tc.testName)
  3318  	}
  3319  }
  3320  
  3321  func (suite *ValidatorManagerTestSuite) TestGrantFreeVote() {
  3322  	prev := model.ValidatorList{
  3323  		Oncall: []linotypes.AccountKey{
  3324  			"validator2",
  3325  			"somebody",
  3326  			"hooli",
  3327  			"tidylabs-validator",
  3328  			"zondacryptocloaker",
  3329  			"cyphercore",
  3330  			"kwunyeung",
  3331  			"p2pvalidator",
  3332  			"boomergames",
  3333  			"stake.fish",
  3334  			"aliagaoglu",
  3335  			"lgo-supernova",
  3336  			"pineapplepizza",
  3337  			"ateam",
  3338  			"cheaky-validator",
  3339  			"nuked",
  3340  		},
  3341  		Standby: []linotypes.AccountKey{
  3342  			"certusone",
  3343  			"metacrypt",
  3344  			"castlenode-validator",
  3345  			"validator7",
  3346  			"cryptocloaker",
  3347  		},
  3348  		Candidates: []linotypes.AccountKey{
  3349  			"dlive-09156526",
  3350  			"vote4us",
  3351  			"happiness",
  3352  			"mr.k.validator",
  3353  			"nodeasy",
  3354  			"bneiluj",
  3355  			"validator1",
  3356  			"validator5",
  3357  			"validator3",
  3358  			"inheritance",
  3359  		},
  3360  
  3361  		LowestOncallVotes:  linotypes.NewCoinFromInt64(290932855056),
  3362  		LowestOncall:       linotypes.AccountKey("nuked"),
  3363  		LowestStandbyVotes: linotypes.NewCoinFromInt64(129751494333),
  3364  		LowestStandby:      linotypes.AccountKey("cryptocloaker"),
  3365  	}
  3366  	suite.vm.storage.SetValidatorList(suite.Ctx, &prev)
  3367  
  3368  	validators := map[linotypes.AccountKey]linotypes.Coin{
  3369  		"validator2":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3370  		"somebody":             linotypes.NewCoinFromInt64(100000 * linotypes.Decimals),
  3371  		"hooli":                linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3372  		"tidylabs-validator":   linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3373  		"zondacryptocloaker":   linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3374  		"cyphercore":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3375  		"kwunyeung":            linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3376  		"p2pvalidator":         linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3377  		"boomergames":          linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3378  		"stake.fish":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3379  		"aliagaoglu":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3380  		"lgo-supernova":        linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3381  		"pineapplepizza":       linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3382  		"ateam":                linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3383  		"cheaky-validator":     linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3384  		"nuked":                linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3385  		"certusone":            linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3386  		"metacrypt":            linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3387  		"castlenode-validator": linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3388  		"validator7":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3389  		"cryptocloaker":        linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3390  		"dlive-09156526":       linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3391  		"vote4us":              linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3392  		"happiness":            linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3393  		"mr.k.validator":       linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3394  		"nodeasy":              linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3395  		"bneiluj":              linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3396  		"validator1":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3397  		"validator5":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3398  		"validator3":           linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3399  		"inheritance":          linotypes.NewCoinFromInt64(100 * linotypes.Decimals),
  3400  	}
  3401  	suite.SetupValidatorAndVotes(validators)
  3402  	suite.vm.grantFreeVotes(suite.Ctx)
  3403  
  3404  	// list := suite.vm.storage.GetValidatorList(suite.Ctx)
  3405  	// fmt.Printf("%+v\n", list)
  3406  
  3407  	// updates, err := suite.vm.GetValidatorUpdates(suite.Ctx)
  3408  	// suite.Nil(err)
  3409  	// for _, v := range updates {
  3410  	// 	fmt.Println(v.Power)
  3411  	// }
  3412  }