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