gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/hostdb/hostentry.go (about) 1 package hostdb 2 3 import ( 4 "math" 5 6 "gitlab.com/NebulousLabs/errors" 7 "gitlab.com/SkynetLabs/skyd/skymodules" 8 "go.sia.tech/siad/types" 9 ) 10 11 // updateHostDBEntry updates a HostDBEntries's historic interactions if more 12 // than one block passed since the last update. This should be called every time 13 // before the recent interactions are updated. if passedTime is e.g. 10, this 14 // means that the recent interactions were updated 10 blocks ago but never 15 // since. So we need to apply the decay of 1 block before we append the recent 16 // interactions from 10 blocks ago and then apply the decay of 9 more blocks in 17 // which the recent interactions have been 0 18 func updateHostHistoricInteractions(host *skymodules.HostDBEntry, bh types.BlockHeight) { 19 // Check that the last historic update was not in the future. 20 if host.LastHistoricUpdate >= bh { 21 // The hostdb may be performing a rescan, or maybe no time has passed 22 // since the last update, so there is nothing to do. 23 return 24 } 25 passedTime := bh - host.LastHistoricUpdate 26 27 // tmp float64 values for more accurate decay 28 hsi := host.HistoricSuccessfulInteractions 29 hfi := host.HistoricFailedInteractions 30 31 // Apply the decay of a single block. 32 decay := historicInteractionDecay 33 hsi *= decay 34 hfi *= decay 35 36 // Apply the recent interactions of that single block. Recent interactions 37 // cannot represent more than recentInteractionWeightLimit of historic 38 // interactions, unless there are less than historicInteractionDecayLimit 39 // total interactions, and then the recent interactions cannot count for 40 // more than recentInteractionWeightLimit of the decay limit. 41 rsi := float64(host.RecentSuccessfulInteractions) 42 rfi := float64(host.RecentFailedInteractions) 43 if hsi+hfi > historicInteractionDecayLimit { 44 if rsi+rfi > recentInteractionWeightLimit*(hsi+hfi) { 45 adjustment := recentInteractionWeightLimit * (hsi + hfi) / (rsi + rfi) 46 rsi *= adjustment 47 rfi *= adjustment 48 } 49 } else { 50 if rsi+rfi > recentInteractionWeightLimit*historicInteractionDecayLimit { 51 adjustment := recentInteractionWeightLimit * historicInteractionDecayLimit / (rsi + rfi) 52 rsi *= adjustment 53 rfi *= adjustment 54 } 55 } 56 hsi += rsi 57 hfi += rfi 58 59 // Apply the decay of the rest of the blocks 60 if passedTime > 1 && hsi+hfi > historicInteractionDecayLimit { 61 decay := math.Pow(historicInteractionDecay, float64(passedTime-1)) 62 hsi *= decay 63 hfi *= decay 64 } 65 66 // Set new values 67 host.HistoricSuccessfulInteractions = hsi 68 host.HistoricFailedInteractions = hfi 69 host.RecentSuccessfulInteractions = 0 70 host.RecentFailedInteractions = 0 71 72 // Update the time of the last update 73 host.LastHistoricUpdate = bh 74 } 75 76 // IncrementSuccessfulInteractions increments the number of successful 77 // interactions with a host for a given key 78 func (hdb *HostDB) IncrementSuccessfulInteractions(key types.SiaPublicKey) error { 79 if err := hdb.tg.Add(); err != nil { 80 return errors.AddContext(err, "error adding hostdb threadgroup:") 81 } 82 defer hdb.tg.Done() 83 84 hdb.mu.Lock() 85 defer hdb.mu.Unlock() 86 87 // Fetch the host. 88 host, haveHost := hdb.staticHostTree.Select(key) 89 if !haveHost { 90 return errors.AddContext(errHostNotFoundInTree, "unable to increment successful interaction:") 91 } 92 93 // Update historic values if necessary 94 updateHostHistoricInteractions(&host, hdb.blockHeight) 95 96 // Increment the successful interactions 97 host.RecentSuccessfulInteractions++ 98 hdb.staticHostTree.Modify(host) 99 return nil 100 } 101 102 // IncrementFailedInteractions increments the number of failed interactions with 103 // a host for a given key 104 func (hdb *HostDB) IncrementFailedInteractions(key types.SiaPublicKey) error { 105 if err := hdb.tg.Add(); err != nil { 106 return errors.AddContext(err, "error adding hostdb threadgroup:") 107 } 108 defer hdb.tg.Done() 109 110 // If we are offline it probably wasn't the host's fault 111 if !hdb.staticGateway.Online() { 112 return nil 113 } 114 115 hdb.mu.Lock() 116 defer hdb.mu.Unlock() 117 118 // Fetch the host. 119 host, haveHost := hdb.staticHostTree.Select(key) 120 if !haveHost { 121 return errors.AddContext(errHostNotFoundInTree, "unable to increment failed interaction:") 122 } 123 124 // Update historic values if necessary 125 updateHostHistoricInteractions(&host, hdb.blockHeight) 126 127 // Increment the failed interactions 128 host.RecentFailedInteractions++ 129 hdb.staticHostTree.Modify(host) 130 return nil 131 }