github.com/DFWallet/tendermint-cosmos@v0.0.2/types/validator.go (about)

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