Commit ef87bb62 authored by Matthew Sevey's avatar Matthew Sevey

Add divde by zero check in price estimation for renter

parent f000a806
......@@ -377,6 +377,13 @@ func (r *Renter) PriceEstimation(allowance modules.Allowance) (modules.RenterPri
numHosts++
}
// Divide by zero check. The only way to get 0 numHosts is if
// RenterPayoutsPreTax errors for every host. This would happend if the
// funding of the allowance is not enough as that would cause the
// fundingPerHost to be less than the contract price
if numHosts == 0 {
return modules.RenterPriceEstimation{}, allowance, errors.New("funding insufficient for number of hosts")
}
// Calculate average collateral and determine collateral for allowance
hostCollateral = hostCollateral.Div64(numHosts)
hostCollateral = hostCollateral.Mul64(allowance.Hosts)
......
......@@ -161,6 +161,63 @@ func (ps pricesStub) RandomHostsWithAllowance(_ int, _, _ []types.SiaPublicKey,
}
func (ps pricesStub) SetIPViolationCheck(enabled bool) { return }
// TestRenterPricesDivideByZero verifies that the Price Estimation catches
// divide by zero errors.
func TestRenterPricesDivideByZero(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
rt, err := newRenterTester(t.Name())
if err != nil {
t.Fatal(err)
}
defer rt.Close()
// Confirm price estimation returns error if there are no hosts available
_, _, err = rt.renter.PriceEstimation(modules.Allowance{})
if err == nil {
t.Fatal("Expected error due to no hosts")
}
// Create a stubbed hostdb, add an entry.
hdb := &pricesStub{}
id := rt.renter.mu.Lock()
rt.renter.hostDB = hdb
rt.renter.mu.Unlock(id)
dbe := modules.HostDBEntry{}
dbe.ContractPrice = types.SiacoinPrecision
dbe.DownloadBandwidthPrice = types.SiacoinPrecision
dbe.UploadBandwidthPrice = types.SiacoinPrecision
dbe.StoragePrice = types.SiacoinPrecision
pk := fastrand.Bytes(crypto.EntropySize)
dbe.PublicKey = types.SiaPublicKey{Key: pk}
hdb.dbEntries = append(hdb.dbEntries, dbe)
// Confirm price estimation does not return an error now that there is a
// host available
_, _, err = rt.renter.PriceEstimation(modules.Allowance{})
if err != nil {
t.Fatal(err)
}
// Set allowance funds and host contract price such that the allowance funds
// are not sufficient to cover the contract price
allowance := modules.Allowance{
Funds: types.SiacoinPrecision,
Hosts: 1,
Period: 12096,
RenewWindow: 4032,
}
dbe.ContractPrice = allowance.Funds.Mul64(2)
// Confirm price estimation returns error because of the contract and
// funding prices
_, _, err = rt.renter.PriceEstimation(allowance)
if err == nil {
t.Fatal("Expected error due to allowance funds inefficient")
}
}
// TestRenterPricesVolatility verifies that the renter caches its price
// estimation, and subsequent calls result in non-volatile results.
func TestRenterPricesVolatility(t *testing.T) {
......
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