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.

227 lines
6.9 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package types
  2. import (
  3. "bytes"
  4. "strings"
  5. "testing"
  6. "github.com/tendermint/go-crypto"
  7. "github.com/tendermint/go-wire"
  8. cmn "github.com/tendermint/tmlibs/common"
  9. )
  10. func randPubKey() crypto.PubKey {
  11. var pubKey [32]byte
  12. copy(pubKey[:], cmn.RandBytes(32))
  13. return crypto.PubKeyEd25519(pubKey).Wrap()
  14. }
  15. func randValidator_() *Validator {
  16. val := NewValidator(randPubKey(), cmn.RandInt64())
  17. val.Accum = cmn.RandInt64()
  18. return val
  19. }
  20. func randValidatorSet(numValidators int) *ValidatorSet {
  21. validators := make([]*Validator, numValidators)
  22. for i := 0; i < numValidators; i++ {
  23. validators[i] = randValidator_()
  24. }
  25. return NewValidatorSet(validators)
  26. }
  27. func TestCopy(t *testing.T) {
  28. vset := randValidatorSet(10)
  29. vsetHash := vset.Hash()
  30. if len(vsetHash) == 0 {
  31. t.Fatalf("ValidatorSet had unexpected zero hash")
  32. }
  33. vsetCopy := vset.Copy()
  34. vsetCopyHash := vsetCopy.Hash()
  35. if !bytes.Equal(vsetHash, vsetCopyHash) {
  36. t.Fatalf("ValidatorSet copy had wrong hash. Orig: %X, Copy: %X", vsetHash, vsetCopyHash)
  37. }
  38. }
  39. func TestProposerSelection1(t *testing.T) {
  40. vset := NewValidatorSet([]*Validator{
  41. newValidator([]byte("foo"), 1000),
  42. newValidator([]byte("bar"), 300),
  43. newValidator([]byte("baz"), 330),
  44. })
  45. proposers := []string{}
  46. for i := 0; i < 99; i++ {
  47. val := vset.GetProposer()
  48. proposers = append(proposers, string(val.Address))
  49. vset.IncrementAccum(1)
  50. }
  51. 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`
  52. if expected != strings.Join(proposers, " ") {
  53. t.Errorf("Expected sequence of proposers was\n%v\nbut got \n%v", expected, strings.Join(proposers, " "))
  54. }
  55. }
  56. func newValidator(address []byte, power int64) *Validator {
  57. return &Validator{Address: address, VotingPower: power}
  58. }
  59. func TestProposerSelection2(t *testing.T) {
  60. addr0 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  61. addr1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
  62. addr2 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
  63. // when all voting power is same, we go in order of addresses
  64. val0, val1, val2 := newValidator(addr0, 100), newValidator(addr1, 100), newValidator(addr2, 100)
  65. valList := []*Validator{val0, val1, val2}
  66. vals := NewValidatorSet(valList)
  67. for i := 0; i < len(valList)*5; i++ {
  68. ii := (i) % len(valList)
  69. prop := vals.GetProposer()
  70. if !bytes.Equal(prop.Address, valList[ii].Address) {
  71. t.Fatalf("(%d): Expected %X. Got %X", i, valList[ii].Address, prop.Address)
  72. }
  73. vals.IncrementAccum(1)
  74. }
  75. // One validator has more than the others, but not enough to propose twice in a row
  76. *val2 = *newValidator(addr2, 400)
  77. vals = NewValidatorSet(valList)
  78. // vals.IncrementAccum(1)
  79. prop := vals.GetProposer()
  80. if !bytes.Equal(prop.Address, addr2) {
  81. t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
  82. }
  83. vals.IncrementAccum(1)
  84. prop = vals.GetProposer()
  85. if !bytes.Equal(prop.Address, addr0) {
  86. t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
  87. }
  88. // One validator has more than the others, and enough to be proposer twice in a row
  89. *val2 = *newValidator(addr2, 401)
  90. vals = NewValidatorSet(valList)
  91. prop = vals.GetProposer()
  92. if !bytes.Equal(prop.Address, addr2) {
  93. t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
  94. }
  95. vals.IncrementAccum(1)
  96. prop = vals.GetProposer()
  97. if !bytes.Equal(prop.Address, addr2) {
  98. t.Fatalf("Expected address with highest voting power to be second proposer. Got %X", prop.Address)
  99. }
  100. vals.IncrementAccum(1)
  101. prop = vals.GetProposer()
  102. if !bytes.Equal(prop.Address, addr0) {
  103. t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
  104. }
  105. // each validator should be the proposer a proportional number of times
  106. val0, val1, val2 = newValidator(addr0, 4), newValidator(addr1, 5), newValidator(addr2, 3)
  107. valList = []*Validator{val0, val1, val2}
  108. propCount := make([]int, 3)
  109. vals = NewValidatorSet(valList)
  110. N := 1
  111. for i := 0; i < 120*N; i++ {
  112. prop := vals.GetProposer()
  113. ii := prop.Address[19]
  114. propCount[ii] += 1
  115. vals.IncrementAccum(1)
  116. }
  117. if propCount[0] != 40*N {
  118. 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)
  119. }
  120. if propCount[1] != 50*N {
  121. 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)
  122. }
  123. if propCount[2] != 30*N {
  124. 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)
  125. }
  126. }
  127. func TestProposerSelection3(t *testing.T) {
  128. vset := NewValidatorSet([]*Validator{
  129. newValidator([]byte("a"), 1),
  130. newValidator([]byte("b"), 1),
  131. newValidator([]byte("c"), 1),
  132. newValidator([]byte("d"), 1),
  133. })
  134. proposerOrder := make([]*Validator, 4)
  135. for i := 0; i < 4; i++ {
  136. proposerOrder[i] = vset.GetProposer()
  137. vset.IncrementAccum(1)
  138. }
  139. // i for the loop
  140. // j for the times
  141. // we should go in order for ever, despite some IncrementAccums with times > 1
  142. var i, j int
  143. for ; i < 10000; i++ {
  144. got := vset.GetProposer().Address
  145. expected := proposerOrder[j%4].Address
  146. if !bytes.Equal(got, expected) {
  147. t.Fatalf(cmn.Fmt("vset.Proposer (%X) does not match expected proposer (%X) for (%d, %d)", got, expected, i, j))
  148. }
  149. // serialize, deserialize, check proposer
  150. b := vset.toBytes()
  151. vset.fromBytes(b)
  152. computed := vset.GetProposer() // findGetProposer()
  153. if i != 0 {
  154. if !bytes.Equal(got, computed.Address) {
  155. t.Fatalf(cmn.Fmt("vset.Proposer (%X) does not match computed proposer (%X) for (%d, %d)", got, computed.Address, i, j))
  156. }
  157. }
  158. // times is usually 1
  159. times := 1
  160. mod := (cmn.RandInt() % 5) + 1
  161. if cmn.RandInt()%mod > 0 {
  162. // sometimes its up to 5
  163. times = cmn.RandInt() % 5
  164. }
  165. vset.IncrementAccum(times)
  166. j += times
  167. }
  168. }
  169. func BenchmarkValidatorSetCopy(b *testing.B) {
  170. b.StopTimer()
  171. vset := NewValidatorSet([]*Validator{})
  172. for i := 0; i < 1000; i++ {
  173. privKey := crypto.GenPrivKeyEd25519()
  174. pubKey := privKey.PubKey()
  175. val := NewValidator(pubKey, 0)
  176. if !vset.Add(val) {
  177. panic("Failed to add validator")
  178. }
  179. }
  180. b.StartTimer()
  181. for i := 0; i < b.N; i++ {
  182. vset.Copy()
  183. }
  184. }
  185. func (valSet *ValidatorSet) toBytes() []byte {
  186. buf, n, err := new(bytes.Buffer), new(int), new(error)
  187. wire.WriteBinary(valSet, buf, n, err)
  188. if *err != nil {
  189. cmn.PanicCrisis(*err)
  190. }
  191. return buf.Bytes()
  192. }
  193. func (valSet *ValidatorSet) fromBytes(b []byte) {
  194. r, n, err := bytes.NewReader(b), new(int), new(error)
  195. wire.ReadBinary(valSet, r, 0, n, err)
  196. if *err != nil {
  197. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  198. cmn.PanicCrisis(*err)
  199. }
  200. }