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.

146 lines
3.7 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package state
  2. import (
  3. "fmt"
  4. "io"
  5. "strings"
  6. . "github.com/tendermint/tendermint/binary"
  7. "github.com/tendermint/tendermint/merkle"
  8. )
  9. // Not goroutine-safe.
  10. type ValidatorSet struct {
  11. validators merkle.Tree
  12. proposer *Validator // Whoever has the highest Accum.
  13. totalVotingPower uint64
  14. }
  15. func NewValidatorSet(vals []*Validator) *ValidatorSet {
  16. validators := merkle.NewIAVLTree(BasicCodec, ValidatorCodec, 0, nil) // In memory
  17. var proposer *Validator
  18. totalVotingPower := uint64(0)
  19. for _, val := range vals {
  20. validators.Set(val.Id, val)
  21. proposer = proposer.CompareAccum(val)
  22. totalVotingPower += val.VotingPower
  23. }
  24. return &ValidatorSet{
  25. validators: validators,
  26. proposer: proposer,
  27. totalVotingPower: totalVotingPower,
  28. }
  29. }
  30. func ReadValidatorSet(r io.Reader, n *int64, err *error) *ValidatorSet {
  31. size := ReadUInt64(r, n, err)
  32. validators := []*Validator{}
  33. for i := uint64(0); i < size; i++ {
  34. validator := ReadValidator(r, n, err)
  35. validators = append(validators, validator)
  36. }
  37. return NewValidatorSet(validators)
  38. }
  39. func (vset *ValidatorSet) WriteTo(w io.Writer) (n int64, err error) {
  40. WriteUInt64(w, uint64(vset.validators.Size()), &n, &err)
  41. vset.validators.Iterate(func(key_ interface{}, val_ interface{}) bool {
  42. val := val_.(*Validator)
  43. WriteBinary(w, val, &n, &err)
  44. return false
  45. })
  46. return
  47. }
  48. func (vset *ValidatorSet) IncrementAccum() {
  49. // Decrement from previous proposer
  50. vset.proposer.Accum -= int64(vset.totalVotingPower)
  51. var proposer *Validator
  52. // Increment accum and find proposer
  53. vset.validators.Iterate(func(key_ interface{}, val_ interface{}) bool {
  54. val := val_.(*Validator)
  55. val.Accum += int64(val.VotingPower)
  56. proposer = proposer.CompareAccum(val)
  57. return false
  58. })
  59. vset.proposer = proposer
  60. }
  61. func (vset *ValidatorSet) Copy() *ValidatorSet {
  62. return &ValidatorSet{
  63. validators: vset.validators.Copy(),
  64. proposer: vset.proposer,
  65. totalVotingPower: vset.totalVotingPower,
  66. }
  67. }
  68. func (vset *ValidatorSet) GetById(id uint64) (index uint32, val *Validator) {
  69. index_, val_ := vset.validators.Get(id)
  70. index, val = uint32(index_), val_.(*Validator)
  71. return
  72. }
  73. func (vset *ValidatorSet) GetByIndex(index uint32) (id uint64, val *Validator) {
  74. id_, val_ := vset.validators.GetByIndex(uint64(index))
  75. id, val = id_.(uint64), val_.(*Validator)
  76. return
  77. }
  78. func (vset *ValidatorSet) Size() uint {
  79. return uint(vset.validators.Size())
  80. }
  81. func (vset *ValidatorSet) TotalVotingPower() uint64 {
  82. return vset.totalVotingPower
  83. }
  84. func (vset *ValidatorSet) Proposer() (proposer *Validator) {
  85. return vset.proposer
  86. }
  87. func (vset *ValidatorSet) Hash() []byte {
  88. return vset.validators.Hash()
  89. }
  90. func (vset *ValidatorSet) Add(val *Validator) (added bool) {
  91. if vset.validators.Has(val.Id) {
  92. return false
  93. }
  94. return !vset.validators.Set(val.Id, val)
  95. }
  96. func (vset *ValidatorSet) Update(val *Validator) (updated bool) {
  97. if !vset.validators.Has(val.Id) {
  98. return false
  99. }
  100. return vset.validators.Set(val.Id, val)
  101. }
  102. func (vset *ValidatorSet) Remove(validatorId uint64) (val *Validator, removed bool) {
  103. val_, removed := vset.validators.Remove(validatorId)
  104. return val_.(*Validator), removed
  105. }
  106. func (vset *ValidatorSet) Iterate(fn func(val *Validator) bool) {
  107. vset.validators.Iterate(func(key_ interface{}, val_ interface{}) bool {
  108. return fn(val_.(*Validator))
  109. })
  110. }
  111. func (vset *ValidatorSet) StringWithIndent(indent string) string {
  112. valStrings := []string{}
  113. vset.Iterate(func(val *Validator) bool {
  114. valStrings = append(valStrings, val.String())
  115. return false
  116. })
  117. return fmt.Sprintf(`ValidatorSet{
  118. %s Proposer: %v
  119. %s Validators:
  120. %s %v
  121. %s}`,
  122. indent, vset.proposer.String(),
  123. indent,
  124. indent, strings.Join(valStrings, "\n"+indent+" "),
  125. indent)
  126. }