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.

157 lines
4.0 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
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. "io"
  4. . "github.com/tendermint/tendermint/binary"
  5. . "github.com/tendermint/tendermint/common"
  6. )
  7. // Holds state for a Validator at a given height+round.
  8. // Meant to be discarded every round of the consensus protocol.
  9. // TODO consider moving this to another common types package.
  10. type Validator struct {
  11. Account
  12. BondHeight uint32 // TODO: is this needed?
  13. VotingPower uint64
  14. Accum int64
  15. }
  16. // Used to persist the state of ConsensusStateControl.
  17. func ReadValidator(r io.Reader, n *int64, err *error) *Validator {
  18. return &Validator{
  19. Account: ReadAccount(r, n, err),
  20. BondHeight: ReadUInt32(r, n, err),
  21. VotingPower: ReadUInt64(r, n, err),
  22. Accum: ReadInt64(r, n, err),
  23. }
  24. }
  25. // Creates a new copy of the validator so we can mutate accum.
  26. func (v *Validator) Copy() *Validator {
  27. return &Validator{
  28. Account: v.Account,
  29. BondHeight: v.BondHeight,
  30. VotingPower: v.VotingPower,
  31. Accum: v.Accum,
  32. }
  33. }
  34. // Used to persist the state of ConsensusStateControl.
  35. func (v *Validator) WriteTo(w io.Writer) (n int64, err error) {
  36. WriteBinary(w, v.Account, &n, &err)
  37. WriteUInt32(w, v.BondHeight, &n, &err)
  38. WriteUInt64(w, v.VotingPower, &n, &err)
  39. WriteInt64(w, v.Accum, &n, &err)
  40. return
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Not goroutine-safe.
  44. type ValidatorSet struct {
  45. validators map[uint64]*Validator
  46. indexToId map[uint32]uint64 // bitarray index to validator id
  47. idToIndex map[uint64]uint32 // validator id to bitarray index
  48. totalVotingPower uint64
  49. }
  50. func NewValidatorSet(validators map[uint64]*Validator) *ValidatorSet {
  51. if validators == nil {
  52. validators = make(map[uint64]*Validator)
  53. }
  54. ids := []uint64{}
  55. indexToId := map[uint32]uint64{}
  56. idToIndex := map[uint64]uint32{}
  57. totalVotingPower := uint64(0)
  58. for id, val := range validators {
  59. ids = append(ids, id)
  60. totalVotingPower += val.VotingPower
  61. }
  62. UInt64Slice(ids).Sort()
  63. for i, id := range ids {
  64. indexToId[uint32(i)] = id
  65. idToIndex[id] = uint32(i)
  66. }
  67. return &ValidatorSet{
  68. validators: validators,
  69. indexToId: indexToId,
  70. idToIndex: idToIndex,
  71. totalVotingPower: totalVotingPower,
  72. }
  73. }
  74. func (vset *ValidatorSet) IncrementAccum() {
  75. totalDelta := int64(0)
  76. for _, validator := range vset.validators {
  77. validator.Accum += int64(validator.VotingPower)
  78. totalDelta += int64(validator.VotingPower)
  79. }
  80. proposer := vset.GetProposer()
  81. proposer.Accum -= totalDelta
  82. // NOTE: sum(v) here should be zero.
  83. if true {
  84. totalAccum := int64(0)
  85. for _, validator := range vset.validators {
  86. totalAccum += validator.Accum
  87. }
  88. if totalAccum != 0 {
  89. Panicf("Total Accum of validators did not equal 0. Got: ", totalAccum)
  90. }
  91. }
  92. }
  93. func (vset *ValidatorSet) Copy() *ValidatorSet {
  94. validators := map[uint64]*Validator{}
  95. for id, val := range vset.validators {
  96. validators[id] = val.Copy()
  97. }
  98. return &ValidatorSet{
  99. validators: validators,
  100. indexToId: vset.indexToId,
  101. idToIndex: vset.idToIndex,
  102. totalVotingPower: vset.totalVotingPower,
  103. }
  104. }
  105. func (vset *ValidatorSet) GetById(id uint64) *Validator {
  106. return vset.validators[id]
  107. }
  108. func (vset *ValidatorSet) GetIndexById(id uint64) (uint32, bool) {
  109. index, ok := vset.idToIndex[id]
  110. return index, ok
  111. }
  112. func (vset *ValidatorSet) GetIdByIndex(index uint32) (uint64, bool) {
  113. id, ok := vset.indexToId[index]
  114. return id, ok
  115. }
  116. func (vset *ValidatorSet) Map() map[uint64]*Validator {
  117. return vset.validators
  118. }
  119. func (vset *ValidatorSet) Size() uint {
  120. return uint(len(vset.validators))
  121. }
  122. func (vset *ValidatorSet) TotalVotingPower() uint64 {
  123. return vset.totalVotingPower
  124. }
  125. // TODO: cache proposer. invalidate upon increment.
  126. func (vset *ValidatorSet) GetProposer() (proposer *Validator) {
  127. highestAccum := int64(0)
  128. for _, validator := range vset.validators {
  129. if validator.Accum > highestAccum {
  130. highestAccum = validator.Accum
  131. proposer = validator
  132. } else if validator.Accum == highestAccum {
  133. if validator.Id < proposer.Id { // Seniority
  134. proposer = validator
  135. }
  136. }
  137. }
  138. return
  139. }