github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/consensus/bor/valset/validator.go (about)

     1  package valset
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"math/big"
     8  	"sort"
     9  	"strings"
    10  
    11  	"github.com/ethereum/go-ethereum/common"
    12  )
    13  
    14  // Validator represets Volatile state for each Validator
    15  type Validator struct {
    16  	ID               uint64         `json:"ID"`
    17  	Address          common.Address `json:"signer"`
    18  	VotingPower      int64          `json:"power"`
    19  	ProposerPriority int64          `json:"accum"`
    20  }
    21  
    22  // NewValidator creates new validator
    23  func NewValidator(address common.Address, votingPower int64) *Validator {
    24  	return &Validator{
    25  		Address:          address,
    26  		VotingPower:      votingPower,
    27  		ProposerPriority: 0,
    28  	}
    29  }
    30  
    31  // Copy creates a new copy of the validator so we can mutate ProposerPriority.
    32  // Panics if the validator is nil.
    33  func (v *Validator) Copy() *Validator {
    34  	vCopy := *v
    35  	return &vCopy
    36  }
    37  
    38  // Cmp returns the one validator with a higher ProposerPriority.
    39  // If ProposerPriority is same, it returns the validator with lexicographically smaller address
    40  func (v *Validator) Cmp(other *Validator) *Validator {
    41  	// if both of v and other are nil, nil will be returned and that could possibly lead to nil pointer dereference bubbling up the stack
    42  	if v == nil {
    43  		return other
    44  	}
    45  
    46  	if other == nil {
    47  		return v
    48  	}
    49  
    50  	if v.ProposerPriority > other.ProposerPriority {
    51  		return v
    52  	}
    53  
    54  	if v.ProposerPriority < other.ProposerPriority {
    55  		return other
    56  	}
    57  
    58  	result := bytes.Compare(v.Address.Bytes(), other.Address.Bytes())
    59  
    60  	if result == 0 {
    61  		panic("Cannot compare identical validators")
    62  	}
    63  
    64  	if result < 0 {
    65  		return v
    66  	}
    67  
    68  	// result > 0
    69  	return other
    70  }
    71  
    72  func (v *Validator) String() string {
    73  	if v == nil {
    74  		return "nil-Validator"
    75  	}
    76  
    77  	return fmt.Sprintf("Validator{%v Power:%v Priority:%v}",
    78  		v.Address.Hex(),
    79  		v.VotingPower,
    80  		v.ProposerPriority)
    81  }
    82  
    83  // ValidatorListString returns a prettified validator list for logging purposes.
    84  func ValidatorListString(vals []*Validator) string {
    85  	chunks := make([]string, len(vals))
    86  	for i, val := range vals {
    87  		chunks[i] = fmt.Sprintf("%s:%d", val.Address, val.VotingPower)
    88  	}
    89  
    90  	return strings.Join(chunks, ",")
    91  }
    92  
    93  // HeaderBytes return header bytes
    94  func (v *Validator) HeaderBytes() []byte {
    95  	result := make([]byte, 40)
    96  	copy(result[:20], v.Address.Bytes())
    97  	copy(result[20:], v.PowerBytes())
    98  
    99  	return result
   100  }
   101  
   102  // PowerBytes return power bytes
   103  func (v *Validator) PowerBytes() []byte {
   104  	powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes()
   105  	result := make([]byte, 20)
   106  	copy(result[20-len(powerBytes):], powerBytes)
   107  
   108  	return result
   109  }
   110  
   111  // MinimalVal returns block number of last validator update
   112  func (v *Validator) MinimalVal() MinimalVal {
   113  	return MinimalVal{
   114  		ID:          v.ID,
   115  		VotingPower: uint64(v.VotingPower),
   116  		Signer:      v.Address,
   117  	}
   118  }
   119  
   120  // ParseValidators returns validator set bytes
   121  func ParseValidators(validatorsBytes []byte) ([]*Validator, error) {
   122  	if len(validatorsBytes)%40 != 0 {
   123  		return nil, errors.New("Invalid validators bytes")
   124  	}
   125  
   126  	result := make([]*Validator, len(validatorsBytes)/40)
   127  
   128  	for i := 0; i < len(validatorsBytes); i += 40 {
   129  		address := make([]byte, 20)
   130  		power := make([]byte, 20)
   131  
   132  		copy(address, validatorsBytes[i:i+20])
   133  		copy(power, validatorsBytes[i+20:i+40])
   134  
   135  		result[i/40] = NewValidator(common.BytesToAddress(address), big.NewInt(0).SetBytes(power).Int64())
   136  	}
   137  
   138  	return result, nil
   139  }
   140  
   141  // ---
   142  
   143  // MinimalVal is the minimal validator representation
   144  // Used to send validator information to bor validator contract
   145  type MinimalVal struct {
   146  	ID          uint64         `json:"ID"`
   147  	VotingPower uint64         `json:"power"` // TODO add 10^-18 here so that we dont overflow easily
   148  	Signer      common.Address `json:"signer"`
   149  }
   150  
   151  // SortMinimalValByAddress sorts validators
   152  func SortMinimalValByAddress(a []MinimalVal) []MinimalVal {
   153  	sort.Slice(a, func(i, j int) bool {
   154  		return bytes.Compare(a[i].Signer.Bytes(), a[j].Signer.Bytes()) < 0
   155  	})
   156  
   157  	return a
   158  }
   159  
   160  // ValidatorsToMinimalValidators converts array of validators to minimal validators
   161  func ValidatorsToMinimalValidators(vals []Validator) (minVals []MinimalVal) {
   162  	for _, val := range vals {
   163  		minVals = append(minVals, val.MinimalVal())
   164  	}
   165  
   166  	return
   167  }