github.com/badrootd/celestia-core@v0.0.0-20240305091328-aa4207a4b25d/state/state_test.go (about)

     1  package state_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math"
     7  	"math/big"
     8  	"os"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	dbm "github.com/cometbft/cometbft-db"
    15  
    16  	abci "github.com/badrootd/celestia-core/abci/types"
    17  	cfg "github.com/badrootd/celestia-core/config"
    18  	"github.com/badrootd/celestia-core/crypto/ed25519"
    19  	cryptoenc "github.com/badrootd/celestia-core/crypto/encoding"
    20  	cmtrand "github.com/badrootd/celestia-core/libs/rand"
    21  	cmtstate "github.com/badrootd/celestia-core/proto/tendermint/state"
    22  	sm "github.com/badrootd/celestia-core/state"
    23  	"github.com/badrootd/celestia-core/types"
    24  	"github.com/badrootd/celestia-core/version"
    25  )
    26  
    27  // setupTestCase does setup common to all test cases.
    28  func setupTestCase(t *testing.T) (func(t *testing.T), dbm.DB, sm.State) {
    29  	config := cfg.ResetTestRoot("state_")
    30  	dbType := dbm.BackendType(config.DBBackend)
    31  	stateDB, err := dbm.NewDB("state", dbType, config.DBDir())
    32  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
    33  		DiscardABCIResponses: false,
    34  	})
    35  	require.NoError(t, err)
    36  	state, err := stateStore.LoadFromDBOrGenesisFile(config.GenesisFile())
    37  	assert.NoError(t, err, "expected no error on LoadStateFromDBOrGenesisFile")
    38  	err = stateStore.Save(state)
    39  	require.NoError(t, err)
    40  
    41  	tearDown := func(t *testing.T) { os.RemoveAll(config.RootDir) }
    42  
    43  	return tearDown, stateDB, state
    44  }
    45  
    46  // TestStateCopy tests the correct copying behaviour of State.
    47  func TestStateCopy(t *testing.T) {
    48  	tearDown, _, state := setupTestCase(t)
    49  	defer tearDown(t)
    50  	assert := assert.New(t)
    51  
    52  	stateCopy := state.Copy()
    53  
    54  	assert.True(state.Equals(stateCopy),
    55  		fmt.Sprintf("expected state and its copy to be identical.\ngot: %v\nexpected: %v\n",
    56  			stateCopy, state))
    57  
    58  	stateCopy.LastBlockHeight++
    59  	stateCopy.LastValidators = state.Validators
    60  	assert.False(state.Equals(stateCopy), fmt.Sprintf(`expected states to be different. got same
    61          %v`, state))
    62  }
    63  
    64  // TestMakeGenesisStateNilValidators tests state's consistency when genesis file's validators field is nil.
    65  func TestMakeGenesisStateNilValidators(t *testing.T) {
    66  	doc := types.GenesisDoc{
    67  		ChainID:    "dummy",
    68  		Validators: nil,
    69  	}
    70  	require.Nil(t, doc.ValidateAndComplete())
    71  	state, err := sm.MakeGenesisState(&doc)
    72  	require.Nil(t, err)
    73  	require.Equal(t, 0, len(state.Validators.Validators))
    74  	require.Equal(t, 0, len(state.NextValidators.Validators))
    75  }
    76  
    77  func TestMakeGenesisStateSetsAppVersion(t *testing.T) {
    78  	cp := types.DefaultConsensusParams()
    79  	appVersion := uint64(5)
    80  	cp.Version.App = appVersion
    81  	doc := types.GenesisDoc{
    82  		ChainID:         "dummy",
    83  		ConsensusParams: cp,
    84  	}
    85  	require.Nil(t, doc.ValidateAndComplete())
    86  	state, err := sm.MakeGenesisState(&doc)
    87  	require.Nil(t, err)
    88  	require.Equal(t, appVersion, state.Version.Consensus.App)
    89  	require.Equal(t, version.BlockProtocol, state.Version.Consensus.Block)
    90  }
    91  
    92  // TestStateSaveLoad tests saving and loading State from a db.
    93  func TestStateSaveLoad(t *testing.T) {
    94  	tearDown, stateDB, state := setupTestCase(t)
    95  	defer tearDown(t)
    96  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
    97  		DiscardABCIResponses: false,
    98  	})
    99  	assert := assert.New(t)
   100  
   101  	state.LastBlockHeight++
   102  	state.LastValidators = state.Validators
   103  	err := stateStore.Save(state)
   104  	require.NoError(t, err)
   105  
   106  	loadedState, err := stateStore.Load()
   107  	require.NoError(t, err)
   108  	assert.True(state.Equals(loadedState),
   109  		fmt.Sprintf("expected state and its copy to be identical.\ngot: %v\nexpected: %v\n",
   110  			loadedState, state))
   111  }
   112  
   113  // TestABCIResponsesSaveLoad tests saving and loading ABCIResponses.
   114  func TestABCIResponsesSaveLoad1(t *testing.T) {
   115  	tearDown, stateDB, state := setupTestCase(t)
   116  	defer tearDown(t)
   117  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   118  		DiscardABCIResponses: false,
   119  	})
   120  	assert := assert.New(t)
   121  
   122  	state.LastBlockHeight++
   123  
   124  	// Build mock responses.
   125  	block := makeBlock(state, 2)
   126  
   127  	abciResponses := new(cmtstate.ABCIResponses)
   128  	dtxs := make([]*abci.ResponseDeliverTx, 2)
   129  	abciResponses.DeliverTxs = dtxs
   130  
   131  	abciResponses.DeliverTxs[0] = &abci.ResponseDeliverTx{Data: []byte("foo"), Events: nil}
   132  	abciResponses.DeliverTxs[1] = &abci.ResponseDeliverTx{Data: []byte("bar"), Log: "ok", Events: nil}
   133  	abciResponses.EndBlock = &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{
   134  		types.TM2PB.NewValidatorUpdate(ed25519.GenPrivKey().PubKey(), 10),
   135  	}}
   136  
   137  	err := stateStore.SaveABCIResponses(block.Height, abciResponses)
   138  	require.NoError(t, err)
   139  	loadedABCIResponses, err := stateStore.LoadABCIResponses(block.Height)
   140  	assert.Nil(err)
   141  	assert.Equal(abciResponses, loadedABCIResponses,
   142  		fmt.Sprintf("ABCIResponses don't match:\ngot:       %v\nexpected: %v\n",
   143  			loadedABCIResponses, abciResponses))
   144  }
   145  
   146  // TestResultsSaveLoad tests saving and loading ABCI results.
   147  func TestABCIResponsesSaveLoad2(t *testing.T) {
   148  	tearDown, stateDB, _ := setupTestCase(t)
   149  	defer tearDown(t)
   150  	assert := assert.New(t)
   151  
   152  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   153  		DiscardABCIResponses: false,
   154  	})
   155  
   156  	cases := [...]struct {
   157  		// Height is implied to equal index+2,
   158  		// as block 1 is created from genesis.
   159  		added    []*abci.ResponseDeliverTx
   160  		expected []*abci.ResponseDeliverTx
   161  	}{
   162  		0: {
   163  			nil,
   164  			nil,
   165  		},
   166  		1: {
   167  			[]*abci.ResponseDeliverTx{
   168  				{Code: 32, Data: []byte("Hello"), Log: "Huh?"},
   169  			},
   170  			[]*abci.ResponseDeliverTx{
   171  				{Code: 32, Data: []byte("Hello")},
   172  			}},
   173  		2: {
   174  			[]*abci.ResponseDeliverTx{
   175  				{Code: 383},
   176  				{
   177  					Data: []byte("Gotcha!"),
   178  					Events: []abci.Event{
   179  						{Type: "type1", Attributes: []abci.EventAttribute{{Key: "a", Value: "1"}}},
   180  						{Type: "type2", Attributes: []abci.EventAttribute{{Key: "build", Value: "stuff"}}},
   181  					},
   182  				},
   183  			},
   184  			[]*abci.ResponseDeliverTx{
   185  				{Code: 383, Data: nil},
   186  				{Code: 0, Data: []byte("Gotcha!"), Events: []abci.Event{
   187  					{Type: "type1", Attributes: []abci.EventAttribute{{Key: "a", Value: "1"}}},
   188  					{Type: "type2", Attributes: []abci.EventAttribute{{Key: "build", Value: "stuff"}}},
   189  				}},
   190  			}},
   191  		3: {
   192  			nil,
   193  			nil,
   194  		},
   195  		4: {
   196  			[]*abci.ResponseDeliverTx{nil},
   197  			nil,
   198  		},
   199  	}
   200  
   201  	// Query all before, this should return error.
   202  	for i := range cases {
   203  		h := int64(i + 1)
   204  		res, err := stateStore.LoadABCIResponses(h)
   205  		assert.Error(err, "%d: %#v", i, res)
   206  	}
   207  
   208  	// Add all cases.
   209  	for i, tc := range cases {
   210  		h := int64(i + 1) // last block height, one below what we save
   211  		responses := &cmtstate.ABCIResponses{
   212  			BeginBlock: &abci.ResponseBeginBlock{},
   213  			DeliverTxs: tc.added,
   214  			EndBlock:   &abci.ResponseEndBlock{},
   215  		}
   216  		err := stateStore.SaveABCIResponses(h, responses)
   217  		require.NoError(t, err)
   218  	}
   219  
   220  	// Query all before, should return expected value.
   221  	for i, tc := range cases {
   222  		h := int64(i + 1)
   223  		res, err := stateStore.LoadABCIResponses(h)
   224  		if assert.NoError(err, "%d", i) {
   225  			t.Log(res)
   226  			responses := &cmtstate.ABCIResponses{
   227  				BeginBlock: &abci.ResponseBeginBlock{},
   228  				DeliverTxs: tc.expected,
   229  				EndBlock:   &abci.ResponseEndBlock{},
   230  			}
   231  			assert.Equal(sm.ABCIResponsesResultsHash(responses), sm.ABCIResponsesResultsHash(res), "%d", i)
   232  		}
   233  	}
   234  }
   235  
   236  // TestValidatorSimpleSaveLoad tests saving and loading validators.
   237  func TestValidatorSimpleSaveLoad(t *testing.T) {
   238  	tearDown, stateDB, state := setupTestCase(t)
   239  	defer tearDown(t)
   240  	assert := assert.New(t)
   241  
   242  	statestore := sm.NewStore(stateDB, sm.StoreOptions{
   243  		DiscardABCIResponses: false,
   244  	})
   245  
   246  	// Can't load anything for height 0.
   247  	_, err := statestore.LoadValidators(0)
   248  	assert.IsType(sm.ErrNoValSetForHeight{}, err, "expected err at height 0")
   249  
   250  	// Should be able to load for height 1.
   251  	v, err := statestore.LoadValidators(1)
   252  	assert.Nil(err, "expected no err at height 1")
   253  	assert.Equal(v.Hash(), state.Validators.Hash(), "expected validator hashes to match")
   254  
   255  	// Should be able to load for height 2.
   256  	v, err = statestore.LoadValidators(2)
   257  	assert.Nil(err, "expected no err at height 2")
   258  	assert.Equal(v.Hash(), state.NextValidators.Hash(), "expected validator hashes to match")
   259  
   260  	// Increment height, save; should be able to load for next & next next height.
   261  	state.LastBlockHeight++
   262  	nextHeight := state.LastBlockHeight + 1
   263  	err = statestore.Save(state)
   264  	require.NoError(t, err)
   265  	vp0, err := statestore.LoadValidators(nextHeight + 0)
   266  	assert.Nil(err, "expected no err")
   267  	vp1, err := statestore.LoadValidators(nextHeight + 1)
   268  	assert.Nil(err, "expected no err")
   269  	assert.Equal(vp0.Hash(), state.Validators.Hash(), "expected validator hashes to match")
   270  	assert.Equal(vp1.Hash(), state.NextValidators.Hash(), "expected next validator hashes to match")
   271  }
   272  
   273  // TestValidatorChangesSaveLoad tests saving and loading a validator set with changes.
   274  func TestOneValidatorChangesSaveLoad(t *testing.T) {
   275  	tearDown, stateDB, state := setupTestCase(t)
   276  	defer tearDown(t)
   277  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   278  		DiscardABCIResponses: false,
   279  	})
   280  
   281  	// Change vals at these heights.
   282  	changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20}
   283  	N := len(changeHeights)
   284  
   285  	// Build the validator history by running updateState
   286  	// with the right validator set for each height.
   287  	highestHeight := changeHeights[N-1] + 5
   288  	changeIndex := 0
   289  	_, val := state.Validators.GetByIndex(0)
   290  	power := val.VotingPower
   291  	var err error
   292  	var validatorUpdates []*types.Validator
   293  	for i := int64(1); i < highestHeight; i++ {
   294  		// When we get to a change height, use the next pubkey.
   295  		if changeIndex < len(changeHeights) && i == changeHeights[changeIndex] {
   296  			changeIndex++
   297  			power++
   298  		}
   299  		header, blockID, responses := makeHeaderPartsResponsesValPowerChange(state, power)
   300  		validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
   301  		require.NoError(t, err)
   302  		state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates)
   303  		require.NoError(t, err)
   304  		err := stateStore.Save(state)
   305  		require.NoError(t, err)
   306  	}
   307  
   308  	// On each height change, increment the power by one.
   309  	testCases := make([]int64, highestHeight)
   310  	changeIndex = 0
   311  	power = val.VotingPower
   312  	for i := int64(1); i < highestHeight+1; i++ {
   313  		// We get to the height after a change height use the next pubkey (note
   314  		// our counter starts at 0 this time).
   315  		if changeIndex < len(changeHeights) && i == changeHeights[changeIndex]+1 {
   316  			changeIndex++
   317  			power++
   318  		}
   319  		testCases[i-1] = power
   320  	}
   321  
   322  	for i, power := range testCases {
   323  		v, err := stateStore.LoadValidators(int64(i + 1 + 1)) // +1 because vset changes delayed by 1 block.
   324  		assert.Nil(t, err, fmt.Sprintf("expected no err at height %d", i))
   325  		assert.Equal(t, v.Size(), 1, "validator set size is greater than 1: %d", v.Size())
   326  		_, val := v.GetByIndex(0)
   327  
   328  		assert.Equal(t, val.VotingPower, power, fmt.Sprintf(`unexpected powerat
   329                  height %d`, i))
   330  	}
   331  }
   332  
   333  func TestProposerFrequency(t *testing.T) {
   334  
   335  	// some explicit test cases
   336  	testCases := []struct {
   337  		powers []int64
   338  	}{
   339  		// 2 vals
   340  		{[]int64{1, 1}},
   341  		{[]int64{1, 2}},
   342  		{[]int64{1, 100}},
   343  		{[]int64{5, 5}},
   344  		{[]int64{5, 100}},
   345  		{[]int64{50, 50}},
   346  		{[]int64{50, 100}},
   347  		{[]int64{1, 1000}},
   348  
   349  		// 3 vals
   350  		{[]int64{1, 1, 1}},
   351  		{[]int64{1, 2, 3}},
   352  		{[]int64{1, 2, 3}},
   353  		{[]int64{1, 1, 10}},
   354  		{[]int64{1, 1, 100}},
   355  		{[]int64{1, 10, 100}},
   356  		{[]int64{1, 1, 1000}},
   357  		{[]int64{1, 10, 1000}},
   358  		{[]int64{1, 100, 1000}},
   359  
   360  		// 4 vals
   361  		{[]int64{1, 1, 1, 1}},
   362  		{[]int64{1, 2, 3, 4}},
   363  		{[]int64{1, 1, 1, 10}},
   364  		{[]int64{1, 1, 1, 100}},
   365  		{[]int64{1, 1, 1, 1000}},
   366  		{[]int64{1, 1, 10, 100}},
   367  		{[]int64{1, 1, 10, 1000}},
   368  		{[]int64{1, 1, 100, 1000}},
   369  		{[]int64{1, 10, 100, 1000}},
   370  	}
   371  
   372  	for caseNum, testCase := range testCases {
   373  		// run each case 5 times to sample different
   374  		// initial priorities
   375  		for i := 0; i < 5; i++ {
   376  			valSet := genValSetWithPowers(testCase.powers)
   377  			testProposerFreq(t, caseNum, valSet)
   378  		}
   379  	}
   380  
   381  	// some random test cases with up to 100 validators
   382  	maxVals := 100
   383  	maxPower := 1000
   384  	nTestCases := 5
   385  	for i := 0; i < nTestCases; i++ {
   386  		N := cmtrand.Int()%maxVals + 1
   387  		vals := make([]*types.Validator, N)
   388  		totalVotePower := int64(0)
   389  		for j := 0; j < N; j++ {
   390  			// make sure votePower > 0
   391  			votePower := int64(cmtrand.Int()%maxPower) + 1
   392  			totalVotePower += votePower
   393  			privVal := types.NewMockPV()
   394  			pubKey, err := privVal.GetPubKey()
   395  			require.NoError(t, err)
   396  			val := types.NewValidator(pubKey, votePower)
   397  			val.ProposerPriority = cmtrand.Int64()
   398  			vals[j] = val
   399  		}
   400  		valSet := types.NewValidatorSet(vals)
   401  		valSet.RescalePriorities(totalVotePower)
   402  		testProposerFreq(t, i, valSet)
   403  	}
   404  }
   405  
   406  // new val set with given powers and random initial priorities
   407  func genValSetWithPowers(powers []int64) *types.ValidatorSet {
   408  	size := len(powers)
   409  	vals := make([]*types.Validator, size)
   410  	totalVotePower := int64(0)
   411  	for i := 0; i < size; i++ {
   412  		totalVotePower += powers[i]
   413  		val := types.NewValidator(ed25519.GenPrivKey().PubKey(), powers[i])
   414  		val.ProposerPriority = cmtrand.Int64()
   415  		vals[i] = val
   416  	}
   417  	valSet := types.NewValidatorSet(vals)
   418  	valSet.RescalePriorities(totalVotePower)
   419  	return valSet
   420  }
   421  
   422  // test a proposer appears as frequently as expected
   423  func testProposerFreq(t *testing.T, caseNum int, valSet *types.ValidatorSet) {
   424  	N := valSet.Size()
   425  	totalPower := valSet.TotalVotingPower()
   426  
   427  	// run the proposer selection and track frequencies
   428  	runMult := 1
   429  	runs := int(totalPower) * runMult
   430  	freqs := make([]int, N)
   431  	for i := 0; i < runs; i++ {
   432  		prop := valSet.GetProposer()
   433  		idx, _ := valSet.GetByAddress(prop.Address)
   434  		freqs[idx]++
   435  		valSet.IncrementProposerPriority(1)
   436  	}
   437  
   438  	// assert frequencies match expected (max off by 1)
   439  	for i, freq := range freqs {
   440  		_, val := valSet.GetByIndex(int32(i))
   441  		expectFreq := int(val.VotingPower) * runMult
   442  		gotFreq := freq
   443  		abs := int(math.Abs(float64(expectFreq - gotFreq)))
   444  
   445  		// max bound on expected vs seen freq was proven
   446  		// to be 1 for the 2 validator case in
   447  		// https://github.com/cwgoes/tm-proposer-idris
   448  		// and inferred to generalize to N-1
   449  		bound := N - 1
   450  		require.True(
   451  			t,
   452  			abs <= bound,
   453  			fmt.Sprintf("Case %d val %d (%d): got %d, expected %d", caseNum, i, N, gotFreq, expectFreq),
   454  		)
   455  	}
   456  }
   457  
   458  // TestProposerPriorityDoesNotGetResetToZero assert that we preserve accum when calling updateState
   459  // see https://github.com/cometbft/cometbft/issues/2718
   460  func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) {
   461  	tearDown, _, state := setupTestCase(t)
   462  	defer tearDown(t)
   463  	val1VotingPower := int64(10)
   464  	val1PubKey := ed25519.GenPrivKey().PubKey()
   465  	val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower}
   466  
   467  	state.Validators = types.NewValidatorSet([]*types.Validator{val1})
   468  	state.NextValidators = state.Validators
   469  
   470  	// NewValidatorSet calls IncrementProposerPriority but uses on a copy of val1
   471  	assert.EqualValues(t, 0, val1.ProposerPriority)
   472  
   473  	block := makeBlock(state, state.LastBlockHeight+1)
   474  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   475  	abciResponses := &cmtstate.ABCIResponses{
   476  		BeginBlock: &abci.ResponseBeginBlock{},
   477  		EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   478  	}
   479  	validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   480  	require.NoError(t, err)
   481  	updatedState, err := sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
   482  	assert.NoError(t, err)
   483  	curTotal := val1VotingPower
   484  	// one increment step and one validator: 0 + power - total_power == 0
   485  	assert.Equal(t, 0+val1VotingPower-curTotal, updatedState.NextValidators.Validators[0].ProposerPriority)
   486  
   487  	// add a validator
   488  	val2PubKey := ed25519.GenPrivKey().PubKey()
   489  	val2VotingPower := int64(100)
   490  	fvp, err := cryptoenc.PubKeyToProto(val2PubKey)
   491  	require.NoError(t, err)
   492  
   493  	updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val2VotingPower}
   494  	validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
   495  	assert.NoError(t, err)
   496  	updatedState2, err := sm.UpdateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
   497  	assert.NoError(t, err)
   498  
   499  	require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
   500  	_, updatedVal1 := updatedState2.NextValidators.GetByAddress(val1PubKey.Address())
   501  	_, addedVal2 := updatedState2.NextValidators.GetByAddress(val2PubKey.Address())
   502  
   503  	// adding a validator should not lead to a ProposerPriority equal to zero (unless the combination of averaging and
   504  	// incrementing would cause so; which is not the case here)
   505  	// Steps from adding new validator:
   506  	// 0 - val1 prio is 0, TVP after add:
   507  	wantVal1Prio := int64(0)
   508  	totalPowerAfter := val1VotingPower + val2VotingPower
   509  	// 1. Add - Val2 should be initially added with (-123) =>
   510  	wantVal2Prio := -(totalPowerAfter + (totalPowerAfter >> 3))
   511  	// 2. Scale - noop
   512  	// 3. Center - with avg, resulting val2:-61, val1:62
   513  	avg := big.NewInt(0).Add(big.NewInt(wantVal1Prio), big.NewInt(wantVal2Prio))
   514  	avg.Div(avg, big.NewInt(2))
   515  	wantVal2Prio -= avg.Int64() // -61
   516  	wantVal1Prio -= avg.Int64() // 62
   517  
   518  	// 4. Steps from IncrementProposerPriority
   519  	wantVal1Prio += val1VotingPower // 72
   520  	wantVal2Prio += val2VotingPower // 39
   521  	wantVal1Prio -= totalPowerAfter // -38 as val1 is proposer
   522  
   523  	assert.Equal(t, wantVal1Prio, updatedVal1.ProposerPriority)
   524  	assert.Equal(t, wantVal2Prio, addedVal2.ProposerPriority)
   525  
   526  	// Updating a validator does not reset the ProposerPriority to zero:
   527  	// 1. Add - Val2 VotingPower change to 1 =>
   528  	updatedVotingPowVal2 := int64(1)
   529  	updateVal := abci.ValidatorUpdate{PubKey: fvp, Power: updatedVotingPowVal2}
   530  	validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateVal})
   531  	assert.NoError(t, err)
   532  
   533  	// this will cause the diff of priorities (77)
   534  	// to be larger than threshold == 2*totalVotingPower (22):
   535  	updatedState3, err := sm.UpdateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates)
   536  	assert.NoError(t, err)
   537  
   538  	require.Equal(t, len(updatedState3.NextValidators.Validators), 2)
   539  	_, prevVal1 := updatedState3.Validators.GetByAddress(val1PubKey.Address())
   540  	_, prevVal2 := updatedState3.Validators.GetByAddress(val2PubKey.Address())
   541  	_, updatedVal1 = updatedState3.NextValidators.GetByAddress(val1PubKey.Address())
   542  	_, updatedVal2 := updatedState3.NextValidators.GetByAddress(val2PubKey.Address())
   543  
   544  	// 2. Scale
   545  	// old prios: v1(10):-38, v2(1):39
   546  	wantVal1Prio = prevVal1.ProposerPriority
   547  	wantVal2Prio = prevVal2.ProposerPriority
   548  	// scale to diffMax = 22 = 2 * tvp, diff=39-(-38)=77
   549  	// new totalPower
   550  	totalPower := updatedVal1.VotingPower + updatedVal2.VotingPower
   551  	dist := wantVal2Prio - wantVal1Prio
   552  	// ratio := (dist + 2*totalPower - 1) / 2*totalPower = 98/22 = 4
   553  	ratio := (dist + 2*totalPower - 1) / (2 * totalPower)
   554  	// v1(10):-38/4, v2(1):39/4
   555  	wantVal1Prio /= ratio // -9
   556  	wantVal2Prio /= ratio // 9
   557  
   558  	// 3. Center - noop
   559  	// 4. IncrementProposerPriority() ->
   560  	// v1(10):-9+10, v2(1):9+1 -> v2 proposer so subsract tvp(11)
   561  	// v1(10):1, v2(1):-1
   562  	wantVal2Prio += updatedVal2.VotingPower // 10 -> prop
   563  	wantVal1Prio += updatedVal1.VotingPower // 1
   564  	wantVal2Prio -= totalPower              // -1
   565  
   566  	assert.Equal(t, wantVal2Prio, updatedVal2.ProposerPriority)
   567  	assert.Equal(t, wantVal1Prio, updatedVal1.ProposerPriority)
   568  }
   569  
   570  func TestProposerPriorityProposerAlternates(t *testing.T) {
   571  	// Regression test that would fail if the inner workings of
   572  	// IncrementProposerPriority change.
   573  	// Additionally, make sure that same power validators alternate if both
   574  	// have the same voting power (and the 2nd was added later).
   575  	tearDown, _, state := setupTestCase(t)
   576  	defer tearDown(t)
   577  	val1VotingPower := int64(10)
   578  	val1PubKey := ed25519.GenPrivKey().PubKey()
   579  	val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower}
   580  
   581  	// reset state validators to above validator
   582  	state.Validators = types.NewValidatorSet([]*types.Validator{val1})
   583  	state.NextValidators = state.Validators
   584  	// we only have one validator:
   585  	assert.Equal(t, val1PubKey.Address(), state.Validators.Proposer.Address)
   586  
   587  	block := makeBlock(state, state.LastBlockHeight+1)
   588  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   589  	// no updates:
   590  	abciResponses := &cmtstate.ABCIResponses{
   591  		BeginBlock: &abci.ResponseBeginBlock{},
   592  		EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   593  	}
   594  	validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   595  	require.NoError(t, err)
   596  
   597  	updatedState, err := sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
   598  	assert.NoError(t, err)
   599  
   600  	// 0 + 10 (initial prio) - 10 (avg) - 10 (mostest - total) = -10
   601  	totalPower := val1VotingPower
   602  	wantVal1Prio := 0 + val1VotingPower - totalPower
   603  	assert.Equal(t, wantVal1Prio, updatedState.NextValidators.Validators[0].ProposerPriority)
   604  	assert.Equal(t, val1PubKey.Address(), updatedState.NextValidators.Proposer.Address)
   605  
   606  	// add a validator with the same voting power as the first
   607  	val2PubKey := ed25519.GenPrivKey().PubKey()
   608  	fvp, err := cryptoenc.PubKeyToProto(val2PubKey)
   609  	require.NoError(t, err)
   610  	updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val1VotingPower}
   611  	validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal})
   612  	assert.NoError(t, err)
   613  
   614  	updatedState2, err := sm.UpdateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
   615  	assert.NoError(t, err)
   616  
   617  	require.Equal(t, len(updatedState2.NextValidators.Validators), 2)
   618  	assert.Equal(t, updatedState2.Validators, updatedState.NextValidators)
   619  
   620  	// val1 will still be proposer as val2 just got added:
   621  	assert.Equal(t, val1PubKey.Address(), updatedState.NextValidators.Proposer.Address)
   622  	assert.Equal(t, updatedState2.Validators.Proposer.Address, updatedState2.NextValidators.Proposer.Address)
   623  	assert.Equal(t, updatedState2.Validators.Proposer.Address, val1PubKey.Address())
   624  	assert.Equal(t, updatedState2.NextValidators.Proposer.Address, val1PubKey.Address())
   625  
   626  	_, updatedVal1 := updatedState2.NextValidators.GetByAddress(val1PubKey.Address())
   627  	_, oldVal1 := updatedState2.Validators.GetByAddress(val1PubKey.Address())
   628  	_, updatedVal2 := updatedState2.NextValidators.GetByAddress(val2PubKey.Address())
   629  
   630  	// 1. Add
   631  	val2VotingPower := val1VotingPower
   632  	totalPower = val1VotingPower + val2VotingPower           // 20
   633  	v2PrioWhenAddedVal2 := -(totalPower + (totalPower >> 3)) // -22
   634  	// 2. Scale - noop
   635  	// 3. Center
   636  	avgSum := big.NewInt(0).Add(big.NewInt(v2PrioWhenAddedVal2), big.NewInt(oldVal1.ProposerPriority))
   637  	avg := avgSum.Div(avgSum, big.NewInt(2))                   // -11
   638  	expectedVal2Prio := v2PrioWhenAddedVal2 - avg.Int64()      // -11
   639  	expectedVal1Prio := oldVal1.ProposerPriority - avg.Int64() // 11
   640  	// 4. Increment
   641  	expectedVal2Prio += val2VotingPower // -11 + 10 = -1
   642  	expectedVal1Prio += val1VotingPower // 11 + 10 == 21
   643  	expectedVal1Prio -= totalPower      // 1, val1 proposer
   644  
   645  	assert.EqualValues(t, expectedVal1Prio, updatedVal1.ProposerPriority)
   646  	assert.EqualValues(
   647  		t,
   648  		expectedVal2Prio,
   649  		updatedVal2.ProposerPriority,
   650  		"unexpected proposer priority for validator: %v",
   651  		updatedVal2,
   652  	)
   653  
   654  	validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   655  	require.NoError(t, err)
   656  
   657  	updatedState3, err := sm.UpdateState(updatedState2, blockID, &block.Header, abciResponses, validatorUpdates)
   658  	assert.NoError(t, err)
   659  
   660  	assert.Equal(t, updatedState3.Validators.Proposer.Address, updatedState3.NextValidators.Proposer.Address)
   661  
   662  	assert.Equal(t, updatedState3.Validators, updatedState2.NextValidators)
   663  	_, updatedVal1 = updatedState3.NextValidators.GetByAddress(val1PubKey.Address())
   664  	_, updatedVal2 = updatedState3.NextValidators.GetByAddress(val2PubKey.Address())
   665  
   666  	// val1 will still be proposer:
   667  	assert.Equal(t, val1PubKey.Address(), updatedState3.NextValidators.Proposer.Address)
   668  
   669  	// check if expected proposer prio is matched:
   670  	// Increment
   671  	expectedVal2Prio2 := expectedVal2Prio + val2VotingPower // -1 + 10 = 9
   672  	expectedVal1Prio2 := expectedVal1Prio + val1VotingPower // 1 + 10 == 11
   673  	expectedVal1Prio2 -= totalPower                         // -9, val1 proposer
   674  
   675  	assert.EqualValues(
   676  		t,
   677  		expectedVal1Prio2,
   678  		updatedVal1.ProposerPriority,
   679  		"unexpected proposer priority for validator: %v",
   680  		updatedVal2,
   681  	)
   682  	assert.EqualValues(
   683  		t,
   684  		expectedVal2Prio2,
   685  		updatedVal2.ProposerPriority,
   686  		"unexpected proposer priority for validator: %v",
   687  		updatedVal2,
   688  	)
   689  
   690  	// no changes in voting power and both validators have same voting power
   691  	// -> proposers should alternate:
   692  	oldState := updatedState3
   693  	abciResponses = &cmtstate.ABCIResponses{
   694  		BeginBlock: &abci.ResponseBeginBlock{},
   695  		EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   696  	}
   697  	validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   698  	require.NoError(t, err)
   699  
   700  	oldState, err = sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
   701  	assert.NoError(t, err)
   702  	expectedVal1Prio2 = 1
   703  	expectedVal2Prio2 = -1
   704  	expectedVal1Prio = -9
   705  	expectedVal2Prio = 9
   706  
   707  	for i := 0; i < 1000; i++ {
   708  		// no validator updates:
   709  		abciResponses := &cmtstate.ABCIResponses{
   710  			BeginBlock: &abci.ResponseBeginBlock{},
   711  			EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   712  		}
   713  		validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   714  		require.NoError(t, err)
   715  
   716  		updatedState, err := sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
   717  		assert.NoError(t, err)
   718  		// alternate (and cyclic priorities):
   719  		assert.NotEqual(
   720  			t,
   721  			updatedState.Validators.Proposer.Address,
   722  			updatedState.NextValidators.Proposer.Address,
   723  			"iter: %v",
   724  			i,
   725  		)
   726  		assert.Equal(t, oldState.Validators.Proposer.Address, updatedState.NextValidators.Proposer.Address, "iter: %v", i)
   727  
   728  		_, updatedVal1 = updatedState.NextValidators.GetByAddress(val1PubKey.Address())
   729  		_, updatedVal2 = updatedState.NextValidators.GetByAddress(val2PubKey.Address())
   730  
   731  		if i%2 == 0 {
   732  			assert.Equal(t, updatedState.Validators.Proposer.Address, val2PubKey.Address())
   733  			assert.Equal(t, expectedVal1Prio, updatedVal1.ProposerPriority) // -19
   734  			assert.Equal(t, expectedVal2Prio, updatedVal2.ProposerPriority) // 0
   735  		} else {
   736  			assert.Equal(t, updatedState.Validators.Proposer.Address, val1PubKey.Address())
   737  			assert.Equal(t, expectedVal1Prio2, updatedVal1.ProposerPriority) // -9
   738  			assert.Equal(t, expectedVal2Prio2, updatedVal2.ProposerPriority) // -10
   739  		}
   740  		// update for next iteration:
   741  		oldState = updatedState
   742  	}
   743  }
   744  
   745  func TestLargeGenesisValidator(t *testing.T) {
   746  	tearDown, _, state := setupTestCase(t)
   747  	defer tearDown(t)
   748  
   749  	genesisVotingPower := types.MaxTotalVotingPower / 1000
   750  	genesisPubKey := ed25519.GenPrivKey().PubKey()
   751  	// fmt.Println("genesis addr: ", genesisPubKey.Address())
   752  	genesisVal := &types.Validator{
   753  		Address:     genesisPubKey.Address(),
   754  		PubKey:      genesisPubKey,
   755  		VotingPower: genesisVotingPower,
   756  	}
   757  	// reset state validators to above validator
   758  	state.Validators = types.NewValidatorSet([]*types.Validator{genesisVal})
   759  	state.NextValidators = state.Validators
   760  	require.True(t, len(state.Validators.Validators) == 1)
   761  
   762  	// update state a few times with no validator updates
   763  	// asserts that the single validator's ProposerPrio stays the same
   764  	oldState := state
   765  	for i := 0; i < 10; i++ {
   766  		// no updates:
   767  		abciResponses := &cmtstate.ABCIResponses{
   768  			BeginBlock: &abci.ResponseBeginBlock{},
   769  			EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   770  		}
   771  		validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   772  		require.NoError(t, err)
   773  
   774  		block := makeBlock(oldState, oldState.LastBlockHeight+1)
   775  		blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   776  
   777  		updatedState, err := sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
   778  		require.NoError(t, err)
   779  		// no changes in voting power (ProposerPrio += VotingPower == Voting in 1st round; than shiftByAvg == 0,
   780  		// than -Total == -Voting)
   781  		// -> no change in ProposerPrio (stays zero):
   782  		assert.EqualValues(t, oldState.NextValidators, updatedState.NextValidators)
   783  		assert.EqualValues(t, 0, updatedState.NextValidators.Proposer.ProposerPriority)
   784  
   785  		oldState = updatedState
   786  	}
   787  	// add another validator, do a few iterations (create blocks),
   788  	// add more validators with same voting power as the 2nd
   789  	// let the genesis validator "unbond",
   790  	// see how long it takes until the effect wears off and both begin to alternate
   791  	// see: https://github.com/cometbft/cometbft/issues/2960
   792  	firstAddedValPubKey := ed25519.GenPrivKey().PubKey()
   793  	firstAddedValVotingPower := int64(10)
   794  	fvp, err := cryptoenc.PubKeyToProto(firstAddedValPubKey)
   795  	require.NoError(t, err)
   796  	firstAddedVal := abci.ValidatorUpdate{PubKey: fvp, Power: firstAddedValVotingPower}
   797  	validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal})
   798  	assert.NoError(t, err)
   799  	abciResponses := &cmtstate.ABCIResponses{
   800  		BeginBlock: &abci.ResponseBeginBlock{},
   801  		EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{firstAddedVal}},
   802  	}
   803  	block := makeBlock(oldState, oldState.LastBlockHeight+1)
   804  	blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   805  	updatedState, err := sm.UpdateState(oldState, blockID, &block.Header, abciResponses, validatorUpdates)
   806  	require.NoError(t, err)
   807  
   808  	lastState := updatedState
   809  	for i := 0; i < 200; i++ {
   810  		// no updates:
   811  		abciResponses := &cmtstate.ABCIResponses{
   812  			BeginBlock: &abci.ResponseBeginBlock{},
   813  			EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   814  		}
   815  		validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   816  		require.NoError(t, err)
   817  
   818  		block := makeBlock(lastState, lastState.LastBlockHeight+1)
   819  		blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   820  
   821  		updatedStateInner, err := sm.UpdateState(lastState, blockID, &block.Header, abciResponses, validatorUpdates)
   822  		require.NoError(t, err)
   823  		lastState = updatedStateInner
   824  	}
   825  	// set state to last state of above iteration
   826  	state = lastState
   827  
   828  	// set oldState to state before above iteration
   829  	oldState = updatedState
   830  	_, oldGenesisVal := oldState.NextValidators.GetByAddress(genesisVal.Address)
   831  	_, newGenesisVal := state.NextValidators.GetByAddress(genesisVal.Address)
   832  	_, addedOldVal := oldState.NextValidators.GetByAddress(firstAddedValPubKey.Address())
   833  	_, addedNewVal := state.NextValidators.GetByAddress(firstAddedValPubKey.Address())
   834  	// expect large negative proposer priority for both (genesis validator decreased, 2nd validator increased):
   835  	assert.True(t, oldGenesisVal.ProposerPriority > newGenesisVal.ProposerPriority)
   836  	assert.True(t, addedOldVal.ProposerPriority < addedNewVal.ProposerPriority)
   837  
   838  	// add 10 validators with the same voting power as the one added directly after genesis:
   839  	for i := 0; i < 10; i++ {
   840  		addedPubKey := ed25519.GenPrivKey().PubKey()
   841  		ap, err := cryptoenc.PubKeyToProto(addedPubKey)
   842  		require.NoError(t, err)
   843  		addedVal := abci.ValidatorUpdate{PubKey: ap, Power: firstAddedValVotingPower}
   844  		validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal})
   845  		assert.NoError(t, err)
   846  
   847  		abciResponses := &cmtstate.ABCIResponses{
   848  			BeginBlock: &abci.ResponseBeginBlock{},
   849  			EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{addedVal}},
   850  		}
   851  		block := makeBlock(oldState, oldState.LastBlockHeight+1)
   852  		blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   853  		state, err = sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
   854  		require.NoError(t, err)
   855  	}
   856  	require.Equal(t, 10+2, len(state.NextValidators.Validators))
   857  
   858  	// remove genesis validator:
   859  	gp, err := cryptoenc.PubKeyToProto(genesisPubKey)
   860  	require.NoError(t, err)
   861  	removeGenesisVal := abci.ValidatorUpdate{PubKey: gp, Power: 0}
   862  	abciResponses = &cmtstate.ABCIResponses{
   863  		BeginBlock: &abci.ResponseBeginBlock{},
   864  		EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}},
   865  	}
   866  	block = makeBlock(oldState, oldState.LastBlockHeight+1)
   867  	blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   868  	validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   869  	require.NoError(t, err)
   870  	updatedState, err = sm.UpdateState(state, blockID, &block.Header, abciResponses, validatorUpdates)
   871  	require.NoError(t, err)
   872  	// only the first added val (not the genesis val) should be left
   873  	assert.Equal(t, 11, len(updatedState.NextValidators.Validators))
   874  
   875  	// call update state until the effect for the 3rd added validator
   876  	// being proposer for a long time after the genesis validator left wears off:
   877  	curState := updatedState
   878  	count := 0
   879  	isProposerUnchanged := true
   880  	for isProposerUnchanged {
   881  		abciResponses := &cmtstate.ABCIResponses{
   882  			BeginBlock: &abci.ResponseBeginBlock{},
   883  			EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   884  		}
   885  		validatorUpdates, err = types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   886  		require.NoError(t, err)
   887  		block = makeBlock(curState, curState.LastBlockHeight+1)
   888  		blockID = types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   889  		curState, err = sm.UpdateState(curState, blockID, &block.Header, abciResponses, validatorUpdates)
   890  		require.NoError(t, err)
   891  		if !bytes.Equal(curState.Validators.Proposer.Address, curState.NextValidators.Proposer.Address) {
   892  			isProposerUnchanged = false
   893  		}
   894  		count++
   895  	}
   896  	updatedState = curState
   897  	// the proposer changes after this number of blocks
   898  	firstProposerChangeExpectedAfter := 1
   899  	assert.Equal(t, firstProposerChangeExpectedAfter, count)
   900  	// store proposers here to see if we see them again in the same order:
   901  	numVals := len(updatedState.Validators.Validators)
   902  	proposers := make([]*types.Validator, numVals)
   903  	for i := 0; i < 100; i++ {
   904  		// no updates:
   905  		abciResponses := &cmtstate.ABCIResponses{
   906  			BeginBlock: &abci.ResponseBeginBlock{},
   907  			EndBlock:   &abci.ResponseEndBlock{ValidatorUpdates: nil},
   908  		}
   909  		validatorUpdates, err := types.PB2TM.ValidatorUpdates(abciResponses.EndBlock.ValidatorUpdates)
   910  		require.NoError(t, err)
   911  
   912  		block := makeBlock(updatedState, updatedState.LastBlockHeight+1)
   913  		blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: block.MakePartSet(testPartSize).Header()}
   914  
   915  		updatedState, err = sm.UpdateState(updatedState, blockID, &block.Header, abciResponses, validatorUpdates)
   916  		require.NoError(t, err)
   917  		if i > numVals { // expect proposers to cycle through after the first iteration (of numVals blocks):
   918  			if proposers[i%numVals] == nil {
   919  				proposers[i%numVals] = updatedState.NextValidators.Proposer
   920  			} else {
   921  				assert.Equal(t, proposers[i%numVals], updatedState.NextValidators.Proposer)
   922  			}
   923  		}
   924  	}
   925  }
   926  
   927  func TestStoreLoadValidatorsIncrementsProposerPriority(t *testing.T) {
   928  	const valSetSize = 2
   929  	tearDown, stateDB, state := setupTestCase(t)
   930  	t.Cleanup(func() { tearDown(t) })
   931  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   932  		DiscardABCIResponses: false,
   933  	})
   934  	state.Validators = genValSet(valSetSize)
   935  	state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
   936  	err := stateStore.Save(state)
   937  	require.NoError(t, err)
   938  
   939  	nextHeight := state.LastBlockHeight + 1
   940  
   941  	v0, err := stateStore.LoadValidators(nextHeight)
   942  	assert.Nil(t, err)
   943  	acc0 := v0.Validators[0].ProposerPriority
   944  
   945  	v1, err := stateStore.LoadValidators(nextHeight + 1)
   946  	assert.Nil(t, err)
   947  	acc1 := v1.Validators[0].ProposerPriority
   948  
   949  	assert.NotEqual(t, acc1, acc0, "expected ProposerPriority value to change between heights")
   950  }
   951  
   952  // TestValidatorChangesSaveLoad tests saving and loading a validator set with
   953  // changes.
   954  func TestManyValidatorChangesSaveLoad(t *testing.T) {
   955  	const valSetSize = 7
   956  	tearDown, stateDB, state := setupTestCase(t)
   957  	defer tearDown(t)
   958  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   959  		DiscardABCIResponses: false,
   960  	})
   961  	require.Equal(t, int64(0), state.LastBlockHeight)
   962  	state.Validators = genValSet(valSetSize)
   963  	state.NextValidators = state.Validators.CopyIncrementProposerPriority(1)
   964  	err := stateStore.Save(state)
   965  	require.NoError(t, err)
   966  
   967  	_, valOld := state.Validators.GetByIndex(0)
   968  	var pubkeyOld = valOld.PubKey
   969  	pubkey := ed25519.GenPrivKey().PubKey()
   970  
   971  	// Swap the first validator with a new one (validator set size stays the same).
   972  	header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(state, pubkey)
   973  
   974  	// Save state etc.
   975  	var validatorUpdates []*types.Validator
   976  	validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
   977  	require.NoError(t, err)
   978  	state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates)
   979  	require.Nil(t, err)
   980  	nextHeight := state.LastBlockHeight + 1
   981  	err = stateStore.Save(state)
   982  	require.NoError(t, err)
   983  
   984  	// Load nextheight, it should be the oldpubkey.
   985  	v0, err := stateStore.LoadValidators(nextHeight)
   986  	assert.Nil(t, err)
   987  	assert.Equal(t, valSetSize, v0.Size())
   988  	index, val := v0.GetByAddress(pubkeyOld.Address())
   989  	assert.NotNil(t, val)
   990  	if index < 0 {
   991  		t.Fatal("expected to find old validator")
   992  	}
   993  
   994  	// Load nextheight+1, it should be the new pubkey.
   995  	v1, err := stateStore.LoadValidators(nextHeight + 1)
   996  	assert.Nil(t, err)
   997  	assert.Equal(t, valSetSize, v1.Size())
   998  	index, val = v1.GetByAddress(pubkey.Address())
   999  	assert.NotNil(t, val)
  1000  	if index < 0 {
  1001  		t.Fatal("expected to find newly added validator")
  1002  	}
  1003  }
  1004  
  1005  func TestStateMakeBlock(t *testing.T) {
  1006  	tearDown, _, state := setupTestCase(t)
  1007  	defer tearDown(t)
  1008  
  1009  	proposerAddress := state.Validators.GetProposer().Address
  1010  	stateVersion := state.Version.Consensus
  1011  	block := makeBlock(state, 2)
  1012  
  1013  	// test we set some fields
  1014  	assert.Equal(t, stateVersion, block.Version)
  1015  	assert.Equal(t, proposerAddress, block.ProposerAddress)
  1016  }
  1017  
  1018  // TestConsensusParamsChangesSaveLoad tests saving and loading consensus params
  1019  // with changes.
  1020  func TestConsensusParamsChangesSaveLoad(t *testing.T) {
  1021  	tearDown, stateDB, state := setupTestCase(t)
  1022  	defer tearDown(t)
  1023  
  1024  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
  1025  		DiscardABCIResponses: false,
  1026  	})
  1027  
  1028  	// Change vals at these heights.
  1029  	changeHeights := []int64{1, 2, 4, 5, 10, 15, 16, 17, 20}
  1030  	N := len(changeHeights)
  1031  
  1032  	// Each valset is just one validator.
  1033  	// create list of them.
  1034  	params := make([]types.ConsensusParams, N+1)
  1035  	params[0] = state.ConsensusParams
  1036  	for i := 1; i < N+1; i++ {
  1037  		params[i] = *types.DefaultConsensusParams()
  1038  		params[i].Block.MaxBytes += int64(i)
  1039  
  1040  	}
  1041  
  1042  	// Build the params history by running updateState
  1043  	// with the right params set for each height.
  1044  	highestHeight := changeHeights[N-1] + 5
  1045  	changeIndex := 0
  1046  	cp := params[changeIndex]
  1047  	var err error
  1048  	var validatorUpdates []*types.Validator
  1049  	for i := int64(1); i < highestHeight; i++ {
  1050  		// When we get to a change height, use the next params.
  1051  		if changeIndex < len(changeHeights) && i == changeHeights[changeIndex] {
  1052  			changeIndex++
  1053  			cp = params[changeIndex]
  1054  		}
  1055  		header, blockID, responses := makeHeaderPartsResponsesParams(state, cp.ToProto())
  1056  		validatorUpdates, err = types.PB2TM.ValidatorUpdates(responses.EndBlock.ValidatorUpdates)
  1057  		require.NoError(t, err)
  1058  		state, err = sm.UpdateState(state, blockID, &header, responses, validatorUpdates)
  1059  
  1060  		require.Nil(t, err)
  1061  		err := stateStore.Save(state)
  1062  		require.NoError(t, err)
  1063  	}
  1064  
  1065  	// Make all the test cases by using the same params until after the change.
  1066  	testCases := make([]paramsChangeTestCase, highestHeight)
  1067  	changeIndex = 0
  1068  	cp = params[changeIndex]
  1069  	for i := int64(1); i < highestHeight+1; i++ {
  1070  		// We get to the height after a change height use the next pubkey (note
  1071  		// our counter starts at 0 this time).
  1072  		if changeIndex < len(changeHeights) && i == changeHeights[changeIndex]+1 {
  1073  			changeIndex++
  1074  			cp = params[changeIndex]
  1075  		}
  1076  		testCases[i-1] = paramsChangeTestCase{i, cp}
  1077  	}
  1078  
  1079  	for _, testCase := range testCases {
  1080  		p, err := stateStore.LoadConsensusParams(testCase.height)
  1081  		assert.Nil(t, err, fmt.Sprintf("expected no err at height %d", testCase.height))
  1082  		assert.EqualValues(t, testCase.params, p, fmt.Sprintf(`unexpected consensus params at
  1083                  height %d`, testCase.height))
  1084  	}
  1085  }
  1086  
  1087  func TestStateProto(t *testing.T) {
  1088  	tearDown, _, state := setupTestCase(t)
  1089  	defer tearDown(t)
  1090  
  1091  	tc := []struct {
  1092  		testName string
  1093  		state    *sm.State
  1094  		expPass1 bool
  1095  		expPass2 bool
  1096  	}{
  1097  		{"empty state", &sm.State{}, true, false},
  1098  		{"nil failure state", nil, false, false},
  1099  		{"success state", &state, true, true},
  1100  	}
  1101  
  1102  	for _, tt := range tc {
  1103  		tt := tt
  1104  		pbs, err := tt.state.ToProto()
  1105  		if !tt.expPass1 {
  1106  			assert.Error(t, err)
  1107  		} else {
  1108  			assert.NoError(t, err, tt.testName)
  1109  		}
  1110  
  1111  		smt, err := sm.FromProto(pbs)
  1112  		if tt.expPass2 {
  1113  			require.NoError(t, err, tt.testName)
  1114  			require.Equal(t, tt.state, smt, tt.testName)
  1115  		} else {
  1116  			require.Error(t, err, tt.testName)
  1117  		}
  1118  	}
  1119  }