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