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  }