gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/renter/hostdb/hosttree/scorebreakdown.go (about)

     1  package hosttree
     2  
     3  import (
     4  	"math/big"
     5  
     6  	"gitlab.com/SiaPrime/SiaPrime/modules"
     7  	"gitlab.com/SiaPrime/SiaPrime/types"
     8  )
     9  
    10  // ScoreBreakdown is an interface that allows us to mock the hostAdjustments
    11  // during testing.
    12  type ScoreBreakdown interface {
    13  	HostScoreBreakdown(totalScore types.Currency, ignoreAge, ignoreDuration, ignoreUptime bool) modules.HostScoreBreakdown
    14  	Score() types.Currency
    15  }
    16  
    17  // HostAdjustments contains all the adjustments relevant to a host's score and
    18  // implements the scoreBreakdown interface.
    19  type HostAdjustments struct {
    20  	AgeAdjustment              float64
    21  	BurnAdjustment             float64
    22  	CollateralAdjustment       float64
    23  	DurationAdjustment         float64
    24  	InteractionAdjustment      float64
    25  	PriceAdjustment            float64
    26  	StorageRemainingAdjustment float64
    27  	UptimeAdjustment           float64
    28  	VersionAdjustment          float64
    29  }
    30  
    31  var (
    32  	// Previous constructions of the hostdb required the baseWeight to be large
    33  	// to prevent fractional results, but the current iteration of the hostdb
    34  	// has no issues, the scores will always be quite large.
    35  	baseWeight = types.NewCurrency64(1)
    36  )
    37  
    38  // conversionRate computes the likelihood of a host with 'score' to be drawn
    39  // from the hosttree assuming that all hosts have 'totalScore'.
    40  func conversionRate(score, totalScore types.Currency) float64 {
    41  	if totalScore.IsZero() {
    42  		totalScore = types.NewCurrency64(1)
    43  	}
    44  	conversionRate, _ := big.NewRat(0, 1).SetFrac(score.Mul64(50).Big(), totalScore.Big()).Float64()
    45  	if conversionRate > 100 {
    46  		conversionRate = 100
    47  	}
    48  	return conversionRate
    49  }
    50  
    51  // HostScoreBreakdown converts a HostAdjustments object into a
    52  // modules.HostScoreBreakdown.
    53  func (h HostAdjustments) HostScoreBreakdown(totalScore types.Currency, ignoreAge, ignoreDuration, ignoreUptime bool) modules.HostScoreBreakdown {
    54  	// Set the ignored fields to 1.
    55  	if ignoreAge {
    56  		h.AgeAdjustment = 1.0
    57  	}
    58  	if ignoreUptime {
    59  		h.UptimeAdjustment = 1.0
    60  	}
    61  	if ignoreDuration {
    62  		h.DurationAdjustment = 1.0
    63  	}
    64  	// Create the breakdown.
    65  	score := h.Score()
    66  	return modules.HostScoreBreakdown{
    67  		Score:          score,
    68  		ConversionRate: conversionRate(score, totalScore),
    69  
    70  		AgeAdjustment:              h.AgeAdjustment,
    71  		BurnAdjustment:             h.BurnAdjustment,
    72  		CollateralAdjustment:       h.CollateralAdjustment,
    73  		DurationAdjustment:         h.DurationAdjustment,
    74  		InteractionAdjustment:      h.InteractionAdjustment,
    75  		PriceAdjustment:            h.PriceAdjustment,
    76  		StorageRemainingAdjustment: h.StorageRemainingAdjustment,
    77  		UptimeAdjustment:           h.UptimeAdjustment,
    78  		VersionAdjustment:          h.VersionAdjustment,
    79  	}
    80  }
    81  
    82  // Score combines the individual adjustments of the breakdown into a single
    83  // score.
    84  func (h HostAdjustments) Score() types.Currency {
    85  	// Combine the adjustments.
    86  	fullPenalty := h.BurnAdjustment * h.CollateralAdjustment * h.DurationAdjustment * h.InteractionAdjustment *
    87  		h.AgeAdjustment * h.PriceAdjustment * h.StorageRemainingAdjustment * h.UptimeAdjustment * h.VersionAdjustment
    88  
    89  	// Return a types.Currency.
    90  	weight := baseWeight.MulFloat(fullPenalty)
    91  	if weight.IsZero() {
    92  		// A weight of zero is problematic for for the host tree.
    93  		return types.NewCurrency64(1)
    94  	}
    95  	return weight
    96  }