github.com/Finschia/ostracon@v1.1.5/types/validator.go (about)

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