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