github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/renter/hostdb/hostweight_test.go (about) 1 package hostdb 2 3 import ( 4 "testing" 5 "time" 6 7 "SiaPrime/build" 8 "SiaPrime/modules" 9 "SiaPrime/types" 10 ) 11 12 var ( 13 DefaultTestAllowance = modules.Allowance{ 14 Funds: types.SiacoinPrecision.Mul64(500), 15 Hosts: uint64(50), 16 Period: types.BlockHeight(12096), 17 RenewWindow: types.BlockHeight(4032), 18 } 19 ) 20 21 func calculateWeightFromUInt64Price(price, collateral uint64) (weight types.Currency) { 22 hdb := bareHostDB() 23 hdb.SetAllowance(DefaultTestAllowance) 24 hdb.blockHeight = 0 25 var entry modules.HostDBEntry 26 entry.Version = build.Version 27 entry.RemainingStorage = 250e3 28 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 29 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 30 entry.StoragePrice = types.NewCurrency64(price).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 31 entry.Collateral = types.NewCurrency64(collateral).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 32 return hdb.weightFunc(entry) 33 } 34 35 // TestHostWeightDistinctPrices ensures that the host weight is different if the 36 // prices are different, and that a higher price has a lower score. 37 func TestHostWeightDistinctPrices(t *testing.T) { 38 if testing.Short() { 39 t.SkipNow() 40 } 41 weight1 := calculateWeightFromUInt64Price(300, 100) 42 weight2 := calculateWeightFromUInt64Price(301, 100) 43 if weight1.Cmp(weight2) <= 0 { 44 t.Log(weight1) 45 t.Log(weight2) 46 t.Error("Weight of expensive host is not the correct value.") 47 } 48 } 49 50 // TestHostWeightDistinctCollateral ensures that the host weight is different if 51 // the collaterals are different, and that a higher collateral has a higher 52 // score. 53 func TestHostWeightDistinctCollateral(t *testing.T) { 54 if testing.Short() { 55 t.SkipNow() 56 } 57 weight1 := calculateWeightFromUInt64Price(300, 100) 58 weight2 := calculateWeightFromUInt64Price(300, 99) 59 if weight1.Cmp(weight2) <= 0 { 60 t.Log(weight1) 61 t.Log(weight2) 62 t.Error("Weight of expensive host is not the correct value.") 63 } 64 } 65 66 // When the collateral is below the cutoff, the collateral should be more 67 // important than the price. 68 func TestHostWeightCollateralBelowCutoff(t *testing.T) { 69 if testing.Short() { 70 t.SkipNow() 71 } 72 weight1 := calculateWeightFromUInt64Price(300, 10) 73 weight2 := calculateWeightFromUInt64Price(150, 5) 74 if weight1.Cmp(weight2) <= 0 { 75 t.Log(weight1) 76 t.Log(weight2) 77 t.Error("Weight of expensive host is not the correct value.") 78 } 79 } 80 81 // When the collateral is below the cutoff, the price should be more important 82 // than the collateral. 83 func TestHostWeightCollateralAboveCutoff(t *testing.T) { 84 if testing.Short() { 85 t.SkipNow() 86 } 87 weight1 := calculateWeightFromUInt64Price(300, 1000) 88 weight2 := calculateWeightFromUInt64Price(150, 500) 89 if weight1.Cmp(weight2) >= 0 { 90 t.Log(weight1) 91 t.Log(weight2) 92 t.Error("Weight of expensive host is not the correct value.") 93 } 94 } 95 96 // TestHostWeightIdenticalPrices checks that the weight function is 97 // deterministic for two hosts that have identical settings - each should get 98 // the same score. 99 func TestHostWeightIdenticalPrices(t *testing.T) { 100 if testing.Short() { 101 t.SkipNow() 102 } 103 weight1 := calculateWeightFromUInt64Price(42, 100) 104 weight2 := calculateWeightFromUInt64Price(42, 100) 105 if weight1.Cmp(weight2) != 0 { 106 t.Error("Weight of identically priced hosts should be equal.") 107 } 108 } 109 110 // TestHostWeightWithOnePricedZero checks that nothing unexpected happens when 111 // there is a zero price, and also checks that the zero priced host scores 112 // higher than the host that charges money. 113 func TestHostWeightWithOnePricedZero(t *testing.T) { 114 if testing.Short() { 115 t.SkipNow() 116 } 117 weight1 := calculateWeightFromUInt64Price(5, 100) 118 weight2 := calculateWeightFromUInt64Price(0, 100) 119 if weight1.Cmp(weight2) >= 0 { 120 t.Error("Zero-priced host should have higher weight than nonzero-priced host.") 121 } 122 } 123 124 // TestHostWeightBothPricesZero checks that there is nondeterminism in the 125 // weight function even with zero value prices. 126 func TestHostWeightWithBothPricesZero(t *testing.T) { 127 if testing.Short() { 128 t.SkipNow() 129 } 130 weight1 := calculateWeightFromUInt64Price(0, 100) 131 weight2 := calculateWeightFromUInt64Price(0, 100) 132 if weight1.Cmp(weight2) != 0 { 133 t.Error("Weight of two zero-priced hosts should be equal.") 134 } 135 } 136 137 // TestHostWeightWithNoCollateral checks that nothing bad (like a panic) happens 138 // when the collateral is set to zero. 139 func TestHostWeightWithNoCollateral(t *testing.T) { 140 if testing.Short() { 141 t.SkipNow() 142 } 143 weight1 := calculateWeightFromUInt64Price(300, 1) 144 weight2 := calculateWeightFromUInt64Price(300, 0) 145 if weight1.Cmp(weight2) <= 0 { 146 t.Log(weight1) 147 t.Log(weight2) 148 t.Error("Weight of lower priced host should be higher") 149 } 150 } 151 152 // TestHostWeightStorageRemainingDifferences checks that hosts with less storage 153 // remaining have a lower weight. 154 func TestHostWeightStorageRemainingDifferences(t *testing.T) { 155 if testing.Short() { 156 t.SkipNow() 157 } 158 hdb := bareHostDB() 159 var entry modules.HostDBEntry 160 entry.Version = build.Version 161 entry.RemainingStorage = 250e3 162 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 163 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 164 entry.StoragePrice = types.NewCurrency64(100).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 165 entry.Collateral = types.NewCurrency64(300).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 166 167 entry2 := entry 168 entry2.RemainingStorage = 50e3 169 w1 := hdb.weightFunc(entry) 170 w2 := hdb.weightFunc(entry2) 171 172 if w1.Cmp(w2) <= 0 { 173 t.Log(w1) 174 t.Log(w2) 175 t.Error("Larger storage remaining should have more weight") 176 } 177 } 178 179 // TestHostWeightVersionDifferences checks that a host with an out of date 180 // version has a lower score than a host with a more recent version. 181 func TestHostWeightVersionDifferences(t *testing.T) { 182 if testing.Short() { 183 t.SkipNow() 184 } 185 hdb := bareHostDB() 186 var entry modules.HostDBEntry 187 entry.Version = build.Version 188 entry.RemainingStorage = 250e3 189 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 190 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 191 entry.StoragePrice = types.NewCurrency64(100).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 192 entry.Collateral = types.NewCurrency64(300).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 193 194 entry2 := entry 195 entry2.Version = "v1.3.2" 196 w1 := hdb.weightFunc(entry) 197 w2 := hdb.weightFunc(entry2) 198 199 if w1.Cmp(w2) <= 0 { 200 t.Log(w1) 201 t.Log(w2) 202 t.Error("Higher version should have more weight") 203 } 204 } 205 206 // TestHostWeightLifetimeDifferences checks that a host that has been on the 207 // chain for more time has a higher weight than a host that is newer. 208 func TestHostWeightLifetimeDifferences(t *testing.T) { 209 if testing.Short() { 210 t.SkipNow() 211 } 212 hdb := bareHostDB() 213 hdb.blockHeight = 10000 214 var entry modules.HostDBEntry 215 entry.Version = build.Version 216 entry.RemainingStorage = 250e3 217 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 218 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 219 entry.StoragePrice = types.NewCurrency64(100).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 220 entry.Collateral = types.NewCurrency64(300).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 221 222 entry2 := entry 223 entry2.FirstSeen = 8100 224 w1 := hdb.weightFunc(entry) 225 w2 := hdb.weightFunc(entry2) 226 227 if w1.Cmp(w2) <= 0 { 228 t.Log(w1) 229 t.Log(w2) 230 t.Error("Been around longer should have more weight") 231 } 232 } 233 234 // TestHostWeightUptimeDifferences checks that hosts with poorer uptimes have 235 // lower weights. 236 func TestHostWeightUptimeDifferences(t *testing.T) { 237 if testing.Short() { 238 t.SkipNow() 239 } 240 hdb := bareHostDB() 241 hdb.blockHeight = 10000 242 var entry modules.HostDBEntry 243 entry.Version = build.Version 244 entry.RemainingStorage = 250e3 245 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 246 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 247 entry.StoragePrice = types.NewCurrency64(100).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 248 entry.Collateral = types.NewCurrency64(300).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 249 entry.ScanHistory = modules.HostDBScans{ 250 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 251 {Timestamp: time.Now().Add(time.Hour * -80), Success: true}, 252 {Timestamp: time.Now().Add(time.Hour * -60), Success: true}, 253 {Timestamp: time.Now().Add(time.Hour * -40), Success: true}, 254 {Timestamp: time.Now().Add(time.Hour * -20), Success: true}, 255 } 256 257 entry2 := entry 258 entry2.ScanHistory = modules.HostDBScans{ 259 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 260 {Timestamp: time.Now().Add(time.Hour * -80), Success: true}, 261 {Timestamp: time.Now().Add(time.Hour * -60), Success: true}, 262 {Timestamp: time.Now().Add(time.Hour * -40), Success: true}, 263 {Timestamp: time.Now().Add(time.Hour * -20), Success: false}, 264 } 265 w1 := hdb.weightFunc(entry) 266 w2 := hdb.weightFunc(entry2) 267 268 if w1.Cmp(w2) < 0 { 269 t.Log(w1) 270 t.Log(w2) 271 t.Error("Been around longer should have more weight") 272 } 273 } 274 275 // TestHostWeightUptimeDifferences2 checks that hosts with poorer uptimes have 276 // lower weights. 277 func TestHostWeightUptimeDifferences2(t *testing.T) { 278 if testing.Short() { 279 t.SkipNow() 280 } 281 hdb := bareHostDB() 282 hdb.blockHeight = 10000 283 var entry modules.HostDBEntry 284 entry.Version = build.Version 285 entry.RemainingStorage = 250e3 286 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 287 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 288 entry.StoragePrice = types.NewCurrency64(100).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 289 entry.Collateral = types.NewCurrency64(300).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 290 entry.ScanHistory = modules.HostDBScans{ 291 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 292 {Timestamp: time.Now().Add(time.Hour * -80), Success: false}, 293 {Timestamp: time.Now().Add(time.Hour * -60), Success: true}, 294 {Timestamp: time.Now().Add(time.Hour * -40), Success: true}, 295 {Timestamp: time.Now().Add(time.Hour * -20), Success: true}, 296 } 297 298 entry2 := entry 299 entry2.ScanHistory = modules.HostDBScans{ 300 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 301 {Timestamp: time.Now().Add(time.Hour * -80), Success: true}, 302 {Timestamp: time.Now().Add(time.Hour * -60), Success: true}, 303 {Timestamp: time.Now().Add(time.Hour * -40), Success: false}, 304 {Timestamp: time.Now().Add(time.Hour * -20), Success: true}, 305 } 306 w1 := hdb.weightFunc(entry) 307 w2 := hdb.weightFunc(entry2) 308 309 if w1.Cmp(w2) < 0 { 310 t.Errorf("Been around longer should have more weight\n\t%v\n\t%v", w1, w2) 311 } 312 } 313 314 // TestHostWeightUptimeDifferences3 checks that hosts with poorer uptimes have 315 // lower weights. 316 func TestHostWeightUptimeDifferences3(t *testing.T) { 317 if testing.Short() { 318 t.SkipNow() 319 } 320 hdb := bareHostDB() 321 hdb.blockHeight = 10000 322 var entry modules.HostDBEntry 323 entry.Version = build.Version 324 entry.RemainingStorage = 250e3 325 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 326 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 327 entry.StoragePrice = types.NewCurrency64(100).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 328 entry.Collateral = types.NewCurrency64(300).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 329 entry.ScanHistory = modules.HostDBScans{ 330 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 331 {Timestamp: time.Now().Add(time.Hour * -80), Success: false}, 332 {Timestamp: time.Now().Add(time.Hour * -60), Success: true}, 333 {Timestamp: time.Now().Add(time.Hour * -40), Success: true}, 334 {Timestamp: time.Now().Add(time.Hour * -20), Success: true}, 335 } 336 337 entry2 := entry 338 entry2.ScanHistory = modules.HostDBScans{ 339 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 340 {Timestamp: time.Now().Add(time.Hour * -80), Success: false}, 341 {Timestamp: time.Now().Add(time.Hour * -60), Success: false}, 342 {Timestamp: time.Now().Add(time.Hour * -40), Success: true}, 343 {Timestamp: time.Now().Add(time.Hour * -20), Success: true}, 344 } 345 w1 := hdb.weightFunc(entry) 346 w2 := hdb.weightFunc(entry2) 347 348 if w1.Cmp(w2) < 0 { 349 t.Error("Been around longer should have more weight") 350 } 351 } 352 353 // TestHostWeightUptimeDifferences4 checks that hosts with poorer uptimes have 354 // lower weights. 355 func TestHostWeightUptimeDifferences4(t *testing.T) { 356 if testing.Short() { 357 t.SkipNow() 358 } 359 hdb := bareHostDB() 360 hdb.blockHeight = 10000 361 var entry modules.HostDBEntry 362 entry.Version = build.Version 363 entry.RemainingStorage = 250e3 364 entry.MaxCollateral = types.NewCurrency64(1e3).Mul(types.SiacoinPrecision) 365 entry.ContractPrice = types.NewCurrency64(5).Mul(types.SiacoinPrecision) 366 entry.StoragePrice = types.NewCurrency64(100).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 367 entry.Collateral = types.NewCurrency64(300).Mul(types.SiacoinPrecision).Div(modules.BlockBytesPerMonthTerabyte) 368 entry.ScanHistory = modules.HostDBScans{ 369 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 370 {Timestamp: time.Now().Add(time.Hour * -80), Success: true}, 371 {Timestamp: time.Now().Add(time.Hour * -60), Success: true}, 372 {Timestamp: time.Now().Add(time.Hour * -40), Success: true}, 373 {Timestamp: time.Now().Add(time.Hour * -20), Success: false}, 374 } 375 376 entry2 := entry 377 entry2.ScanHistory = modules.HostDBScans{ 378 {Timestamp: time.Now().Add(time.Hour * -100), Success: true}, 379 {Timestamp: time.Now().Add(time.Hour * -80), Success: true}, 380 {Timestamp: time.Now().Add(time.Hour * -60), Success: true}, 381 {Timestamp: time.Now().Add(time.Hour * -40), Success: false}, 382 {Timestamp: time.Now().Add(time.Hour * -20), Success: false}, 383 } 384 w1 := hdb.weightFunc(entry) 385 w2 := hdb.weightFunc(entry2) 386 387 if w1.Cmp(w2) < 0 { 388 t.Error("Been around longer should have more weight") 389 } 390 }