github.com/okex/exchain@v1.8.0/libs/tendermint/types/validator.go (about)

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