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