github.com/MetalBlockchain/metalgo@v1.11.9/snow/networking/tracker/targeter.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package tracker
     5  
     6  import (
     7  	"go.uber.org/zap"
     8  
     9  	"github.com/MetalBlockchain/metalgo/ids"
    10  	"github.com/MetalBlockchain/metalgo/snow/validators"
    11  	"github.com/MetalBlockchain/metalgo/utils/constants"
    12  	"github.com/MetalBlockchain/metalgo/utils/logging"
    13  )
    14  
    15  var _ Targeter = (*targeter)(nil)
    16  
    17  type Targeter interface {
    18  	// Returns the target usage of the given node.
    19  	TargetUsage(nodeID ids.NodeID) float64
    20  }
    21  
    22  type TargeterConfig struct {
    23  	// VdrAlloc is the amount of the resource to split over validators, weighted
    24  	// by stake.
    25  	VdrAlloc float64 `json:"vdrAlloc"`
    26  
    27  	// MaxNonVdrUsage is the amount of the resource which, if utilized, will
    28  	// result in allocations being based only on the stake weighted allocation.
    29  	MaxNonVdrUsage float64 `json:"maxNonVdrUsage"`
    30  
    31  	// MaxNonVdrNodeUsage is the amount of the resource to allocate to a node
    32  	// before adding the stake weighted allocation.
    33  	MaxNonVdrNodeUsage float64 `json:"maxNonVdrNodeUsage"`
    34  }
    35  
    36  func NewTargeter(
    37  	logger logging.Logger,
    38  	config *TargeterConfig,
    39  	vdrs validators.Manager,
    40  	tracker Tracker,
    41  ) Targeter {
    42  	return &targeter{
    43  		log:                logger,
    44  		vdrs:               vdrs,
    45  		tracker:            tracker,
    46  		vdrAlloc:           config.VdrAlloc,
    47  		maxNonVdrUsage:     config.MaxNonVdrUsage,
    48  		maxNonVdrNodeUsage: config.MaxNonVdrNodeUsage,
    49  	}
    50  }
    51  
    52  type targeter struct {
    53  	vdrs               validators.Manager
    54  	log                logging.Logger
    55  	tracker            Tracker
    56  	vdrAlloc           float64
    57  	maxNonVdrUsage     float64
    58  	maxNonVdrNodeUsage float64
    59  }
    60  
    61  func (t *targeter) TargetUsage(nodeID ids.NodeID) float64 {
    62  	// This node's at-large allocation is min([remaining at large], [max at large for a given peer])
    63  	usage := t.tracker.TotalUsage()
    64  	baseAlloc := max(0, t.maxNonVdrUsage-usage)
    65  	baseAlloc = min(baseAlloc, t.maxNonVdrNodeUsage)
    66  
    67  	// This node gets a stake-weighted portion of the validator allocation.
    68  	weight := t.vdrs.GetWeight(constants.PrimaryNetworkID, nodeID)
    69  	if weight == 0 {
    70  		return baseAlloc
    71  	}
    72  
    73  	totalWeight, err := t.vdrs.TotalWeight(constants.PrimaryNetworkID)
    74  	if err != nil {
    75  		t.log.Error("couldn't get total weight of primary network",
    76  			zap.Error(err),
    77  		)
    78  		return baseAlloc
    79  	}
    80  
    81  	vdrAlloc := t.vdrAlloc * float64(weight) / float64(totalWeight)
    82  	return vdrAlloc + baseAlloc
    83  }