Commit dd10c714 authored by Christopher Schinnerl's avatar Christopher Schinnerl

Merge branch 'hostdb-durations' into 'master'

hostdb will minimize the score of hosts that don't have a high enough MaxDuration

See merge request !3588
parents ca04cd25 2e218ac4
Pipeline #57651175 failed with stages
in 98 minutes and 3 seconds
......@@ -53,6 +53,7 @@ func printScoreBreakdown(info *api.HostdbHostsGET) {
fmt.Fprintf(w, "\t\tAge:\t %.3f\n", info.ScoreBreakdown.AgeAdjustment)
fmt.Fprintf(w, "\t\tBurn:\t %.3f\n", info.ScoreBreakdown.BurnAdjustment)
fmt.Fprintf(w, "\t\tCollateral:\t %.3f\n", info.ScoreBreakdown.CollateralAdjustment/1e96)
fmt.Fprintf(w, "\t\tDuration:\t %.3f\n", info.ScoreBreakdown.DurationAdjustment)
fmt.Fprintf(w, "\t\tInteraction:\t %.3f\n", info.ScoreBreakdown.InteractionAdjustment)
fmt.Fprintf(w, "\t\tPrice:\t %.3f\n", info.ScoreBreakdown.PriceAdjustment*1e24)
fmt.Fprintf(w, "\t\tStorage:\t %.3f\n", info.ScoreBreakdown.StorageRemainingAdjustment)
......
......@@ -1348,6 +1348,7 @@ Example Pubkey: ed25519:1234567890abcdef1234567890abcdef1234567890abcdef12345678
"ageadjustment": 0.1234, // float64
"burnadjustment": 0.1234, // float64
"collateraladjustment": 23.456, // float64
"durationadjustment": 1, // float64
"interactionadjustment": 0.1234, // float64
"priceadjustment": 0.1234, // float64
"storageremainingadjustment": 0.1234, // float64
......@@ -1376,6 +1377,9 @@ The multiplier that gets applied to the host based on how much proof-of-burn the
**collateraladjustment** | float64
The multiplier that gets applied to a host based on how much collateral the host is offering. More collateral is typically better, though above a point it can be detrimental.
**durationadjustment** | float64
The multiplier that gets applied to a host based on the max duration it accepts for file contracts. Typically '1' for hosts with an acceptable max duration, and '0' for hosts that have a max duration which is not long enough.
**interactionadjustment** | float64
The multipler that gets applied to a host based on previous interactions with the host. A high ratio of successful interactions will improve this hosts score, and a high ratio of failed interactions will hurt this hosts score. This adjustment helps account for hosts that are on unstable connections, don't keep their wallets unlocked, ran out of funds, etc.
......@@ -3439,4 +3443,4 @@ curl -A "Sia-Agent" -u "":<apipassword> --data "<requestbody>" "localhost:9980/w
standard success or error response. See [standard responses](#standard-responses).
# Version
<a href='https://sia.tech/docs/v140'>**v140**
\ No newline at end of file
<a href='https://sia.tech/docs/v140'>**v140**
......@@ -318,6 +318,7 @@ type HostScoreBreakdown struct {
AgeAdjustment float64 `json:"ageadjustment"`
BurnAdjustment float64 `json:"burnadjustment"`
CollateralAdjustment float64 `json:"collateraladjustment"`
DurationAdjustment float64 `json:"durationadjustment"`
InteractionAdjustment float64 `json:"interactionadjustment"`
PriceAdjustment float64 `json:"pricesmultiplier"`
StorageRemainingAdjustment float64 `json:"storageremainingadjustment"`
......
......@@ -28,7 +28,7 @@ func (sb customScoreBreakdown) Score() types.Currency {
func (sb customScoreBreakdown) ConversionRate(_ types.Currency) float64 {
return 0.0
}
func (sb customScoreBreakdown) HostScoreBreakdown(_ types.Currency, _, _ bool) modules.HostScoreBreakdown {
func (sb customScoreBreakdown) HostScoreBreakdown(_ types.Currency, _, _, _ bool) modules.HostScoreBreakdown {
return modules.HostScoreBreakdown{}
}
func newCustomScoreBreakdown(score types.Currency) ScoreBreakdown {
......
......@@ -10,7 +10,7 @@ import (
// ScoreBreakdown is an interface that allows us to mock the hostAdjustments
// during testing.
type ScoreBreakdown interface {
HostScoreBreakdown(totalScore types.Currency, ignoreAge, ignoreUptime bool) modules.HostScoreBreakdown
HostScoreBreakdown(totalScore types.Currency, ignoreAge, ignoreDuration, ignoreUptime bool) modules.HostScoreBreakdown
Score() types.Currency
}
......@@ -20,6 +20,7 @@ type HostAdjustments struct {
AgeAdjustment float64
BurnAdjustment float64
CollateralAdjustment float64
DurationAdjustment float64
InteractionAdjustment float64
PriceAdjustment float64
StorageRemainingAdjustment float64
......@@ -49,7 +50,7 @@ func conversionRate(score, totalScore types.Currency) float64 {
// HostScoreBreakdown converts a HostAdjustments object into a
// modules.HostScoreBreakdown.
func (h HostAdjustments) HostScoreBreakdown(totalScore types.Currency, ignoreAge, ignoreUptime bool) modules.HostScoreBreakdown {
func (h HostAdjustments) HostScoreBreakdown(totalScore types.Currency, ignoreAge, ignoreDuration, ignoreUptime bool) modules.HostScoreBreakdown {
// Set the ignored fields to 1.
if ignoreAge {
h.AgeAdjustment = 1.0
......@@ -57,6 +58,9 @@ func (h HostAdjustments) HostScoreBreakdown(totalScore types.Currency, ignoreAge
if ignoreUptime {
h.UptimeAdjustment = 1.0
}
if ignoreDuration {
h.DurationAdjustment = 1.0
}
// Create the breakdown.
score := h.Score()
return modules.HostScoreBreakdown{
......@@ -66,6 +70,7 @@ func (h HostAdjustments) HostScoreBreakdown(totalScore types.Currency, ignoreAge
AgeAdjustment: h.AgeAdjustment,
BurnAdjustment: h.BurnAdjustment,
CollateralAdjustment: h.CollateralAdjustment,
DurationAdjustment: h.DurationAdjustment,
InteractionAdjustment: h.InteractionAdjustment,
PriceAdjustment: h.PriceAdjustment,
StorageRemainingAdjustment: h.StorageRemainingAdjustment,
......@@ -78,8 +83,8 @@ func (h HostAdjustments) HostScoreBreakdown(totalScore types.Currency, ignoreAge
// score.
func (h HostAdjustments) Score() types.Currency {
// Combine the adjustments.
fullPenalty := h.BurnAdjustment * h.CollateralAdjustment * h.InteractionAdjustment * h.AgeAdjustment *
h.PriceAdjustment * h.StorageRemainingAdjustment * h.UptimeAdjustment * h.VersionAdjustment
fullPenalty := h.BurnAdjustment * h.CollateralAdjustment * h.DurationAdjustment * h.InteractionAdjustment *
h.AgeAdjustment * h.PriceAdjustment * h.StorageRemainingAdjustment * h.UptimeAdjustment * h.VersionAdjustment
// Return a types.Currency.
weight := baseWeight.MulFloat(fullPenalty)
......
......@@ -3,6 +3,7 @@ package hostdb
import (
"fmt"
"math"
"time"
"gitlab.com/NebulousLabs/Sia/build"
"gitlab.com/NebulousLabs/Sia/modules"
......@@ -180,6 +181,16 @@ func (hdb *HostDB) collateralAdjustments(entry modules.HostDBEntry, allowance mo
return smallWeight * largeWeight
}
// durationAdjustments checks that the host has a maxduration which is larger
// than the period of the allowance. The host's score is heavily minimized if
// not.
func (hdb *HostDB) durationAdjustments(entry modules.HostDBEntry, allowance modules.Allowance) float64 {
if entry.MaxDuration < allowance.Period {
return math.SmallestNonzeroFloat64
}
return 1
}
// interactionAdjustments determine the penalty to be applied to a host for the
// historic and current interactions with that host. This function focuses on
// historic interactions and ignores recent interactions.
......@@ -386,6 +397,11 @@ func (hdb *HostDB) lifetimeAdjustments(entry modules.HostDBEntry) float64 {
// new host to give the host some initial uptime or downtime. Modification of
// this function needs to be made paying attention to the structure of that
// function.
//
// TODO: This function doesn't correctly handle situations where the user's
// clock goes back in time. If the user adjusts their system clock to be in the
// past, we'll get timestamping that's out of order, and this will cause erratic
// / improper / untested behavior.
func (hdb *HostDB) uptimeAdjustments(entry modules.HostDBEntry) float64 {
// Special case: if we have scanned the host twice or fewer, don't perform
// uptime math.
......@@ -419,7 +435,7 @@ func (hdb *HostDB) uptimeAdjustments(entry modules.HostDBEntry) float64 {
if build.DEBUG {
hdb.log.Critical("Host entry scan history not sorted.")
} else {
hdb.log.Print("WARNING: Host entry scan history not sorted.")
hdb.log.Print("WARN: Host entry scan history not sorted.")
}
// Ignore the unsorted scan entry.
continue
......@@ -432,8 +448,19 @@ func (hdb *HostDB) uptimeAdjustments(entry modules.HostDBEntry) float64 {
recentTime = scan.Timestamp
recentSuccess = scan.Success
}
// One more check to incorporate the uptime or downtime of the most recent
// scan, we assume that if we scanned them right now, their uptime /
// downtime status would be equal to what it currently is.
if recentSuccess {
uptime += time.Now().Sub(recentTime)
} else {
downtime += time.Now().Sub(recentTime)
}
// Sanity check against 0 total time.
if uptime == 0 && downtime == 0 {
build.Critical("uptime and downtime are zero for this host, should have been caught in earlier logic")
return 0.001 // Shouldn't happen.
}
......@@ -478,6 +505,7 @@ func (hdb *HostDB) managedCalculateHostWeightFn(allowance modules.Allowance) hos
return hosttree.HostAdjustments{
BurnAdjustment: 1,
CollateralAdjustment: hdb.collateralAdjustments(entry, allowance),
DurationAdjustment: hdb.durationAdjustments(entry, allowance),
InteractionAdjustment: hdb.interactionAdjustments(entry),
AgeAdjustment: hdb.lifetimeAdjustments(entry),
PriceAdjustment: hdb.priceAdjustments(entry, allowance, txnFees),
......@@ -495,7 +523,7 @@ func (hdb *HostDB) EstimateHostScore(entry modules.HostDBEntry, allowance module
return modules.HostScoreBreakdown{}, err
}
defer hdb.tg.Done()
return hdb.managedScoreBreakdown(entry, true, true), nil
return hdb.managedScoreBreakdown(entry, true, true, true), nil
}
// ScoreBreakdown provdes a detailed set of scalars and bools indicating
......@@ -505,12 +533,12 @@ func (hdb *HostDB) ScoreBreakdown(entry modules.HostDBEntry) (modules.HostScoreB
return modules.HostScoreBreakdown{}, err
}
defer hdb.tg.Done()
return hdb.managedScoreBreakdown(entry, false, false), nil
return hdb.managedScoreBreakdown(entry, false, false, false), nil
}
// managedScoreBreakdown computes the score breakdown of a host. Certain
// adjustments can be ignored.
func (hdb *HostDB) managedScoreBreakdown(entry modules.HostDBEntry, ignoreAge, ignoreUptime bool) modules.HostScoreBreakdown {
func (hdb *HostDB) managedScoreBreakdown(entry modules.HostDBEntry, ignoreAge, ignoreDuration, ignoreUptime bool) modules.HostScoreBreakdown {
hosts := hdb.ActiveHosts()
// Compute the totalScore.
......@@ -521,5 +549,5 @@ func (hdb *HostDB) managedScoreBreakdown(entry modules.HostDBEntry, ignoreAge, i
totalScore = totalScore.Add(hdb.weightFunc(host).Score())
}
// Compute the breakdown.
return hdb.weightFunc(entry).HostScoreBreakdown(totalScore, ignoreAge, ignoreUptime)
return hdb.weightFunc(entry).HostScoreBreakdown(totalScore, ignoreAge, ignoreDuration, ignoreUptime)
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment