You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
4.1 KiB

  1. package certifiers_test
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "github.com/stretchr/testify/require"
  6. "github.com/tendermint/tendermint/types"
  7. "github.com/tendermint/tendermint/certifiers"
  8. "github.com/tendermint/tendermint/certifiers/errors"
  9. )
  10. // TestDynamicCert just makes sure it still works like StaticCert
  11. func TestDynamicCert(t *testing.T) {
  12. // assert, require := assert.New(t), require.New(t)
  13. assert := assert.New(t)
  14. // require := require.New(t)
  15. keys := certifiers.GenValKeys(4)
  16. // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do!
  17. vals := keys.ToValidators(20, 10)
  18. // and a certifier based on our known set
  19. chainID := "test-dyno"
  20. cert := certifiers.NewDynamic(chainID, vals, 0)
  21. cases := []struct {
  22. keys certifiers.ValKeys
  23. vals *types.ValidatorSet
  24. height int
  25. first, last int // who actually signs
  26. proper bool // true -> expect no error
  27. changed bool // true -> expect validator change error
  28. }{
  29. // perfect, signed by everyone
  30. {keys, vals, 1, 0, len(keys), true, false},
  31. // skip little guy is okay
  32. {keys, vals, 2, 1, len(keys), true, false},
  33. // but not the big guy
  34. {keys, vals, 3, 0, len(keys) - 1, false, false},
  35. // even changing the power a little bit breaks the static validator
  36. // the sigs are enough, but the validator hash is unknown
  37. {keys, keys.ToValidators(20, 11), 4, 0, len(keys), false, true},
  38. }
  39. for _, tc := range cases {
  40. check := tc.keys.GenCommit(chainID, tc.height, nil, tc.vals,
  41. []byte("bar"), tc.first, tc.last)
  42. err := cert.Certify(check)
  43. if tc.proper {
  44. assert.Nil(err, "%+v", err)
  45. assert.Equal(cert.LastHeight(), tc.height)
  46. } else {
  47. assert.NotNil(err)
  48. if tc.changed {
  49. assert.True(errors.IsValidatorsChangedErr(err), "%+v", err)
  50. }
  51. }
  52. }
  53. }
  54. // TestDynamicUpdate makes sure we update safely and sanely
  55. func TestDynamicUpdate(t *testing.T) {
  56. assert, require := assert.New(t), require.New(t)
  57. chainID := "test-dyno-up"
  58. keys := certifiers.GenValKeys(5)
  59. vals := keys.ToValidators(20, 0)
  60. cert := certifiers.NewDynamic(chainID, vals, 40)
  61. // one valid block to give us a sense of time
  62. h := 100
  63. good := keys.GenCommit(chainID, h, nil, vals, []byte("foo"), 0, len(keys))
  64. err := cert.Certify(good)
  65. require.Nil(err, "%+v", err)
  66. // some new sets to try later
  67. keys2 := keys.Extend(2)
  68. keys3 := keys2.Extend(4)
  69. // we try to update with some blocks
  70. cases := []struct {
  71. keys certifiers.ValKeys
  72. vals *types.ValidatorSet
  73. height int
  74. first, last int // who actually signs
  75. proper bool // true -> expect no error
  76. changed bool // true -> expect too much change error
  77. }{
  78. // same validator set, well signed, of course it is okay
  79. {keys, vals, h + 10, 0, len(keys), true, false},
  80. // same validator set, poorly signed, fails
  81. {keys, vals, h + 20, 2, len(keys), false, false},
  82. // shift the power a little, works if properly signed
  83. {keys, keys.ToValidators(10, 0), h + 30, 1, len(keys), true, false},
  84. // but not on a poor signature
  85. {keys, keys.ToValidators(10, 0), h + 40, 2, len(keys), false, false},
  86. // and not if it was in the past
  87. {keys, keys.ToValidators(10, 0), h + 25, 0, len(keys), false, false},
  88. // let's try to adjust to a whole new validator set (we have 5/7 of the votes)
  89. {keys2, keys2.ToValidators(10, 0), h + 33, 0, len(keys2), true, false},
  90. // properly signed but too much change, not allowed (only 7/11 validators known)
  91. {keys3, keys3.ToValidators(10, 0), h + 50, 0, len(keys3), false, true},
  92. }
  93. for _, tc := range cases {
  94. fc := tc.keys.GenFullCommit(chainID, tc.height, nil, tc.vals,
  95. []byte("bar"), tc.first, tc.last)
  96. err := cert.Update(fc)
  97. if tc.proper {
  98. assert.Nil(err, "%d: %+v", tc.height, err)
  99. // we update last seen height
  100. assert.Equal(cert.LastHeight(), tc.height)
  101. // and we update the proper validators
  102. assert.EqualValues(fc.Header.ValidatorsHash, cert.Hash())
  103. } else {
  104. assert.NotNil(err, "%d", tc.height)
  105. // we don't update the height
  106. assert.NotEqual(cert.LastHeight(), tc.height)
  107. if tc.changed {
  108. assert.True(errors.IsTooMuchChangeErr(err),
  109. "%d: %+v", tc.height, err)
  110. }
  111. }
  112. }
  113. }