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.

173 lines
4.0 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "strings"
  7. "github.com/tendermint/tendermint/crypto"
  8. ce "github.com/tendermint/tendermint/crypto/encoding"
  9. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  10. )
  11. // Volatile state for each Validator
  12. // NOTE: The ProposerPriority is not included in Validator.Hash();
  13. // make sure to update that method if changes are made here
  14. type Validator struct {
  15. Address Address `json:"address"`
  16. PubKey crypto.PubKey `json:"pub_key"`
  17. VotingPower int64 `json:"voting_power"`
  18. ProposerPriority int64 `json:"proposer_priority"`
  19. }
  20. // NewValidator returns a new validator with the given pubkey and voting power.
  21. func NewValidator(pubKey crypto.PubKey, votingPower int64) *Validator {
  22. return &Validator{
  23. Address: pubKey.Address(),
  24. PubKey: pubKey,
  25. VotingPower: votingPower,
  26. ProposerPriority: 0,
  27. }
  28. }
  29. // ValidateBasic performs basic validation.
  30. func (v *Validator) ValidateBasic() error {
  31. if v == nil {
  32. return errors.New("nil validator")
  33. }
  34. if v.PubKey == nil {
  35. return errors.New("validator does not have a public key")
  36. }
  37. if v.VotingPower < 0 {
  38. return errors.New("validator has negative voting power")
  39. }
  40. if len(v.Address) != crypto.AddressSize {
  41. return fmt.Errorf("validator address is the wrong size: %v", v.Address)
  42. }
  43. return nil
  44. }
  45. // Creates a new copy of the validator so we can mutate ProposerPriority.
  46. // Panics if the validator is nil.
  47. func (v *Validator) Copy() *Validator {
  48. vCopy := *v
  49. return &vCopy
  50. }
  51. // Returns the one with higher ProposerPriority.
  52. func (v *Validator) CompareProposerPriority(other *Validator) *Validator {
  53. if v == nil {
  54. return other
  55. }
  56. switch {
  57. case v.ProposerPriority > other.ProposerPriority:
  58. return v
  59. case v.ProposerPriority < other.ProposerPriority:
  60. return other
  61. default:
  62. result := bytes.Compare(v.Address, other.Address)
  63. switch {
  64. case result < 0:
  65. return v
  66. case result > 0:
  67. return other
  68. default:
  69. panic("Cannot compare identical validators")
  70. }
  71. }
  72. }
  73. // String returns a string representation of String.
  74. //
  75. // 1. address
  76. // 2. public key
  77. // 3. voting power
  78. // 4. proposer priority
  79. func (v *Validator) String() string {
  80. if v == nil {
  81. return "nil-Validator"
  82. }
  83. return fmt.Sprintf("Validator{%v %v VP:%v A:%v}",
  84. v.Address,
  85. v.PubKey,
  86. v.VotingPower,
  87. v.ProposerPriority)
  88. }
  89. // ValidatorListString returns a prettified validator list for logging purposes.
  90. func ValidatorListString(vals []*Validator) string {
  91. chunks := make([]string, len(vals))
  92. for i, val := range vals {
  93. chunks[i] = fmt.Sprintf("%s:%d", val.Address, val.VotingPower)
  94. }
  95. return strings.Join(chunks, ",")
  96. }
  97. // Bytes computes the unique encoding of a validator with a given voting power.
  98. // These are the bytes that gets hashed in consensus. It excludes address
  99. // as its redundant with the pubkey. This also excludes ProposerPriority
  100. // which changes every round.
  101. func (v *Validator) Bytes() []byte {
  102. pk, err := ce.PubKeyToProto(v.PubKey)
  103. if err != nil {
  104. panic(err)
  105. }
  106. pbv := tmproto.SimpleValidator{
  107. PubKey: &pk,
  108. VotingPower: v.VotingPower,
  109. }
  110. bz, err := pbv.Marshal()
  111. if err != nil {
  112. panic(err)
  113. }
  114. return bz
  115. }
  116. // ToProto converts Valiator to protobuf
  117. func (v *Validator) ToProto() (*tmproto.Validator, error) {
  118. if v == nil {
  119. return nil, errors.New("nil validator")
  120. }
  121. pk, err := ce.PubKeyToProto(v.PubKey)
  122. if err != nil {
  123. return nil, err
  124. }
  125. vp := tmproto.Validator{
  126. Address: v.Address,
  127. PubKey: pk,
  128. VotingPower: v.VotingPower,
  129. ProposerPriority: v.ProposerPriority,
  130. }
  131. return &vp, nil
  132. }
  133. // FromProto sets a protobuf Validator to the given pointer.
  134. // It returns an error if the public key is invalid.
  135. func ValidatorFromProto(vp *tmproto.Validator) (*Validator, error) {
  136. if vp == nil {
  137. return nil, errors.New("nil validator")
  138. }
  139. pk, err := ce.PubKeyFromProto(vp.PubKey)
  140. if err != nil {
  141. return nil, err
  142. }
  143. v := new(Validator)
  144. v.Address = vp.GetAddress()
  145. v.PubKey = pk
  146. v.VotingPower = vp.GetVotingPower()
  147. v.ProposerPriority = vp.GetProposerPriority()
  148. return v, nil
  149. }