github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/state/staker.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package state
     5  
     6  import (
     7  	"bytes"
     8  	"time"
     9  
    10  	"github.com/google/btree"
    11  
    12  	"github.com/MetalBlockchain/metalgo/ids"
    13  	"github.com/MetalBlockchain/metalgo/utils/crypto/bls"
    14  	"github.com/MetalBlockchain/metalgo/vms/platformvm/txs"
    15  )
    16  
    17  var _ btree.LessFunc[*Staker] = (*Staker).Less
    18  
    19  // StakerIterator defines an interface for iterating over a set of stakers.
    20  type StakerIterator interface {
    21  	// Next attempts to move the iterator to the next staker. It returns false
    22  	// once there are no more stakers to return.
    23  	Next() bool
    24  
    25  	// Value returns the current staker. Value should only be called after a
    26  	// call to Next which returned true.
    27  	Value() *Staker
    28  
    29  	// Release any resources associated with the iterator. This must be called
    30  	// after the interator is no longer needed.
    31  	Release()
    32  }
    33  
    34  // Staker contains all information required to represent a validator or
    35  // delegator in the current and pending validator sets.
    36  // Invariant: Staker's size is bounded to prevent OOM DoS attacks.
    37  type Staker struct {
    38  	TxID            ids.ID
    39  	NodeID          ids.NodeID
    40  	PublicKey       *bls.PublicKey
    41  	SubnetID        ids.ID
    42  	Weight          uint64
    43  	StartTime       time.Time
    44  	EndTime         time.Time
    45  	PotentialReward uint64
    46  
    47  	// NextTime is the next time this staker will be moved from a validator set.
    48  	// If the staker is in the pending validator set, NextTime will equal
    49  	// StartTime. If the staker is in the current validator set, NextTime will
    50  	// equal EndTime.
    51  	NextTime time.Time
    52  
    53  	// Priority specifies how to break ties between stakers with the same
    54  	// NextTime. This ensures that stakers created by the same transaction type
    55  	// are grouped together. The ordering of these groups is documented in
    56  	// [priorities.go] and depends on if the stakers are in the pending or
    57  	// current validator set.
    58  	Priority txs.Priority
    59  }
    60  
    61  // A *Staker is considered to be less than another *Staker when:
    62  //
    63  //  1. If its NextTime is before the other's.
    64  //  2. If the NextTimes are the same, the *Staker with the lesser priority is the
    65  //     lesser one.
    66  //  3. If the priorities are also the same, the one with the lesser txID is
    67  //     lesser.
    68  func (s *Staker) Less(than *Staker) bool {
    69  	if s.NextTime.Before(than.NextTime) {
    70  		return true
    71  	}
    72  	if than.NextTime.Before(s.NextTime) {
    73  		return false
    74  	}
    75  
    76  	if s.Priority < than.Priority {
    77  		return true
    78  	}
    79  	if than.Priority < s.Priority {
    80  		return false
    81  	}
    82  
    83  	return bytes.Compare(s.TxID[:], than.TxID[:]) == -1
    84  }
    85  
    86  func NewCurrentStaker(
    87  	txID ids.ID,
    88  	staker txs.Staker,
    89  	startTime time.Time,
    90  	potentialReward uint64,
    91  ) (*Staker, error) {
    92  	publicKey, _, err := staker.PublicKey()
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	endTime := staker.EndTime()
    97  	return &Staker{
    98  		TxID:            txID,
    99  		NodeID:          staker.NodeID(),
   100  		PublicKey:       publicKey,
   101  		SubnetID:        staker.SubnetID(),
   102  		Weight:          staker.Weight(),
   103  		StartTime:       startTime,
   104  		EndTime:         endTime,
   105  		PotentialReward: potentialReward,
   106  		NextTime:        endTime,
   107  		Priority:        staker.CurrentPriority(),
   108  	}, nil
   109  }
   110  
   111  func NewPendingStaker(txID ids.ID, staker txs.ScheduledStaker) (*Staker, error) {
   112  	publicKey, _, err := staker.PublicKey()
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	startTime := staker.StartTime()
   117  	return &Staker{
   118  		TxID:      txID,
   119  		NodeID:    staker.NodeID(),
   120  		PublicKey: publicKey,
   121  		SubnetID:  staker.SubnetID(),
   122  		Weight:    staker.Weight(),
   123  		StartTime: startTime,
   124  		EndTime:   staker.EndTime(),
   125  		NextTime:  startTime,
   126  		Priority:  staker.PendingPriority(),
   127  	}, nil
   128  }