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.

429 lines
13 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math"
  6. "strings"
  7. "testing"
  8. "testing/quick"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/tendermint/tendermint/crypto"
  11. "github.com/tendermint/tendermint/crypto/ed25519"
  12. cmn "github.com/tendermint/tendermint/libs/common"
  13. tmtime "github.com/tendermint/tendermint/types/time"
  14. )
  15. func TestValidatorSetBasic(t *testing.T) {
  16. assert.Panics(t, func() { NewValidatorSet([]*Validator{}) })
  17. vset := NewValidatorSet(nil)
  18. assert.Panics(t, func() { vset.IncrementAccum(1) })
  19. assert.EqualValues(t, vset, vset.Copy())
  20. assert.False(t, vset.HasAddress([]byte("some val")))
  21. idx, val := vset.GetByAddress([]byte("some val"))
  22. assert.Equal(t, -1, idx)
  23. assert.Nil(t, val)
  24. addr, val := vset.GetByIndex(-100)
  25. assert.Nil(t, addr)
  26. assert.Nil(t, val)
  27. addr, val = vset.GetByIndex(0)
  28. assert.Nil(t, addr)
  29. assert.Nil(t, val)
  30. addr, val = vset.GetByIndex(100)
  31. assert.Nil(t, addr)
  32. assert.Nil(t, val)
  33. assert.Zero(t, vset.Size())
  34. assert.Equal(t, int64(0), vset.TotalVotingPower())
  35. assert.Nil(t, vset.GetProposer())
  36. assert.Nil(t, vset.Hash())
  37. // add
  38. val = randValidator_()
  39. assert.True(t, vset.Add(val))
  40. assert.True(t, vset.HasAddress(val.Address))
  41. idx, val2 := vset.GetByAddress(val.Address)
  42. assert.Equal(t, 0, idx)
  43. assert.Equal(t, val, val2)
  44. addr, val2 = vset.GetByIndex(0)
  45. assert.Equal(t, []byte(val.Address), addr)
  46. assert.Equal(t, val, val2)
  47. assert.Equal(t, 1, vset.Size())
  48. assert.Equal(t, val.VotingPower, vset.TotalVotingPower())
  49. assert.Equal(t, val, vset.GetProposer())
  50. assert.NotNil(t, vset.Hash())
  51. assert.NotPanics(t, func() { vset.IncrementAccum(1) })
  52. // update
  53. assert.False(t, vset.Update(randValidator_()))
  54. val.VotingPower = 100
  55. assert.True(t, vset.Update(val))
  56. // remove
  57. val2, removed := vset.Remove(randValidator_().Address)
  58. assert.Nil(t, val2)
  59. assert.False(t, removed)
  60. val2, removed = vset.Remove(val.Address)
  61. assert.Equal(t, val.Address, val2.Address)
  62. assert.True(t, removed)
  63. }
  64. func TestCopy(t *testing.T) {
  65. vset := randValidatorSet(10)
  66. vsetHash := vset.Hash()
  67. if len(vsetHash) == 0 {
  68. t.Fatalf("ValidatorSet had unexpected zero hash")
  69. }
  70. vsetCopy := vset.Copy()
  71. vsetCopyHash := vsetCopy.Hash()
  72. if !bytes.Equal(vsetHash, vsetCopyHash) {
  73. t.Fatalf("ValidatorSet copy had wrong hash. Orig: %X, Copy: %X", vsetHash, vsetCopyHash)
  74. }
  75. }
  76. func BenchmarkValidatorSetCopy(b *testing.B) {
  77. b.StopTimer()
  78. vset := NewValidatorSet([]*Validator{})
  79. for i := 0; i < 1000; i++ {
  80. privKey := ed25519.GenPrivKey()
  81. pubKey := privKey.PubKey()
  82. val := NewValidator(pubKey, 0)
  83. if !vset.Add(val) {
  84. panic("Failed to add validator")
  85. }
  86. }
  87. b.StartTimer()
  88. for i := 0; i < b.N; i++ {
  89. vset.Copy()
  90. }
  91. }
  92. //-------------------------------------------------------------------
  93. func TestProposerSelection1(t *testing.T) {
  94. vset := NewValidatorSet([]*Validator{
  95. newValidator([]byte("foo"), 1000),
  96. newValidator([]byte("bar"), 300),
  97. newValidator([]byte("baz"), 330),
  98. })
  99. proposers := []string{}
  100. for i := 0; i < 99; i++ {
  101. val := vset.GetProposer()
  102. proposers = append(proposers, string(val.Address))
  103. vset.IncrementAccum(1)
  104. }
  105. expected := `foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo foo baz bar foo foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo`
  106. if expected != strings.Join(proposers, " ") {
  107. t.Errorf("Expected sequence of proposers was\n%v\nbut got \n%v", expected, strings.Join(proposers, " "))
  108. }
  109. }
  110. func TestProposerSelection2(t *testing.T) {
  111. addr0 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  112. addr1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
  113. addr2 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
  114. // when all voting power is same, we go in order of addresses
  115. val0, val1, val2 := newValidator(addr0, 100), newValidator(addr1, 100), newValidator(addr2, 100)
  116. valList := []*Validator{val0, val1, val2}
  117. vals := NewValidatorSet(valList)
  118. for i := 0; i < len(valList)*5; i++ {
  119. ii := (i) % len(valList)
  120. prop := vals.GetProposer()
  121. if !bytes.Equal(prop.Address, valList[ii].Address) {
  122. t.Fatalf("(%d): Expected %X. Got %X", i, valList[ii].Address, prop.Address)
  123. }
  124. vals.IncrementAccum(1)
  125. }
  126. // One validator has more than the others, but not enough to propose twice in a row
  127. *val2 = *newValidator(addr2, 400)
  128. vals = NewValidatorSet(valList)
  129. // vals.IncrementAccum(1)
  130. prop := vals.GetProposer()
  131. if !bytes.Equal(prop.Address, addr2) {
  132. t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
  133. }
  134. vals.IncrementAccum(1)
  135. prop = vals.GetProposer()
  136. if !bytes.Equal(prop.Address, addr0) {
  137. t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
  138. }
  139. // One validator has more than the others, and enough to be proposer twice in a row
  140. *val2 = *newValidator(addr2, 401)
  141. vals = NewValidatorSet(valList)
  142. prop = vals.GetProposer()
  143. if !bytes.Equal(prop.Address, addr2) {
  144. t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
  145. }
  146. vals.IncrementAccum(1)
  147. prop = vals.GetProposer()
  148. if !bytes.Equal(prop.Address, addr2) {
  149. t.Fatalf("Expected address with highest voting power to be second proposer. Got %X", prop.Address)
  150. }
  151. vals.IncrementAccum(1)
  152. prop = vals.GetProposer()
  153. if !bytes.Equal(prop.Address, addr0) {
  154. t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
  155. }
  156. // each validator should be the proposer a proportional number of times
  157. val0, val1, val2 = newValidator(addr0, 4), newValidator(addr1, 5), newValidator(addr2, 3)
  158. valList = []*Validator{val0, val1, val2}
  159. propCount := make([]int, 3)
  160. vals = NewValidatorSet(valList)
  161. N := 1
  162. for i := 0; i < 120*N; i++ {
  163. prop := vals.GetProposer()
  164. ii := prop.Address[19]
  165. propCount[ii]++
  166. vals.IncrementAccum(1)
  167. }
  168. if propCount[0] != 40*N {
  169. t.Fatalf("Expected prop count for validator with 4/12 of voting power to be %d/%d. Got %d/%d", 40*N, 120*N, propCount[0], 120*N)
  170. }
  171. if propCount[1] != 50*N {
  172. t.Fatalf("Expected prop count for validator with 5/12 of voting power to be %d/%d. Got %d/%d", 50*N, 120*N, propCount[1], 120*N)
  173. }
  174. if propCount[2] != 30*N {
  175. t.Fatalf("Expected prop count for validator with 3/12 of voting power to be %d/%d. Got %d/%d", 30*N, 120*N, propCount[2], 120*N)
  176. }
  177. }
  178. func TestProposerSelection3(t *testing.T) {
  179. vset := NewValidatorSet([]*Validator{
  180. newValidator([]byte("a"), 1),
  181. newValidator([]byte("b"), 1),
  182. newValidator([]byte("c"), 1),
  183. newValidator([]byte("d"), 1),
  184. })
  185. proposerOrder := make([]*Validator, 4)
  186. for i := 0; i < 4; i++ {
  187. proposerOrder[i] = vset.GetProposer()
  188. vset.IncrementAccum(1)
  189. }
  190. // i for the loop
  191. // j for the times
  192. // we should go in order for ever, despite some IncrementAccums with times > 1
  193. var i, j int
  194. for ; i < 10000; i++ {
  195. got := vset.GetProposer().Address
  196. expected := proposerOrder[j%4].Address
  197. if !bytes.Equal(got, expected) {
  198. t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match expected proposer (%X) for (%d, %d)", got, expected, i, j))
  199. }
  200. // serialize, deserialize, check proposer
  201. b := vset.toBytes()
  202. vset.fromBytes(b)
  203. computed := vset.GetProposer() // findGetProposer()
  204. if i != 0 {
  205. if !bytes.Equal(got, computed.Address) {
  206. t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match computed proposer (%X) for (%d, %d)", got, computed.Address, i, j))
  207. }
  208. }
  209. // times is usually 1
  210. times := 1
  211. mod := (cmn.RandInt() % 5) + 1
  212. if cmn.RandInt()%mod > 0 {
  213. // sometimes its up to 5
  214. times = cmn.RandInt() % 5
  215. }
  216. vset.IncrementAccum(times)
  217. j += times
  218. }
  219. }
  220. func newValidator(address []byte, power int64) *Validator {
  221. return &Validator{Address: address, VotingPower: power}
  222. }
  223. func randPubKey() crypto.PubKey {
  224. var pubKey [32]byte
  225. copy(pubKey[:], cmn.RandBytes(32))
  226. return ed25519.PubKeyEd25519(pubKey)
  227. }
  228. func randValidator_() *Validator {
  229. val := NewValidator(randPubKey(), cmn.RandInt64())
  230. val.Accum = cmn.RandInt64()
  231. return val
  232. }
  233. func randValidatorSet(numValidators int) *ValidatorSet {
  234. validators := make([]*Validator, numValidators)
  235. for i := 0; i < numValidators; i++ {
  236. validators[i] = randValidator_()
  237. }
  238. return NewValidatorSet(validators)
  239. }
  240. func (valSet *ValidatorSet) toBytes() []byte {
  241. bz, err := cdc.MarshalBinaryLengthPrefixed(valSet)
  242. if err != nil {
  243. panic(err)
  244. }
  245. return bz
  246. }
  247. func (valSet *ValidatorSet) fromBytes(b []byte) {
  248. err := cdc.UnmarshalBinaryLengthPrefixed(b, &valSet)
  249. if err != nil {
  250. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  251. panic(err)
  252. }
  253. }
  254. //-------------------------------------------------------------------
  255. func TestValidatorSetTotalVotingPowerOverflows(t *testing.T) {
  256. vset := NewValidatorSet([]*Validator{
  257. {Address: []byte("a"), VotingPower: math.MaxInt64, Accum: 0},
  258. {Address: []byte("b"), VotingPower: math.MaxInt64, Accum: 0},
  259. {Address: []byte("c"), VotingPower: math.MaxInt64, Accum: 0},
  260. })
  261. assert.EqualValues(t, math.MaxInt64, vset.TotalVotingPower())
  262. }
  263. func TestValidatorSetIncrementAccumOverflows(t *testing.T) {
  264. // NewValidatorSet calls IncrementAccum(1)
  265. vset := NewValidatorSet([]*Validator{
  266. // too much voting power
  267. 0: {Address: []byte("a"), VotingPower: math.MaxInt64, Accum: 0},
  268. // too big accum
  269. 1: {Address: []byte("b"), VotingPower: 10, Accum: math.MaxInt64},
  270. // almost too big accum
  271. 2: {Address: []byte("c"), VotingPower: 10, Accum: math.MaxInt64 - 5},
  272. })
  273. assert.Equal(t, int64(0), vset.Validators[0].Accum, "0") // because we decrement val with most voting power
  274. assert.EqualValues(t, math.MaxInt64, vset.Validators[1].Accum, "1")
  275. assert.EqualValues(t, math.MaxInt64, vset.Validators[2].Accum, "2")
  276. }
  277. func TestValidatorSetIncrementAccumUnderflows(t *testing.T) {
  278. // NewValidatorSet calls IncrementAccum(1)
  279. vset := NewValidatorSet([]*Validator{
  280. 0: {Address: []byte("a"), VotingPower: math.MaxInt64, Accum: math.MinInt64},
  281. 1: {Address: []byte("b"), VotingPower: 1, Accum: math.MinInt64},
  282. })
  283. vset.IncrementAccum(5)
  284. assert.EqualValues(t, math.MinInt64, vset.Validators[0].Accum, "0")
  285. assert.EqualValues(t, math.MinInt64, vset.Validators[1].Accum, "1")
  286. }
  287. func TestSafeMul(t *testing.T) {
  288. f := func(a, b int64) bool {
  289. c, overflow := safeMul(a, b)
  290. return overflow || (!overflow && c == a*b)
  291. }
  292. if err := quick.Check(f, nil); err != nil {
  293. t.Error(err)
  294. }
  295. }
  296. func TestSafeAdd(t *testing.T) {
  297. f := func(a, b int64) bool {
  298. c, overflow := safeAdd(a, b)
  299. return overflow || (!overflow && c == a+b)
  300. }
  301. if err := quick.Check(f, nil); err != nil {
  302. t.Error(err)
  303. }
  304. }
  305. func TestSafeMulClip(t *testing.T) {
  306. assert.EqualValues(t, math.MaxInt64, safeMulClip(math.MinInt64, math.MinInt64))
  307. assert.EqualValues(t, math.MinInt64, safeMulClip(math.MaxInt64, math.MinInt64))
  308. assert.EqualValues(t, math.MinInt64, safeMulClip(math.MinInt64, math.MaxInt64))
  309. assert.EqualValues(t, math.MaxInt64, safeMulClip(math.MaxInt64, 2))
  310. }
  311. func TestSafeAddClip(t *testing.T) {
  312. assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, 10))
  313. assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, math.MaxInt64))
  314. assert.EqualValues(t, math.MinInt64, safeAddClip(math.MinInt64, -10))
  315. }
  316. func TestSafeSubClip(t *testing.T) {
  317. assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, 10))
  318. assert.EqualValues(t, 0, safeSubClip(math.MinInt64, math.MinInt64))
  319. assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, math.MaxInt64))
  320. assert.EqualValues(t, math.MaxInt64, safeSubClip(math.MaxInt64, -10))
  321. }
  322. //-------------------------------------------------------------------
  323. func TestValidatorSetVerifyCommit(t *testing.T) {
  324. privKey := ed25519.GenPrivKey()
  325. pubKey := privKey.PubKey()
  326. v1 := NewValidator(pubKey, 1000)
  327. vset := NewValidatorSet([]*Validator{v1})
  328. chainID := "mychainID"
  329. blockID := BlockID{Hash: []byte("hello")}
  330. height := int64(5)
  331. vote := &Vote{
  332. ValidatorAddress: v1.Address,
  333. ValidatorIndex: 0,
  334. Height: height,
  335. Round: 0,
  336. Timestamp: tmtime.Now(),
  337. Type: PrecommitType,
  338. BlockID: blockID,
  339. }
  340. sig, err := privKey.Sign(vote.SignBytes(chainID))
  341. assert.NoError(t, err)
  342. vote.Signature = sig
  343. commit := &Commit{
  344. BlockID: blockID,
  345. Precommits: []*Vote{vote},
  346. }
  347. badChainID := "notmychainID"
  348. badBlockID := BlockID{Hash: []byte("goodbye")}
  349. badHeight := height + 1
  350. badCommit := &Commit{
  351. BlockID: blockID,
  352. Precommits: []*Vote{nil},
  353. }
  354. // test some error cases
  355. // TODO: test more cases!
  356. cases := []struct {
  357. chainID string
  358. blockID BlockID
  359. height int64
  360. commit *Commit
  361. }{
  362. {badChainID, blockID, height, commit},
  363. {chainID, badBlockID, height, commit},
  364. {chainID, blockID, badHeight, commit},
  365. {chainID, blockID, height, badCommit},
  366. }
  367. for i, c := range cases {
  368. err := vset.VerifyCommit(c.chainID, c.blockID, c.height, c.commit)
  369. assert.NotNil(t, err, i)
  370. }
  371. // test a good one
  372. err = vset.VerifyCommit(chainID, blockID, height, commit)
  373. assert.Nil(t, err)
  374. }