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.

158 lines
3.8 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. tmrand "github.com/tendermint/tendermint/libs/rand"
  10. tmproto "github.com/tendermint/tendermint/proto/types"
  11. )
  12. // Volatile state for each Validator
  13. // NOTE: The ProposerPriority is not included in Validator.Hash();
  14. // make sure to update that method if changes are made here
  15. type Validator struct {
  16. Address Address `json:"address"`
  17. PubKey crypto.PubKey `json:"pub_key"`
  18. VotingPower int64 `json:"voting_power"`
  19. ProposerPriority int64 `json:"proposer_priority"`
  20. }
  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. // Creates a new copy of the validator so we can mutate ProposerPriority.
  30. // Panics if the validator is nil.
  31. func (v *Validator) Copy() *Validator {
  32. vCopy := *v
  33. return &vCopy
  34. }
  35. // Returns the one with higher ProposerPriority.
  36. func (v *Validator) CompareProposerPriority(other *Validator) *Validator {
  37. if v == nil {
  38. return other
  39. }
  40. switch {
  41. case v.ProposerPriority > other.ProposerPriority:
  42. return v
  43. case v.ProposerPriority < other.ProposerPriority:
  44. return other
  45. default:
  46. result := bytes.Compare(v.Address, other.Address)
  47. switch {
  48. case result < 0:
  49. return v
  50. case result > 0:
  51. return other
  52. default:
  53. panic("Cannot compare identical validators")
  54. }
  55. }
  56. }
  57. func (v *Validator) String() string {
  58. if v == nil {
  59. return "nil-Validator"
  60. }
  61. return fmt.Sprintf("Validator{%v %v VP:%v A:%v}",
  62. v.Address,
  63. v.PubKey,
  64. v.VotingPower,
  65. v.ProposerPriority)
  66. }
  67. // ValidatorListString returns a prettified validator list for logging purposes.
  68. func ValidatorListString(vals []*Validator) string {
  69. chunks := make([]string, len(vals))
  70. for i, val := range vals {
  71. chunks[i] = fmt.Sprintf("%s:%d", val.Address, val.VotingPower)
  72. }
  73. return strings.Join(chunks, ",")
  74. }
  75. // Bytes computes the unique encoding of a validator with a given voting power.
  76. // These are the bytes that gets hashed in consensus. It excludes address
  77. // as its redundant with the pubkey. This also excludes ProposerPriority
  78. // which changes every round.
  79. func (v *Validator) Bytes() []byte {
  80. return cdcEncode(struct {
  81. PubKey crypto.PubKey
  82. VotingPower int64
  83. }{
  84. v.PubKey,
  85. v.VotingPower,
  86. })
  87. }
  88. // ToProto converts Valiator to protobuf
  89. func (v *Validator) ToProto() (*tmproto.Validator, error) {
  90. if v == nil {
  91. return nil, errors.New("nil validator")
  92. }
  93. pk, err := ce.PubKeyToProto(v.PubKey)
  94. if err != nil {
  95. return nil, err
  96. }
  97. vp := tmproto.Validator{
  98. Address: v.Address,
  99. PubKey: pk,
  100. VotingPower: v.VotingPower,
  101. ProposerPriority: v.ProposerPriority,
  102. }
  103. return &vp, nil
  104. }
  105. // FromProto sets a protobuf Validator to the given pointer.
  106. // It returns an error if the public key is invalid.
  107. func ValidatorFromProto(vp *tmproto.Validator) (*Validator, error) {
  108. if vp == nil {
  109. return nil, errors.New("nil validator")
  110. }
  111. pk, err := ce.PubKeyFromProto(vp.PubKey)
  112. if err != nil {
  113. return nil, err
  114. }
  115. v := new(Validator)
  116. v.Address = vp.GetAddress()
  117. v.PubKey = pk
  118. v.VotingPower = vp.GetVotingPower()
  119. v.ProposerPriority = vp.GetProposerPriority()
  120. return v, nil
  121. }
  122. //----------------------------------------
  123. // RandValidator
  124. // RandValidator returns a randomized validator, useful for testing.
  125. // UNSTABLE
  126. func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) {
  127. privVal := NewMockPV()
  128. votePower := minPower
  129. if randPower {
  130. votePower += int64(tmrand.Uint32())
  131. }
  132. pubKey, err := privVal.GetPubKey()
  133. if err != nil {
  134. panic(fmt.Errorf("could not retrieve pubkey %w", err))
  135. }
  136. val := NewValidator(pubKey, votePower)
  137. return val, privVal
  138. }