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.

106 lines
2.5 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/tendermint/tendermint/crypto/tmhash"
  6. "github.com/tendermint/tendermint/crypto"
  7. cmn "github.com/tendermint/tendermint/libs/common"
  8. )
  9. // Volatile state for each Validator
  10. // NOTE: The Accum is not included in Validator.Hash();
  11. // make sure to update that method if changes are made here
  12. type Validator struct {
  13. Address Address `json:"address"`
  14. PubKey crypto.PubKey `json:"pub_key"`
  15. VotingPower int64 `json:"voting_power"`
  16. Accum int64 `json:"accum"`
  17. }
  18. func NewValidator(pubKey crypto.PubKey, votingPower int64) *Validator {
  19. return &Validator{
  20. Address: pubKey.Address(),
  21. PubKey: pubKey,
  22. VotingPower: votingPower,
  23. Accum: 0,
  24. }
  25. }
  26. // Creates a new copy of the validator so we can mutate accum.
  27. // Panics if the validator is nil.
  28. func (v *Validator) Copy() *Validator {
  29. vCopy := *v
  30. return &vCopy
  31. }
  32. // Returns the one with higher Accum.
  33. func (v *Validator) CompareAccum(other *Validator) *Validator {
  34. if v == nil {
  35. return other
  36. }
  37. if v.Accum > other.Accum {
  38. return v
  39. } else if v.Accum < other.Accum {
  40. return other
  41. } else {
  42. result := bytes.Compare(v.Address, other.Address)
  43. if result < 0 {
  44. return v
  45. } else if result > 0 {
  46. return other
  47. } else {
  48. cmn.PanicSanity("Cannot compare identical validators")
  49. return nil
  50. }
  51. }
  52. }
  53. func (v *Validator) String() string {
  54. if v == nil {
  55. return "nil-Validator"
  56. }
  57. return fmt.Sprintf("Validator{%v %v VP:%v A:%v}",
  58. v.Address,
  59. v.PubKey,
  60. v.VotingPower,
  61. v.Accum)
  62. }
  63. // Hash computes the unique ID of a validator with a given voting power.
  64. // It excludes the Accum value, which changes with every round.
  65. func (v *Validator) Hash() []byte {
  66. return tmhash.Sum(v.Bytes())
  67. }
  68. // Bytes computes the unique encoding of a validator with a given voting power.
  69. // These are the bytes that gets hashed in consensus. It excludes pubkey
  70. // as its redundant with the address. This also excludes accum which changes
  71. // every round.
  72. func (v *Validator) Bytes() []byte {
  73. return cdcEncode((struct {
  74. Address Address
  75. VotingPower int64
  76. }{
  77. v.Address,
  78. v.VotingPower,
  79. }))
  80. }
  81. //----------------------------------------
  82. // RandValidator
  83. // RandValidator returns a randomized validator, useful for testing.
  84. // UNSTABLE
  85. func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) {
  86. privVal := NewMockPV()
  87. votePower := minPower
  88. if randPower {
  89. votePower += int64(cmn.RandUint32())
  90. }
  91. val := NewValidator(privVal.GetPubKey(), votePower)
  92. return val, privVal
  93. }