github.com/bloxroute-labs/bor@v0.1.4/consensus/bor/validator.go (about)

     1  package bor
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"math/big"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/maticnetwork/bor/common"
    13  )
    14  
    15  // Validator represets 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  	ID               uint64         `json:"ID"`
    20  	Address          common.Address `json:"signer"`
    21  	VotingPower      int64          `json:"power"`
    22  	ProposerPriority int64          `json:"accum"`
    23  }
    24  
    25  // NewValidator creates new validator
    26  func NewValidator(address common.Address, votingPower int64) *Validator {
    27  	return &Validator{
    28  		Address:          address,
    29  		VotingPower:      votingPower,
    30  		ProposerPriority: 0,
    31  	}
    32  }
    33  
    34  // Creates a new copy of the validator so we can mutate ProposerPriority.
    35  // Panics if the validator is nil.
    36  func (v *Validator) Copy() *Validator {
    37  	vCopy := *v
    38  	return &vCopy
    39  }
    40  
    41  // Returns the one with higher ProposerPriority.
    42  func (v *Validator) CompareProposerPriority(other *Validator) *Validator {
    43  	if v == nil {
    44  		return other
    45  	}
    46  	if v.ProposerPriority > other.ProposerPriority {
    47  		return v
    48  	} else if v.ProposerPriority < other.ProposerPriority {
    49  		return other
    50  	} else {
    51  		result := bytes.Compare(v.Address.Bytes(), other.Address.Bytes())
    52  		if result < 0 {
    53  			return v
    54  		} else if result > 0 {
    55  			return other
    56  		} else {
    57  			panic("Cannot compare identical validators")
    58  			return nil
    59  		}
    60  	}
    61  }
    62  
    63  func (v *Validator) String() string {
    64  	if v == nil {
    65  		return "nil-Validator"
    66  	}
    67  	return fmt.Sprintf("Validator{%v Power:%v Priority:%v}",
    68  		v.Address.Hex(),
    69  		v.VotingPower,
    70  		v.ProposerPriority)
    71  }
    72  
    73  // ValidatorListString returns a prettified validator list for logging purposes.
    74  func ValidatorListString(vals []*Validator) string {
    75  	chunks := make([]string, len(vals))
    76  	for i, val := range vals {
    77  		chunks[i] = fmt.Sprintf("%s:%d", val.Address, val.VotingPower)
    78  	}
    79  
    80  	return strings.Join(chunks, ",")
    81  }
    82  
    83  // Bytes computes the unique encoding of a validator with a given voting power.
    84  // These are the bytes that gets hashed in consensus. It excludes address
    85  // as its redundant with the pubkey. This also excludes ProposerPriority
    86  // which changes every round.
    87  func (v *Validator) Bytes() []byte {
    88  	b, err := json.Marshal(v)
    89  	if err != nil {
    90  		return b
    91  	}
    92  	return nil
    93  }
    94  
    95  // HeaderBytes return header bytes
    96  func (v *Validator) HeaderBytes() []byte {
    97  	result := make([]byte, 40)
    98  	copy(result[:20], v.Address.Bytes())
    99  	copy(result[20:], v.PowerBytes())
   100  	return result
   101  }
   102  
   103  // PowerBytes return power bytes
   104  func (v *Validator) PowerBytes() []byte {
   105  	powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes()
   106  	result := make([]byte, 20)
   107  	copy(result[20-len(powerBytes):], powerBytes)
   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  	for i := 0; i < len(validatorsBytes); i += 40 {
   128  		address := make([]byte, 20)
   129  		power := make([]byte, 20)
   130  
   131  		copy(address, validatorsBytes[i:i+20])
   132  		copy(power, validatorsBytes[i+20:i+40])
   133  
   134  		result[i/40] = NewValidator(common.BytesToAddress(address), big.NewInt(0).SetBytes(power).Int64())
   135  	}
   136  
   137  	return result, nil
   138  }
   139  
   140  // ---
   141  
   142  // MinimalVal is the minimal validator representation
   143  // Used to send validator information to bor validator contract
   144  type MinimalVal struct {
   145  	ID          uint64         `json:"ID"`
   146  	VotingPower uint64         `json:"power"` // TODO add 10^-18 here so that we dont overflow easily
   147  	Signer      common.Address `json:"signer"`
   148  }
   149  
   150  // SortMinimalValByAddress sorts validators
   151  func SortMinimalValByAddress(a []MinimalVal) []MinimalVal {
   152  	sort.Slice(a, func(i, j int) bool {
   153  		return bytes.Compare(a[i].Signer.Bytes(), a[j].Signer.Bytes()) < 0
   154  	})
   155  	return a
   156  }
   157  
   158  // ValidatorsToMinimalValidators converts array of validators to minimal validators
   159  func ValidatorsToMinimalValidators(vals []Validator) (minVals []MinimalVal) {
   160  	for _, val := range vals {
   161  		minVals = append(minVals, val.MinimalVal())
   162  	}
   163  	return
   164  }