Beispiel #1
0
// maxSectors is the estimated maximum number of sectors that the allowance
// can support.
func maxSectors(a modules.Allowance, hdb hostDB) (uint64, error) {
	if a.Hosts == 0 || a.Period == 0 {
		return 0, errors.New("invalid allowance")
	}

	// Sample at least 10 hosts.
	nRandomHosts := int(a.Hosts)
	if nRandomHosts < 10 {
		nRandomHosts = 10
	}
	hosts := hdb.RandomHosts(nRandomHosts, nil)
	if len(hosts) < int(a.Hosts) {
		return 0, errors.New("not enough hosts")
	}

	// Calculate cost of storing 1 sector per host for the allowance period.
	var sum types.Currency
	for _, h := range hosts {
		sum = sum.Add(h.StoragePrice)
	}
	averagePrice := sum.Div64(uint64(len(hosts)))
	costPerSector := averagePrice.Mul64(a.Hosts).Mul64(modules.SectorSize).Mul64(uint64(a.Period))

	// Divide total funds by cost per sector.
	numSectors, err := a.Funds.Div(costPerSector).Uint64()
	if err != nil {
		// if there was an overflow, something is definitely wrong
		return 0, errors.New("allowance can fund suspiciously large number of sectors")
	}
	return numSectors, nil
}
Beispiel #2
0
// CalculateFee returns the fee-per-byte of a transaction set.
func CalculateFee(ts []types.Transaction) types.Currency {
	var sum types.Currency
	for _, t := range ts {
		for _, fee := range t.MinerFees {
			sum = sum.Add(fee)
		}
	}
	size := len(encoding.Marshal(ts))
	return sum.Div64(uint64(size))
}
Beispiel #3
0
// AverageContractPrice returns the average price of a host.
func (hdb *HostDB) AverageContractPrice() types.Currency {
	// maybe a more sophisticated way of doing this
	var totalPrice types.Currency
	sampleSize := 18
	hosts := hdb.RandomHosts(sampleSize, nil)
	if len(hosts) == 0 {
		return totalPrice
	}
	for _, host := range hosts {
		totalPrice = totalPrice.Add(host.ContractPrice)
	}
	return totalPrice.Div64(uint64(len(hosts)))
}
Beispiel #4
0
// hostcmd is the handler for the command `siac host`.
// Prints info about the host and its storage folders.
func hostcmd() {
	hg := new(api.HostGET)
	err := getAPI("/host", hg)
	if err != nil {
		die("Could not fetch host settings:", err)
	}
	sg := new(api.StorageGET)
	err = getAPI("/host/storage", sg)
	if err != nil {
		die("Could not fetch storage info:", err)
	}

	// Determine the competitive price string.
	ah := new(api.ActiveHosts)
	var competitivePrice string
	err = getAPI("/hostdb/active?numhosts=24", ah)
	if err != nil || len(ah.Hosts) == 0 {
		competitivePrice = "Unavailable"
	} else {
		var sum types.Currency
		for _, host := range ah.Hosts {
			sum = sum.Add(host.StoragePrice)
		}

		// Divide by the number of hosts to get the average price, and then
		// trim 5% to present what would be a competitive edge.
		competitivePrice = currencyUnits(sum.Div64(uint64(len(ah.Hosts))).MulFloat(0.95).Mul(modules.BlockBytesPerMonthTerabyte))
	}

	es := hg.ExternalSettings
	fm := hg.FinancialMetrics
	is := hg.InternalSettings
	nm := hg.NetworkMetrics

	// calculate total storage available and remaining
	var totalstorage, storageremaining uint64
	for _, folder := range sg.Folders {
		totalstorage += folder.Capacity
		storageremaining += folder.CapacityRemaining
	}

	// convert price from bytes/block to TB/Month
	price := currencyUnits(is.MinStoragePrice.Mul(modules.BlockBytesPerMonthTerabyte))
	// calculate total revenue
	totalRevenue := fm.ContractCompensation.
		Add(fm.StorageRevenue).
		Add(fm.DownloadBandwidthRevenue).
		Add(fm.UploadBandwidthRevenue)
	totalPotentialRevenue := fm.PotentialContractCompensation.
		Add(fm.PotentialStorageRevenue).
		Add(fm.PotentialDownloadBandwidthRevenue).
		Add(fm.PotentialUploadBandwidthRevenue)
	// determine the display method for the net address.
	netaddr := es.NetAddress
	if is.NetAddress == "" {
		netaddr += " (automatically determined)"
	} else {
		netaddr += " (manually specified)"
	}

	if hostVerbose {
		// describe net address
		fmt.Printf(`General Info:
	Estimated Competitive Price: %v

Host Internal Settings:
	acceptingcontracts:   %v
	maxduration:          %v Weeks
	maxdownloadbatchsize: %v
	maxrevisebatchsize:   %v
	netaddress:           %v
	windowsize:           %v Hours

	collateral:       %v / TB / Month
	collateralbudget: %v 
	maxcollateral:    %v Per Contract

	mincontractprice:          %v
	mindownloadbandwidthprice: %v / TB
	minstorageprice:           %v / TB / Month
	minuploadbandwidthprice:   %v / TB

Host Financials:
	Contract Count:               %v
	Transaction Fee Compensation: %v
	Potential Fee Compensation:   %v
	Transaction Fee Expenses:     %v

	Storage Revenue:           %v
	Potential Storage Revenue: %v

	Locked Collateral: %v
	Risked Collateral: %v
	Lost Collateral:   %v

	Download Revenue:           %v
	Potential Download Revenue: %v
	Upload Revenue :            %v
	Potential Upload Revenue:   %v

RPC Stats:
	Error Calls:        %v
	Unrecognized Calls: %v
	Download Calls:     %v
	Renew Calls:        %v
	Revise Calls:       %v
	Settings Calls:     %v
	FormContract Calls: %v
`,
			competitivePrice,

			yesNo(is.AcceptingContracts), periodUnits(is.MaxDuration),
			filesizeUnits(int64(is.MaxDownloadBatchSize)),
			filesizeUnits(int64(is.MaxReviseBatchSize)), netaddr,
			is.WindowSize/6,

			currencyUnits(is.Collateral.Mul(modules.BlockBytesPerMonthTerabyte)),
			currencyUnits(is.CollateralBudget),
			currencyUnits(is.MaxCollateral),

			currencyUnits(is.MinContractPrice),
			currencyUnits(is.MinDownloadBandwidthPrice.Mul(modules.BytesPerTerabyte)),
			currencyUnits(is.MinStoragePrice.Mul(modules.BlockBytesPerMonthTerabyte)),
			currencyUnits(is.MinUploadBandwidthPrice.Mul(modules.BytesPerTerabyte)),

			fm.ContractCount, currencyUnits(fm.ContractCompensation),
			currencyUnits(fm.PotentialContractCompensation),
			currencyUnits(fm.TransactionFeeExpenses),

			currencyUnits(fm.StorageRevenue),
			currencyUnits(fm.PotentialStorageRevenue),

			currencyUnits(fm.LockedStorageCollateral),
			currencyUnits(fm.RiskedStorageCollateral),
			currencyUnits(fm.LostStorageCollateral),

			currencyUnits(fm.DownloadBandwidthRevenue),
			currencyUnits(fm.PotentialDownloadBandwidthRevenue),
			currencyUnits(fm.UploadBandwidthRevenue),
			currencyUnits(fm.PotentialUploadBandwidthRevenue),

			nm.ErrorCalls, nm.UnrecognizedCalls, nm.DownloadCalls,
			nm.RenewCalls, nm.ReviseCalls, nm.SettingsCalls,
			nm.FormContractCalls)
	} else {
		fmt.Printf(`Host info:
	Estimated Competitive Price: %v

	Storage:      %v (%v used)
	Price:        %v / TB / Month
	Max Duration: %v Weeks

	Accepting Contracts: %v
	Anticipated Revenue: %v
	Locked Collateral:   %v
	Revenue:             %v
`,
			competitivePrice,

			filesizeUnits(int64(totalstorage)),
			filesizeUnits(int64(totalstorage-storageremaining)), price,
			periodUnits(is.MaxDuration),

			yesNo(is.AcceptingContracts), currencyUnits(totalPotentialRevenue),
			currencyUnits(fm.LockedStorageCollateral),
			currencyUnits(totalRevenue))
	}

	fmt.Println("\nStorage Folders:")

	// display storage folder info
	if len(sg.Folders) == 0 {
		fmt.Println("No storage folders configured")
		return
	}
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 4, ' ', 0)
	fmt.Fprintf(w, "\tUsed\tCapacity\t%% Used\tPath\n")
	for _, folder := range sg.Folders {
		curSize := int64(folder.Capacity - folder.CapacityRemaining)
		pctUsed := 100 * (float64(curSize) / float64(folder.Capacity))
		fmt.Fprintf(w, "\t%s\t%s\t%.2f\t%s\n", filesizeUnits(curSize), filesizeUnits(int64(folder.Capacity)), pctUsed, folder.Path)
	}
	w.Flush()
}