gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter.go (about)

     1  package skymodules
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"math/big"
     9  	"os"
    10  	"sync"
    11  	"time"
    12  
    13  	"gitlab.com/NebulousLabs/errors"
    14  
    15  	"gitlab.com/SkynetLabs/skyd/build"
    16  	"gitlab.com/SkynetLabs/skyd/skykey"
    17  	"go.sia.tech/siad/crypto"
    18  	"go.sia.tech/siad/modules"
    19  	"go.sia.tech/siad/types"
    20  )
    21  
    22  type (
    23  	// ContractParams are supplied as an argument to FormContract.
    24  	ContractParams struct {
    25  		Allowance     Allowance
    26  		Host          HostDBEntry
    27  		Funding       types.Currency
    28  		StartHeight   types.BlockHeight
    29  		EndHeight     types.BlockHeight
    30  		RefundAddress types.UnlockHash
    31  		RenterSeed    EphemeralRenterSeed
    32  
    33  		// TODO: add optional keypair
    34  	}
    35  )
    36  
    37  // WorkerPool is an interface that describes a collection of workers. It's used
    38  // to be able to pass the renter's workers to the contractor.
    39  type WorkerPool interface {
    40  	Worker(types.SiaPublicKey) (Worker, error)
    41  }
    42  
    43  // Worker is a minimal interface for a single worker. It's used to be able to
    44  // use workers within the contractor.
    45  type Worker interface {
    46  	RenewContract(ctx context.Context, fcid types.FileContractID, params ContractParams, txnBuilder modules.TransactionBuilder) (RenterContract, []types.Transaction, error)
    47  }
    48  
    49  var (
    50  	// DefaultAllowance is the set of default allowance settings that will be
    51  	// used when allowances are not set or not fully set
    52  	DefaultAllowance = Allowance{
    53  		Funds:       types.SiacoinPrecision.Mul64(2500),
    54  		Hosts:       uint64(PriceEstimationScope),
    55  		Period:      2 * types.BlocksPerMonth,
    56  		RenewWindow: types.BlocksPerMonth,
    57  
    58  		ExpectedStorage:    1e12,                                         // 1 TB
    59  		ExpectedUpload:     uint64(200e9) / uint64(types.BlocksPerMonth), // 200 GB per month
    60  		ExpectedDownload:   uint64(100e9) / uint64(types.BlocksPerMonth), // 100 GB per month
    61  		ExpectedRedundancy: 3.0,                                          // default is 10/30 erasure coding
    62  		MaxPeriodChurn:     uint64(250e9),                                // 250 GB
    63  	}
    64  
    65  	// DefaultSkynetBaseCost is the default base cost applied to all downloads.
    66  	// The base cost protects us against very cheap (or free) workers as their
    67  	// cost factor doesn't weigh as much. It also directly influences the cost
    68  	// of an overdrive worker, the higher the base cost, the higher the cost of
    69  	// an overdrive.
    70  	DefaultSkynetBaseCost = types.SiacoinPrecision.Mul64(200).Div(types.NewCurrency64(1e12)) // 200SC / TB
    71  
    72  	// ErrHostFault indicates if an error is the host's fault.
    73  	ErrHostFault = errors.New("host has returned an error")
    74  
    75  	// ErrDownloadCancelled is the error set when a download was cancelled
    76  	// manually by the user.
    77  	ErrDownloadCancelled = errors.New("download was cancelled")
    78  
    79  	// ErrNotEnoughWorkersInWorkerPool is an error that is returned whenever an
    80  	// operation expects a certain number of workers but there aren't that many
    81  	// available.
    82  	ErrNotEnoughWorkersInWorkerPool = errors.New("not enough workers in worker pool")
    83  
    84  	// PriceEstimationScope is the number of hosts that get queried by the
    85  	// renter when providing price estimates. Especially for the 'Standard'
    86  	// variable, there should be congruence with the number of contracts being
    87  	// used in the renter allowance.
    88  	PriceEstimationScope = build.Select(build.Var{
    89  		Standard: int(50),
    90  		Dev:      int(12),
    91  		Testing:  int(4),
    92  	}).(int)
    93  	// BackupKeySpecifier is a specifier that is hashed with the wallet seed to
    94  	// create a key for encrypting backups.
    95  	BackupKeySpecifier = types.NewSpecifier("backupkey")
    96  )
    97  
    98  // DataSourceID is an identifier to uniquely identify a data source, such as for
    99  // loading a file. Adding data sources that have the same ID should return the
   100  // exact same data when queried. This is typically used inside of the renter to
   101  // build stream buffers.
   102  type DataSourceID crypto.Hash
   103  
   104  // FilterMode is the helper type for the enum constants for the HostDB filter
   105  // mode
   106  type FilterMode int
   107  
   108  // FileListFunc is a type that's passed in to functions related to iterating
   109  // over the filesystem.
   110  type FileListFunc func(FileInfo)
   111  
   112  // DirListFunc is a type that's passed in to functions related to iterating
   113  // over the filesystem.
   114  type DirListFunc func(DirectoryInfo)
   115  
   116  // RenterPerformance contains a collection of information that can be exported
   117  // from the renter about its performance.
   118  type RenterPerformance struct {
   119  	SystemHealthScanDuration time.Duration
   120  
   121  	BaseSectorDownloadOverdriveStats   *DownloadOverdriveStats
   122  	FanoutSectorDownloadOverdriveStats *DownloadOverdriveStats
   123  
   124  	BaseSectorUploadStats *DistributionTrackerStats
   125  	ChunkUploadStats      *DistributionTrackerStats
   126  	RegistryReadStats     *DistributionTrackerStats
   127  	RegistryWriteStats    *DistributionTrackerStats
   128  	StreamBufferReadStats *DistributionTrackerStats
   129  }
   130  
   131  // DownloadOverdriveStats is a helper struct that contains information about the
   132  // sector downloads, it keeps track of what percentage of downloads we overdrive
   133  // and how many overdrive workers get launched.
   134  type DownloadOverdriveStats struct {
   135  	// total keeps track of the total amount of downloads
   136  	total uint64
   137  
   138  	// overdrive keeps track of the amount of times the download requires one or
   139  	// more overdrive workers to be launched in order to complete
   140  	overdrive uint64
   141  
   142  	// overdriveWorkersLaunched keeps track of the amount of overdrive workers
   143  	// that were launched for a download
   144  	overdriveWorkersLaunched uint64
   145  
   146  	mu sync.Mutex
   147  }
   148  
   149  // OverdriveStats specifies the download overdrive statistics. This includes
   150  // both the base sector and fanout over drive stats.
   151  var OverdriveStats = types.NewSpecifier("overdrive")
   152  
   153  // NewSectorDownloadStats returns a new DownloadOverdriveStats object.
   154  func NewSectorDownloadStats() *DownloadOverdriveStats {
   155  	return &DownloadOverdriveStats{}
   156  }
   157  
   158  // OverdrivePct returns the frequency with which we overdrive when downloading a
   159  // sector. The frequency is expressed as a percentage of overall downloads. E.g.
   160  // an overdrive pct of 0.6 means we launch at least one overdrive worker 60% of
   161  // the time.
   162  func (ds *DownloadOverdriveStats) OverdrivePct() float64 {
   163  	ds.mu.Lock()
   164  	defer ds.mu.Unlock()
   165  
   166  	if ds.total == 0 {
   167  		return 0
   168  	}
   169  	return float64(ds.overdrive) / float64(ds.total)
   170  }
   171  
   172  // NumOverdriveWorkersAvg returns the average amount of overdrive workers we
   173  // launch.
   174  func (ds *DownloadOverdriveStats) NumOverdriveWorkersAvg() float64 {
   175  	ds.mu.Lock()
   176  	defer ds.mu.Unlock()
   177  
   178  	if ds.total == 0 {
   179  		return 0
   180  	}
   181  	return float64(ds.overdriveWorkersLaunched) / float64(ds.total)
   182  }
   183  
   184  // AddDataPoint adds a data point to the statistics, it takes one parameter
   185  // called 'numOverdriveWorkers' which represents the amount of overdrive workers
   186  // launched.
   187  func (ds *DownloadOverdriveStats) AddDataPoint(numOverdriveWorkers uint64) {
   188  	ds.mu.Lock()
   189  	defer ds.mu.Unlock()
   190  
   191  	ds.total++
   192  	ds.overdriveWorkersLaunched += numOverdriveWorkers
   193  	if numOverdriveWorkers > 0 {
   194  		ds.overdrive++
   195  	}
   196  }
   197  
   198  // Reset resets the stats to zero.
   199  func (ds *DownloadOverdriveStats) Reset() {
   200  	ds.mu.Lock()
   201  	defer ds.mu.Unlock()
   202  
   203  	ds.total = 0
   204  	ds.overdrive = 0
   205  	ds.overdriveWorkersLaunched = 0
   206  }
   207  
   208  // RenterStats is a struct which tracks key metrics in a single renter. This
   209  // struct is intended to give a large overview / large dump of data related to
   210  // the renter, which can then be aggregated across a fleet of renters by a
   211  // program which monitors for inconsistencies or other challenges.
   212  type RenterStats struct {
   213  	// A name for this renter.
   214  	Name string `json:"name"`
   215  
   216  	// Any alerts that are in place for this renter.
   217  	Alerts []modules.Alert `json:"alerts"`
   218  
   219  	// The total amount of contract data that hosts are maintaining on behalf of
   220  	// the renter is the sum of these fields.
   221  	ActiveContractData  uint64 `json:"activecontractdata"`
   222  	PassiveContractData uint64 `json:"passivecontractdata"`
   223  	WastedContractData  uint64 `json:"wastedcontractdata"`
   224  
   225  	AggregateLastHealthCheckTime time.Time `json:"aggregatelasthealthchecktime"`
   226  	TotalRepairSize              uint64    `json:"totalrepairsize"`
   227  	TotalSiafiles                uint64    `json:"totalsiafiles"`
   228  	TotalSiadirs                 uint64    `json:"totalsiadirs"`
   229  	TotalSize                    uint64    `json:"totalsize"`
   230  	TotalStuckChunks             uint64    `json:"totalstuckchunks"`
   231  	TotalStuckSize               uint64    `json:"totalstucksize"`
   232  
   233  	TotalContractSpentFunds     types.Currency `json:"totalcontractspentfunds"` // Includes fees
   234  	TotalContractSpentFees      types.Currency `json:"totalcontractspentfees"`
   235  	TotalContractRemainingFunds types.Currency `json:"totalcontractremainingfunds"`
   236  
   237  	Allowance                   Allowance      `json:"allowance"`
   238  	AllowanceUnspentUnallocated types.Currency `json:"allowanceunspentunallocated"`
   239  	WalletFunds                 types.Currency `json:"walletfunds"` // Includes unconfirmed
   240  
   241  	// Information about the status of the memory queue. If the memory is all
   242  	// used up, jobs will start blocking eachother.
   243  	HasRenterMemory         bool `json:"hasrentermemory"`
   244  	HasPriorityRenterMemory bool `json:"haspriorityrentermemory"`
   245  }
   246  
   247  // HostDBFilterError HostDBDisableFilter HostDBActivateBlacklist and
   248  // HostDBActiveWhitelist are the constants used to enable and disable the filter
   249  // mode of the renter's hostdb
   250  const (
   251  	HostDBFilterError FilterMode = iota
   252  	HostDBDisableFilter
   253  	HostDBActivateBlacklist
   254  	HostDBActiveWhitelist
   255  )
   256  
   257  // Filesystem related consts.
   258  const (
   259  	// DefaultDirPerm defines the default permissions used for a new dir if no
   260  	// permissions are supplied. Changing this value is a compatibility issue
   261  	// since users expect dirs to have these permissions.
   262  	DefaultDirPerm = 0755
   263  
   264  	// DefaultFilePerm defines the default permissions used for a new file if no
   265  	// permissions are supplied. Changing this value is a compatibility issue
   266  	// since users expect files to have these permissions.
   267  	DefaultFilePerm = 0644
   268  )
   269  
   270  // String returns the string value for the FilterMode
   271  func (fm FilterMode) String() string {
   272  	switch fm {
   273  	case HostDBFilterError:
   274  		return "error"
   275  	case HostDBDisableFilter:
   276  		return "disable"
   277  	case HostDBActivateBlacklist:
   278  		return "blacklist"
   279  	case HostDBActiveWhitelist:
   280  		return "whitelist"
   281  	default:
   282  		return ""
   283  	}
   284  }
   285  
   286  // FromString assigned the FilterMode from the provide string
   287  func (fm *FilterMode) FromString(s string) error {
   288  	switch s {
   289  	case "disable":
   290  		*fm = HostDBDisableFilter
   291  	case "blacklist":
   292  		*fm = HostDBActivateBlacklist
   293  	case "whitelist":
   294  		*fm = HostDBActiveWhitelist
   295  	default:
   296  		*fm = HostDBFilterError
   297  		return fmt.Errorf("could not assigned FilterMode from string %v", s)
   298  	}
   299  	return nil
   300  }
   301  
   302  // IsHostsFault indicates if a returned error is the host's fault.
   303  func IsHostsFault(err error) bool {
   304  	return errors.Contains(err, ErrHostFault)
   305  }
   306  
   307  const (
   308  	// RenterDir is the name of the directory that is used to store the
   309  	// renter's persistent data.
   310  	RenterDir = "renter"
   311  
   312  	// FileSystemRoot is the name of the directory that is used as the root of
   313  	// the renter's filesystem.
   314  	FileSystemRoot = "fs"
   315  
   316  	// CombinedChunksRoot is the name of the directory that contains combined
   317  	// chunks consisting of multiple partial chunks.
   318  	CombinedChunksRoot = "combinedchunks"
   319  
   320  	// EstimatedFileContractTransactionSetSize is the estimated blockchain size
   321  	// of a transaction set between a renter and a host that contains a file
   322  	// contract. This transaction set will contain a setup transaction from each
   323  	// the host and the renter, and will also contain a file contract and file
   324  	// contract revision that have each been signed by all parties.
   325  	EstimatedFileContractTransactionSetSize = 2048
   326  
   327  	// EstimatedFileContractRevisionAndProofTransactionSetSize is the
   328  	// estimated blockchain size of a transaction set used by the host to
   329  	// provide the storage proof at the end of the contract duration.
   330  	EstimatedFileContractRevisionAndProofTransactionSetSize = 5000
   331  
   332  	// SkynetSpendingHistoryFilename is the name of the file that periodically
   333  	// tracks the part of the renter spending that is elligible for the skynet
   334  	// license fee.
   335  	SkynetSpendingHistoryFilename = "spendinghistory.dat"
   336  
   337  	// StreamDownloadSize is the size of downloaded in a single streaming download
   338  	// request.
   339  	StreamDownloadSize = uint64(1 << 16) // 64 KiB
   340  
   341  	// StreamUploadSize is the size of downloaded in a single streaming upload
   342  	// request.
   343  	StreamUploadSize = uint64(1 << 16) // 64 KiB
   344  )
   345  
   346  type (
   347  	// DownloadID is a unique identifier used to identify downloads within the
   348  	// download history.
   349  	DownloadID string
   350  
   351  	// CombinedChunkID is a unique identifier for a combined chunk which makes up
   352  	// part of its filename on disk.
   353  	CombinedChunkID string
   354  )
   355  
   356  // An Allowance dictates how much the Renter is allowed to spend in a given
   357  // period. Note that funds are spent on both storage and bandwidth.
   358  //
   359  // NOTE: When changing the allowance struct, any new or adjusted fields are
   360  // going to be loaded as blank when the contractor first starts up. The startup
   361  // code either needs to set sane defaults, or the code which depends on the
   362  // values needs to appropriately handle the values being empty.
   363  type Allowance struct {
   364  	Funds       types.Currency    `json:"funds"`
   365  	Hosts       uint64            `json:"hosts"`
   366  	Period      types.BlockHeight `json:"period"`
   367  	RenewWindow types.BlockHeight `json:"renewwindow"`
   368  
   369  	// PaymentContractInitialFunding establishes the amount of money that the a
   370  	// Skynet portal will put into a brand new payment contract. If this value
   371  	// is set to zero, this node will not act as a Skynet portal. When this
   372  	// value is non-zero, this node will act as a Skynet portal, and form
   373  	// contracts with every reasonably priced host.
   374  	PaymentContractInitialFunding types.Currency `json:"paymentcontractinitialfunding"`
   375  
   376  	// ExpectedStorage is the amount of data that we expect to have in a contract.
   377  	ExpectedStorage uint64 `json:"expectedstorage"`
   378  
   379  	// ExpectedUpload is the expected amount of data uploaded through the API,
   380  	// before redundancy, per block.
   381  	ExpectedUpload uint64 `json:"expectedupload"`
   382  
   383  	// ExpectedDownload is the expected amount of data downloaded through the
   384  	// API per block.
   385  	ExpectedDownload uint64 `json:"expecteddownload"`
   386  
   387  	// ExpectedRedundancy is the average redundancy of files being uploaded.
   388  	ExpectedRedundancy float64 `json:"expectedredundancy"`
   389  
   390  	// MaxPeriodChurn is maximum amount of contract churn allowed in a single
   391  	// period.
   392  	MaxPeriodChurn uint64 `json:"maxperiodchurn"`
   393  
   394  	// The following fields provide price gouging protection for the user. By
   395  	// setting a particular maximum price for each mechanism that a host can use
   396  	// to charge users, the workers know to avoid hosts that go outside of the
   397  	// safety range.
   398  	//
   399  	// The intention is that if the fields are not set, a reasonable value will
   400  	// be derived from the other allowance settings. The intention is that the
   401  	// hostdb will pay attention to these limits when forming contracts,
   402  	// understanding that a certain feature (such as storage) will not be used
   403  	// if the host price is above the limit. If the hostdb believes that a host
   404  	// is valuable for its other, more reasonably priced features, the hostdb
   405  	// may choose to form a contract with the host anyway.
   406  	//
   407  	// NOTE: If the allowance max price fields are ever extended, all of the
   408  	// price gouging checks throughout the worker code and contract formation
   409  	// code also need to be extended.
   410  	MaxRPCPrice               types.Currency `json:"maxrpcprice"`
   411  	MaxContractPrice          types.Currency `json:"maxcontractprice"`
   412  	MaxDownloadBandwidthPrice types.Currency `json:"maxdownloadbandwidthprice"`
   413  	MaxSectorAccessPrice      types.Currency `json:"maxsectoraccessprice"`
   414  	MaxStoragePrice           types.Currency `json:"maxstorageprice"`
   415  	MaxUploadBandwidthPrice   types.Currency `json:"maxuploadbandwidthprice"`
   416  }
   417  
   418  // Active returns true if and only if this allowance has been set in the
   419  // contractor.
   420  func (a Allowance) Active() bool {
   421  	return a.Period != 0
   422  }
   423  
   424  // PortalMode returns true if the renter is supposed to act as a portal.
   425  func (a Allowance) PortalMode() bool {
   426  	return !a.PaymentContractInitialFunding.IsZero()
   427  }
   428  
   429  // ContractUtility contains metrics internal to the contractor that reflect the
   430  // utility of a given contract.
   431  type ContractUtility struct {
   432  	GoodForUpload  bool `json:"goodforupload"`
   433  	GoodForRefresh bool `json:"goodforrefresh"`
   434  	GoodForRenew   bool `json:"goodforrenew"`
   435  
   436  	// BadContract will be set to true if there's good reason to believe that
   437  	// the contract is unusable and will continue to be unusable. For example,
   438  	// if the host is claiming that the contract does not exist, the contract
   439  	// should be marked as bad.
   440  	BadContract bool              `json:"badcontract"`
   441  	LastOOSErr  types.BlockHeight `json:"lastooserr"` // OOS means Out Of Storage
   442  
   443  	// If a contract is locked, the utility should not be updated. 'Locked' is a
   444  	// value that gets persisted.
   445  	Locked bool `json:"locked"`
   446  }
   447  
   448  // Merge merges two contract utilities by giving priority to the worse fields.
   449  // So for example a utility that is !gfu that is merged with a utility that is
   450  // gfu will result in !gfu whereas locked and !locked results in locked.
   451  func (cu ContractUtility) Merge(cu2 ContractUtility) ContractUtility {
   452  	lastOOS := cu.LastOOSErr
   453  	if cu2.LastOOSErr > lastOOS {
   454  		lastOOS = cu2.LastOOSErr
   455  	}
   456  	return ContractUtility{
   457  		GoodForUpload:  cu.GoodForUpload && cu2.GoodForUpload,
   458  		GoodForRefresh: cu.GoodForRefresh && cu2.GoodForRefresh,
   459  		GoodForRenew:   cu.GoodForRenew && cu2.GoodForRenew,
   460  		BadContract:    cu.BadContract || cu2.BadContract,
   461  		LastOOSErr:     lastOOS,
   462  		Locked:         cu.Locked || cu2.Locked,
   463  	}
   464  }
   465  
   466  // ContractWatchStatus provides information about the status of a contract in
   467  // the renter's watchdog.
   468  type ContractWatchStatus struct {
   469  	Archived                  bool              `json:"archived"`
   470  	FormationSweepHeight      types.BlockHeight `json:"formationsweepheight"`
   471  	ContractFound             bool              `json:"contractfound"`
   472  	LatestRevisionFound       uint64            `json:"latestrevisionfound"`
   473  	StorageProofFoundAtHeight types.BlockHeight `json:"storageprooffoundatheight"`
   474  	DoubleSpendHeight         types.BlockHeight `json:"doublespendheight"`
   475  	WindowStart               types.BlockHeight `json:"windowstart"`
   476  	WindowEnd                 types.BlockHeight `json:"windowend"`
   477  }
   478  
   479  // DirectoryInfo provides information about a siadir
   480  type DirectoryInfo struct {
   481  	// The following fields are aggregate values of the siadir. These values are
   482  	// the totals of the siadir and any sub siadirs, or are calculated based on
   483  	// all the values in the subtree
   484  	AggregateHealth              float64   `json:"aggregatehealth"`
   485  	AggregateLastHealthCheckTime time.Time `json:"aggregatelasthealthchecktime"`
   486  	AggregateMaxHealth           float64   `json:"aggregatemaxhealth"`
   487  	AggregateMaxHealthPercentage float64   `json:"aggregatemaxhealthpercentage"`
   488  	AggregateMinRedundancy       float64   `json:"aggregateminredundancy"`
   489  	AggregateMostRecentModTime   time.Time `json:"aggregatemostrecentmodtime"`
   490  	AggregateNumFiles            uint64    `json:"aggregatenumfiles"`
   491  	AggregateNumLostFiles        uint64    `json:"aggregatenumlostfiles"`
   492  	AggregateNumStuckChunks      uint64    `json:"aggregatenumstuckchunks"`
   493  	AggregateNumSubDirs          uint64    `json:"aggregatenumsubdirs"`
   494  	AggregateNumUnfinishedFiles  uint64    `json:"aggregatenumunfinishedfiles"`
   495  	AggregateRepairSize          uint64    `json:"aggregaterepairsize"`
   496  	AggregateSize                uint64    `json:"aggregatesize"`
   497  	AggregateStuckHealth         float64   `json:"aggregatestuckhealth"`
   498  	AggregateStuckSize           uint64    `json:"aggregatestucksize"`
   499  
   500  	// Skynet Fields
   501  	AggregateSkynetFiles uint64 `json:"aggregateskynetfiles"`
   502  	AggregateSkynetSize  uint64 `json:"aggregateskynetsize"`
   503  
   504  	// The following fields are information specific to the siadir that is not
   505  	// an aggregate of the entire sub directory tree
   506  	Health              float64     `json:"health"`
   507  	LastHealthCheckTime time.Time   `json:"lasthealthchecktime"`
   508  	MaxHealthPercentage float64     `json:"maxhealthpercentage"`
   509  	MaxHealth           float64     `json:"maxhealth"`
   510  	MinRedundancy       float64     `json:"minredundancy"`
   511  	DirMode             os.FileMode `json:"mode,siamismatch"` // Field is called DirMode for fuse compatibility
   512  	MostRecentModTime   time.Time   `json:"mostrecentmodtime"`
   513  	NumFiles            uint64      `json:"numfiles"`
   514  	NumLostFiles        uint64      `json:"numlostfiles"`
   515  	NumStuckChunks      uint64      `json:"numstuckchunks"`
   516  	NumSubDirs          uint64      `json:"numsubdirs"`
   517  	NumUnfinishedFiles  uint64      `json:"numunfinishedfiles"`
   518  	RepairSize          uint64      `json:"repairsize"`
   519  	SiaPath             SiaPath     `json:"siapath"`
   520  	DirSize             uint64      `json:"size,siamismatch"` // Stays as 'size' in json for compatibility
   521  	StuckHealth         float64     `json:"stuckhealth"`
   522  	StuckSize           uint64      `json:"stucksize"`
   523  	UID                 uint64      `json:"uid"`
   524  
   525  	// Skynet Fields
   526  	SkynetFiles uint64 `json:"skynetfiles"`
   527  	SkynetSize  uint64 `json:"skynetsize"`
   528  }
   529  
   530  // Name implements os.FileInfo.
   531  func (d DirectoryInfo) Name() string { return d.SiaPath.Name() }
   532  
   533  // Size implements os.FileInfo.
   534  func (d DirectoryInfo) Size() int64 { return int64(d.DirSize) }
   535  
   536  // Mode implements os.FileInfo.
   537  func (d DirectoryInfo) Mode() os.FileMode { return d.DirMode }
   538  
   539  // ModTime implements os.FileInfo.
   540  func (d DirectoryInfo) ModTime() time.Time { return d.MostRecentModTime }
   541  
   542  // IsDir implements os.FileInfo.
   543  func (d DirectoryInfo) IsDir() bool { return true }
   544  
   545  // Sys implements os.FileInfo.
   546  func (d DirectoryInfo) Sys() interface{} { return nil }
   547  
   548  // DownloadInfo provides information about a file that has been requested for
   549  // download.
   550  type DownloadInfo struct {
   551  	Destination     string  `json:"destination"`     // The destination of the download.
   552  	DestinationType string  `json:"destinationtype"` // Can be "file", "memory buffer", or "http stream".
   553  	Length          uint64  `json:"length"`          // The length requested for the download.
   554  	Offset          uint64  `json:"offset"`          // The offset within the siafile requested for the download.
   555  	SiaPath         SiaPath `json:"siapath"`         // The siapath of the file used for the download.
   556  
   557  	Completed            bool      `json:"completed"`            // Whether or not the download has completed.
   558  	EndTime              time.Time `json:"endtime"`              // The time when the download fully completed.
   559  	Error                string    `json:"error"`                // Will be the empty string unless there was an error.
   560  	Received             uint64    `json:"received"`             // Amount of data confirmed and decoded.
   561  	StartTime            time.Time `json:"starttime"`            // The time when the download was started.
   562  	StartTimeUnix        int64     `json:"starttimeunix"`        // The time when the download was started in unix format.
   563  	TotalDataTransferred uint64    `json:"totaldatatransferred"` // Total amount of data transferred, including negotiation, etc.
   564  }
   565  
   566  // FileUploadParams contains the information used by the Renter to upload a
   567  // file.
   568  type FileUploadParams struct {
   569  	Source      string
   570  	SiaPath     SiaPath
   571  	ErasureCode ErasureCoder
   572  	Force       bool
   573  	Repair      bool
   574  
   575  	// CipherType was added later. If it is left blank, the renter will use the
   576  	// default encryption method (as of writing, Threefish)
   577  	CipherType crypto.CipherType
   578  
   579  	// CipherKey was added in v1.5.0. If it is left blank, the renter will use it
   580  	// to create a CipherKey with the given CipherType. This value override
   581  	// CipherType if it is set.
   582  	CipherKey crypto.CipherKey
   583  }
   584  
   585  // FileInfo provides information about a file.
   586  type FileInfo struct {
   587  	AccessTime       time.Time         `json:"accesstime"`
   588  	Available        bool              `json:"available"`
   589  	ChangeTime       time.Time         `json:"changetime"`
   590  	CipherType       string            `json:"ciphertype"`
   591  	CreateTime       time.Time         `json:"createtime"`
   592  	Expiration       types.BlockHeight `json:"expiration"`
   593  	Filesize         uint64            `json:"filesize"`
   594  	Finished         bool              `json:"finished"`
   595  	Health           float64           `json:"health"`
   596  	LocalPath        string            `json:"localpath"`
   597  	Lost             bool              `json:"lost"`
   598  	MaxHealth        float64           `json:"maxhealth"`
   599  	MaxHealthPercent float64           `json:"maxhealthpercent"`
   600  	ModificationTime time.Time         `json:"modtime,siamismatch"` // Stays as 'modtime' in json for compatibility
   601  	FileMode         os.FileMode       `json:"mode,siamismatch"`    // Field is called FileMode for fuse compatibility
   602  	NumStuckChunks   uint64            `json:"numstuckchunks"`
   603  	OnDisk           bool              `json:"ondisk"`
   604  	Recoverable      bool              `json:"recoverable"`
   605  	Redundancy       float64           `json:"redundancy"`
   606  	Renewing         bool              `json:"renewing"`
   607  	RepairBytes      uint64            `json:"repairbytes"`
   608  	Skylinks         []string          `json:"skylinks"`
   609  	SiaPath          SiaPath           `json:"siapath"`
   610  	Stuck            bool              `json:"stuck"`
   611  	StuckBytes       uint64            `json:"stuckbytes"`
   612  	StuckHealth      float64           `json:"stuckhealth"`
   613  	UID              uint64            `json:"uid"`
   614  	UploadedBytes    uint64            `json:"uploadedbytes"`
   615  	UploadProgress   float64           `json:"uploadprogress"`
   616  }
   617  
   618  // Name implements os.FileInfo.
   619  func (f FileInfo) Name() string { return f.SiaPath.Name() }
   620  
   621  // Size implements os.FileInfo.
   622  func (f FileInfo) Size() int64 { return int64(f.Filesize) }
   623  
   624  // Mode implements os.FileInfo.
   625  func (f FileInfo) Mode() os.FileMode { return f.FileMode }
   626  
   627  // ModTime implements os.FileInfo.
   628  func (f FileInfo) ModTime() time.Time { return f.ModificationTime }
   629  
   630  // IsDir implements os.FileInfo.
   631  func (f FileInfo) IsDir() bool { return false }
   632  
   633  // Sys implements os.FileInfo.
   634  func (f FileInfo) Sys() interface{} { return nil }
   635  
   636  // A HostDBEntry represents one host entry in the Renter's host DB. It
   637  // aggregates the host's external settings and metrics with its public key.
   638  type HostDBEntry struct {
   639  	modules.HostExternalSettings
   640  
   641  	// FirstSeen is the last block height at which this host was announced.
   642  	FirstSeen types.BlockHeight `json:"firstseen"`
   643  
   644  	// Measurements that have been taken on the host. The most recent
   645  	// measurements are kept in full detail, historic ones are compressed into
   646  	// the historic values.
   647  	HistoricDowntime time.Duration `json:"historicdowntime"`
   648  	HistoricUptime   time.Duration `json:"historicuptime"`
   649  	ScanHistory      HostDBScans   `json:"scanhistory"`
   650  
   651  	// Measurements that are taken whenever we interact with a host.
   652  	HistoricFailedInteractions     float64 `json:"historicfailedinteractions"`
   653  	HistoricSuccessfulInteractions float64 `json:"historicsuccessfulinteractions"`
   654  	RecentFailedInteractions       float64 `json:"recentfailedinteractions"`
   655  	RecentSuccessfulInteractions   float64 `json:"recentsuccessfulinteractions"`
   656  
   657  	LastHistoricUpdate types.BlockHeight `json:"lasthistoricupdate"`
   658  
   659  	// Measurements related to the IP subnet mask.
   660  	IPNets          []string  `json:"ipnets"`
   661  	LastIPNetChange time.Time `json:"lastipnetchange"`
   662  
   663  	// Malicious indicates whether the host is considered to be a malicous
   664  	// host by the hostdb.
   665  	Malicious bool `json:"malicious"`
   666  
   667  	// The public key of the host, stored separately to minimize risk of certain
   668  	// MitM based vulnerabilities.
   669  	PublicKey types.SiaPublicKey `json:"publickey"`
   670  
   671  	// Filtered says whether or not a HostDBEntry is being filtered out of the
   672  	// filtered hosttree due to the filter mode of the hosttree
   673  	Filtered bool `json:"filtered"`
   674  }
   675  
   676  // DecoratedHostDBEntry wraps a host db entry and adds a price table.
   677  type DecoratedHostDBEntry struct {
   678  	HostDBEntry
   679  
   680  	// PriceTable is the host's most recent price table. This can be nil as the
   681  	// price tables are kept in-memory and get updated on the host db by the
   682  	// individual workers
   683  	PriceTable *modules.RPCPriceTable
   684  }
   685  
   686  // HostDBScan represents a single scan event.
   687  type HostDBScan struct {
   688  	Timestamp time.Time `json:"timestamp"`
   689  	Success   bool      `json:"success"`
   690  }
   691  
   692  // HostScoreBreakdown provides a piece-by-piece explanation of why a host has
   693  // the score that they do.
   694  //
   695  // NOTE: Renters are free to use whatever scoring they feel appropriate for
   696  // hosts. Some renters will outright blacklist or whitelist sets of hosts. The
   697  // results provided by this struct can only be used as a guide, and may vary
   698  // significantly from machine to machine.
   699  type HostScoreBreakdown struct {
   700  	Score          types.Currency `json:"score"`
   701  	ConversionRate float64        `json:"conversionrate"`
   702  
   703  	AcceptContractAdjustment   float64 `json:"acceptcontractadjustment"`
   704  	AgeAdjustment              float64 `json:"ageadjustment"`
   705  	BasePriceAdjustment        float64 `json:"basepriceadjustment"`
   706  	BurnAdjustment             float64 `json:"burnadjustment"`
   707  	CollateralAdjustment       float64 `json:"collateraladjustment"`
   708  	DurationAdjustment         float64 `json:"durationadjustment"`
   709  	InteractionAdjustment      float64 `json:"interactionadjustment"`
   710  	PriceAdjustment            float64 `json:"pricesmultiplier,siamismatch"`
   711  	StorageRemainingAdjustment float64 `json:"storageremainingadjustment"`
   712  	UptimeAdjustment           float64 `json:"uptimeadjustment"`
   713  	VersionAdjustment          float64 `json:"versionadjustment"`
   714  }
   715  
   716  // MemoryStatus contains information about the status of the memory managers in
   717  // the renter.
   718  type MemoryStatus struct {
   719  	MemoryManagerStatus
   720  
   721  	Registry     MemoryManagerStatus `json:"registry"`
   722  	UserUpload   MemoryManagerStatus `json:"userupload"`
   723  	UserDownload MemoryManagerStatus `json:"userdownload"`
   724  	System       MemoryManagerStatus `json:"system"`
   725  }
   726  
   727  // MemoryManagerStatus contains the memory status of a single memory manager.
   728  type MemoryManagerStatus struct {
   729  	Available uint64 `json:"available"`
   730  	Base      uint64 `json:"base"`
   731  	Requested uint64 `json:"requested"`
   732  
   733  	PriorityAvailable uint64 `json:"priorityavailable"`
   734  	PriorityBase      uint64 `json:"prioritybase"`
   735  	PriorityRequested uint64 `json:"priorityrequested"`
   736  	PriorityReserve   uint64 `json:"priorityreserve"`
   737  }
   738  
   739  // Add combines two MemoryManagerStatus objects into one.
   740  func (ms MemoryManagerStatus) Add(ms2 MemoryManagerStatus) MemoryManagerStatus {
   741  	return MemoryManagerStatus{
   742  		Available:         ms.Available + ms2.Available,
   743  		Base:              ms.Base + ms2.Base,
   744  		Requested:         ms.Requested + ms2.Requested,
   745  		PriorityAvailable: ms.PriorityAvailable + ms2.PriorityAvailable,
   746  		PriorityBase:      ms.PriorityBase + ms2.PriorityBase,
   747  		PriorityRequested: ms.PriorityRequested + ms2.PriorityRequested,
   748  		PriorityReserve:   ms.PriorityReserve + ms2.PriorityReserve,
   749  	}
   750  }
   751  
   752  // MountInfo contains information about a mounted FUSE filesystem.
   753  type MountInfo struct {
   754  	MountPoint string  `json:"mountpoint"`
   755  	SiaPath    SiaPath `json:"siapath"`
   756  
   757  	MountOptions MountOptions `json:"mountoptions"`
   758  }
   759  
   760  // RenterPriceEstimation contains a bunch of files estimating the costs of
   761  // various operations on the network.
   762  type RenterPriceEstimation struct {
   763  	// The cost of downloading 1 TB of data.
   764  	DownloadTerabyte types.Currency `json:"downloadterabyte"`
   765  
   766  	// The cost of forming a set of contracts using the defaults.
   767  	FormContracts types.Currency `json:"formcontracts"`
   768  
   769  	// The cost of storing 1 TB for a month, including redundancy.
   770  	StorageTerabyteMonth types.Currency `json:"storageterabytemonth"`
   771  
   772  	// The cost of consuming 1 TB of upload bandwidth from the host, including
   773  	// redundancy.
   774  	UploadTerabyte types.Currency `json:"uploadterabyte"`
   775  }
   776  
   777  // RenterSettings control the behavior of the Renter.
   778  type RenterSettings struct {
   779  	Allowance        Allowance     `json:"allowance"`
   780  	IPViolationCheck bool          `json:"ipviolationcheck"`
   781  	MaxUploadSpeed   int64         `json:"maxuploadspeed"`
   782  	MaxDownloadSpeed int64         `json:"maxdownloadspeed"`
   783  	UploadsStatus    UploadsStatus `json:"uploadsstatus"`
   784  }
   785  
   786  // UploadsStatus contains information about the Renter's Uploads
   787  type UploadsStatus struct {
   788  	Paused       bool      `json:"paused"`
   789  	PauseEndTime time.Time `json:"pauseendtime"`
   790  }
   791  
   792  // HostDBScans represents a sortable slice of scans.
   793  type HostDBScans []HostDBScan
   794  
   795  func (s HostDBScans) Len() int           { return len(s) }
   796  func (s HostDBScans) Less(i, j int) bool { return s[i].Timestamp.Before(s[j].Timestamp) }
   797  func (s HostDBScans) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   798  
   799  // MerkleRootSet is a set of Merkle roots, and gets encoded more efficiently.
   800  type MerkleRootSet []crypto.Hash
   801  
   802  // MarshalJSON defines a JSON encoding for a MerkleRootSet.
   803  func (mrs MerkleRootSet) MarshalJSON() ([]byte, error) {
   804  	// Copy the whole array into a giant byte slice and then encode that.
   805  	fullBytes := make([]byte, crypto.HashSize*len(mrs))
   806  	for i := range mrs {
   807  		copy(fullBytes[i*crypto.HashSize:(i+1)*crypto.HashSize], mrs[i][:])
   808  	}
   809  	return json.Marshal(fullBytes)
   810  }
   811  
   812  // ChunkSize is a helper to compute the size of a chunk given the used cipher
   813  // type and data pieces.
   814  func ChunkSize(ct crypto.CipherType, dataPieces uint64) uint64 {
   815  	pieceSize := modules.SectorSize - ct.Overhead()
   816  	return pieceSize * dataPieces
   817  }
   818  
   819  // NumChunks returns the number of chunks a file has given its CipherType, size
   820  // and number of data pieces.
   821  func NumChunks(ct crypto.CipherType, fileSize, dataPieces uint64) uint64 {
   822  	chunkSize := ChunkSize(ct, dataPieces)
   823  	numChunks := fileSize / chunkSize
   824  	if fileSize%chunkSize != 0 {
   825  		numChunks++
   826  	}
   827  	return numChunks
   828  }
   829  
   830  // UnmarshalJSON attempts to decode a MerkleRootSet, falling back on the legacy
   831  // decoding of a []crypto.Hash if that fails.
   832  func (mrs *MerkleRootSet) UnmarshalJSON(b []byte) error {
   833  	// Decode the giant byte slice, and then split it into separate arrays.
   834  	var fullBytes []byte
   835  	err := json.Unmarshal(b, &fullBytes)
   836  	if err != nil {
   837  		// Encoding the byte slice has failed, try decoding it as a []crypto.Hash.
   838  		var hashes []crypto.Hash
   839  		err := json.Unmarshal(b, &hashes)
   840  		if err != nil {
   841  			return err
   842  		}
   843  		*mrs = MerkleRootSet(hashes)
   844  		return nil
   845  	}
   846  
   847  	umrs := make(MerkleRootSet, len(fullBytes)/32)
   848  	for i := range umrs {
   849  		copy(umrs[i][:], fullBytes[i*crypto.HashSize:(i+1)*crypto.HashSize])
   850  	}
   851  	*mrs = umrs
   852  	return nil
   853  }
   854  
   855  // MountOptions specify various settings of a FUSE filesystem mount.
   856  type MountOptions struct {
   857  	AllowOther bool `json:"allowother"`
   858  	ReadOnly   bool `json:"readonly"`
   859  }
   860  
   861  // RecoverableContract is a types.FileContract as it appears on the blockchain
   862  // with additional fields which contain the information required to recover its
   863  // latest revision from a host.
   864  type RecoverableContract struct {
   865  	types.FileContract
   866  	// ID is the FileContract's ID.
   867  	ID types.FileContractID `json:"id"`
   868  	// HostPublicKey is the public key of the host we formed this contract
   869  	// with.
   870  	HostPublicKey types.SiaPublicKey `json:"hostpublickey"`
   871  	// InputParentID is the ParentID of the first SiacoinInput of the
   872  	// transaction that contains this contract.
   873  	InputParentID types.SiacoinOutputID `json:"inputparentid"`
   874  	// StartHeight is the estimated startheight of a recoverable contract.
   875  	StartHeight types.BlockHeight `json:"startheight"`
   876  	// TxnFee of the transaction which contains the contract.
   877  	TxnFee types.Currency `json:"txnfee"`
   878  }
   879  
   880  // A RenterContract contains metadata about a file contract. It is read-only;
   881  // modifying a RenterContract does not modify the actual file contract.
   882  type RenterContract struct {
   883  	ID            types.FileContractID
   884  	HostPublicKey types.SiaPublicKey
   885  	Transaction   types.Transaction
   886  
   887  	StartHeight types.BlockHeight
   888  	EndHeight   types.BlockHeight
   889  
   890  	// RenterFunds is the amount remaining in the contract that the renter can
   891  	// spend.
   892  	RenterFunds types.Currency
   893  
   894  	// The FileContract does not indicate what funds were spent on, so we have
   895  	// to track the various costs manually.
   896  	DownloadSpending    types.Currency
   897  	FundAccountSpending types.Currency
   898  	MaintenanceSpending MaintenanceSpending
   899  	StorageSpending     types.Currency
   900  	UploadSpending      types.Currency
   901  
   902  	// Utility contains utility information about the renter.
   903  	Utility ContractUtility
   904  
   905  	// TotalCost indicates the amount of money that the renter spent and/or
   906  	// locked up while forming a contract. This includes fees, and includes
   907  	// funds which were allocated (but not necessarily committed) to spend on
   908  	// uploads/downloads/storage.
   909  	TotalCost types.Currency
   910  
   911  	// ContractFee is the amount of money paid to the host to cover potential
   912  	// future transaction fees that the host may incur, and to cover any other
   913  	// overheads the host may have.
   914  	//
   915  	// TxnFee is the amount of money spent on the transaction fee when putting
   916  	// the renter contract on the blockchain.
   917  	//
   918  	// SiafundFee is the amount of money spent on siafund fees when creating the
   919  	// contract. The siafund fee that the renter pays covers both the renter and
   920  	// the host portions of the contract, and therefore can be unexpectedly high
   921  	// if the the host collateral is high.
   922  	ContractFee types.Currency
   923  	TxnFee      types.Currency
   924  	SiafundFee  types.Currency
   925  }
   926  
   927  // SpendingDetails is a helper struct that contains a breakdown of where exactly
   928  // the money was spent. The MaintenanceSpending field is an aggregate of costs
   929  // spent on RHP3 maintenance, this includes updating the price table, syncing
   930  // the account balance, etc.
   931  type SpendingDetails struct {
   932  	DownloadSpending    types.Currency
   933  	FundAccountSpending types.Currency
   934  	MaintenanceSpending MaintenanceSpending
   935  	StorageSpending     types.Currency
   936  	UploadSpending      types.Currency
   937  }
   938  
   939  // AccountSpending is a helper struct that contains a breakdown of all spending
   940  // costs within an ephemeral account
   941  type AccountSpending struct {
   942  	AccountBalanceCost    types.Currency `json:"accountbalancecost"`
   943  	DownloadsCost         types.Currency `json:"downloadscost"`
   944  	RegistryReadsCost     types.Currency `json:"registryreadscost"`
   945  	RegistryWritesCost    types.Currency `json:"registrywritescost"`
   946  	RepairDownloadsCost   types.Currency `json:"repairdownloadscost"`
   947  	RepairUploadsCost     types.Currency `json:"repairuploadscost"`
   948  	SnapshotDownloadsCost types.Currency `json:"snapshotdownloadscost"`
   949  	SnapshotUploadsCost   types.Currency `json:"snapshotuploadscost"`
   950  	SubscriptionsCost     types.Currency `json:"subscriptionscost"`
   951  	UpdatePriceTableCost  types.Currency `json:"updatepricetablecost"`
   952  	UploadsCost           types.Currency `json:"uploadscost"`
   953  
   954  	// Balance is the current balance in the ephermal account
   955  	Balance types.Currency `json:"balance"`
   956  
   957  	// BalanceDrift is the amount of money with which the balance is off of what
   958  	// we expected it to be, this can be either in the positive or negative
   959  	// direction. We have a drift because we sync our balance with the host
   960  	// balance, meaning that we essentially reset to the host's version, at the
   961  	// time we do that we record the drift in either direction to eventually
   962  	// gouge the host if we notice he's consistently cheating us out of small
   963  	// amounts of money.
   964  	BalanceDrift big.Int `json:"balancedrift"`
   965  
   966  	// Residue is the amount of money in the account at the time the contract
   967  	// renewed and the spending fields for the corresponding contract go back to
   968  	// 0. We need the residue to properly break down the spending in the next
   969  	// period.
   970  	Residue types.Currency `json:"residue"`
   971  }
   972  
   973  // Add returns a new account spending struct where all the fields are the sum of
   974  // the struct and the given account spending.
   975  func (as AccountSpending) Add(other AccountSpending) (a AccountSpending) {
   976  	a.AccountBalanceCost = as.AccountBalanceCost.Add(other.AccountBalanceCost)
   977  	a.DownloadsCost = as.DownloadsCost.Add(other.DownloadsCost)
   978  	a.RegistryReadsCost = as.RegistryReadsCost.Add(other.RegistryReadsCost)
   979  	a.RegistryWritesCost = as.RegistryWritesCost.Add(other.RegistryWritesCost)
   980  	a.RepairDownloadsCost = as.RepairDownloadsCost.Add(other.RepairDownloadsCost)
   981  	a.RepairUploadsCost = as.RepairUploadsCost.Add(other.RepairUploadsCost)
   982  	a.SnapshotDownloadsCost = as.SnapshotDownloadsCost.Add(other.SnapshotDownloadsCost)
   983  	a.SnapshotUploadsCost = as.SnapshotUploadsCost.Add(other.SnapshotUploadsCost)
   984  	a.SubscriptionsCost = as.SubscriptionsCost.Add(other.SubscriptionsCost)
   985  	a.UpdatePriceTableCost = as.UpdatePriceTableCost.Add(other.UpdatePriceTableCost)
   986  	a.UploadsCost = as.UploadsCost.Add(other.UploadsCost)
   987  
   988  	a.Balance = as.Balance.Add(other.Balance)
   989  	a.BalanceDrift.Add(&as.BalanceDrift, &other.BalanceDrift)
   990  	a.Residue = as.Residue.Add(other.Residue)
   991  
   992  	return a
   993  }
   994  
   995  // Sum is the sum of all fields
   996  func (as AccountSpending) Sum() types.Currency {
   997  	var total types.Currency
   998  	total = total.Add(as.AccountBalanceCost)
   999  	total = total.Add(as.DownloadsCost)
  1000  	total = total.Add(as.RegistryReadsCost)
  1001  	total = total.Add(as.RegistryWritesCost)
  1002  	total = total.Add(as.RepairDownloadsCost)
  1003  	total = total.Add(as.RepairUploadsCost)
  1004  	total = total.Add(as.SnapshotDownloadsCost)
  1005  	total = total.Add(as.SnapshotUploadsCost)
  1006  	total = total.Add(as.SubscriptionsCost)
  1007  	total = total.Add(as.UpdatePriceTableCost)
  1008  	total = total.Add(as.UploadsCost)
  1009  	return total
  1010  }
  1011  
  1012  // EphemeralAccountSpending embeds AccountSpending and adds a host key. The host
  1013  // key is added in a separate struct to be able to use the account spending
  1014  // struct as an aggregate across all hosts
  1015  type EphemeralAccountSpending struct {
  1016  	AccountSpending
  1017  
  1018  	HostKey types.SiaPublicKey `json:"hostkey"`
  1019  }
  1020  
  1021  // MaintenanceSpending is a helper struct that contains a breakdown of costs
  1022  // related to the maintenance (a.k.a upkeep) of the RHP3 protocol. This includes
  1023  // the costs to sync the account balance, update the price table, etc.
  1024  type MaintenanceSpending struct {
  1025  	AccountBalanceCost   types.Currency `json:"accountbalancecost"`
  1026  	FundAccountCost      types.Currency `json:"fundaccountcost"`
  1027  	UpdatePriceTableCost types.Currency `json:"updatepricetablecost"`
  1028  }
  1029  
  1030  // Add is a convenience function that sums the fields of the spending object
  1031  // with the corresponding fields of the given object.
  1032  func (x MaintenanceSpending) Add(y MaintenanceSpending) MaintenanceSpending {
  1033  	return MaintenanceSpending{
  1034  		AccountBalanceCost:   x.AccountBalanceCost.Add(y.AccountBalanceCost),
  1035  		FundAccountCost:      x.FundAccountCost.Add(y.FundAccountCost),
  1036  		UpdatePriceTableCost: x.UpdatePriceTableCost.Add(y.UpdatePriceTableCost),
  1037  	}
  1038  }
  1039  
  1040  // Sum is a convenience function that sums up all of the fields in the spending
  1041  // object and returns the total as a types.Currency.
  1042  func (x MaintenanceSpending) Sum() types.Currency {
  1043  	return x.AccountBalanceCost.Add(x.FundAccountCost).Add(x.UpdatePriceTableCost)
  1044  }
  1045  
  1046  // Size returns the contract size
  1047  func (rc *RenterContract) Size() uint64 {
  1048  	var size uint64
  1049  	if len(rc.Transaction.FileContractRevisions) != 0 {
  1050  		size = rc.Transaction.FileContractRevisions[0].NewFileSize
  1051  	}
  1052  	return size
  1053  }
  1054  
  1055  // SkynetSpending return the sum of all spending of the contract that is subject
  1056  // to skynet fees.
  1057  //
  1058  // NOTE: updating this method requires a change to the 'SkynetFee' on the
  1059  // ContractorSpending struct
  1060  func (rc *RenterContract) SkynetSpending() (spending types.Currency) {
  1061  	spending = spending.Add(rc.DownloadSpending)
  1062  	spending = spending.Add(rc.FundAccountSpending)
  1063  	spending = spending.Add(rc.MaintenanceSpending.Sum())
  1064  	spending = spending.Add(rc.StorageSpending)
  1065  	spending = spending.Add(rc.UploadSpending)
  1066  	spending = spending.Add(rc.ContractFee)
  1067  	spending = spending.Add(rc.TxnFee)
  1068  	spending = spending.Add(rc.SiafundFee)
  1069  	return
  1070  }
  1071  
  1072  // FinancialMetrics wraps the contractor spending and adds the ephermal account
  1073  // spending, which contains a breakdown of the FundAccountSpending per spending
  1074  // category, e.g. downloads, uploads, registry reads etc.
  1075  type FinancialMetrics struct {
  1076  	// ContractorSpending contains the metrics about how much the Contractor has
  1077  	// spent during the current billing period.
  1078  	ContractorSpending
  1079  
  1080  	// EphemeralAccountSpending shows a breakdown of the money being spent from
  1081  	// all accounts in the renter.
  1082  	EphemeralAccountSpending []EphemeralAccountSpending `json:"ephemeralaccountspending"`
  1083  
  1084  	// SkynetFee is the amount of money spent on Skynet fees. Which is 20% of
  1085  	// all contract expenditures that are subject to skynet fees.
  1086  	//
  1087  	// NOTE: this is the money that is eventually going to be spent, since we
  1088  	// pay the skynet fee in 24h intervals the total amount might have not been
  1089  	// spent yet.
  1090  	SkynetFee types.Currency `json:"skynetfee"`
  1091  }
  1092  
  1093  // ContractorSpending contains the metrics about how much the Contractor has
  1094  // spent during the current billing period.
  1095  type ContractorSpending struct {
  1096  	// DownloadSpending is the money currently spent on downloads.
  1097  	DownloadSpending types.Currency `json:"downloadspending"`
  1098  	// Fees is the money currently spent on fees.
  1099  	Fees Fees `json:"fees"`
  1100  	// FundAccountSpending is the money used to fund an ephemeral account on the
  1101  	// host.
  1102  	FundAccountSpending types.Currency `json:"fundaccountspending"`
  1103  	// MaintenanceSpending is the money spent on maintenance tasks in support of
  1104  	// the RHP3 protocol, this includes updating the price table as well as
  1105  	// syncing the ephemeral account balance.
  1106  	MaintenanceSpending MaintenanceSpending `json:"maintenancespending"`
  1107  	// StorageSpending is the money currently spent on storage.
  1108  	StorageSpending types.Currency `json:"storagespending"`
  1109  	// ContractSpending is the total amount of money that the renter has put
  1110  	// into contracts, whether it's locked and the renter gets that money
  1111  	// back or whether it's spent and the renter won't get the money back.
  1112  	TotalAllocated types.Currency `json:"totalallocated"`
  1113  	// UploadSpending is the money currently spent on uploads.
  1114  	UploadSpending types.Currency `json:"uploadspending"`
  1115  	// Unspent is locked-away, unspent money.
  1116  	Unspent types.Currency `json:"unspent"`
  1117  	// ContractSpendingDeprecated was renamed to TotalAllocated and always has the
  1118  	// same value as TotalAllocated.
  1119  	ContractSpendingDeprecated types.Currency `json:"contractspending,siamismatch"`
  1120  	// WithheldFunds are the funds from the previous period that are tied up
  1121  	// in contracts and have not been released yet
  1122  	WithheldFunds types.Currency `json:"withheldfunds"`
  1123  	// ReleaseBlock is the block at which the WithheldFunds should be
  1124  	// released to the renter, based on worst case.
  1125  	// Contract End Height + Host Window Size + Maturity Delay
  1126  	ReleaseBlock types.BlockHeight `json:"releaseblock"`
  1127  	// PreviousSpending is the total spend funds from old contracts
  1128  	// that are not included in the current period spending
  1129  	PreviousSpending types.Currency `json:"previousspending"`
  1130  
  1131  	// ContractFees are the sum of all fees in the contract. This means it
  1132  	// includes the ContractFee, TxnFee and SiafundFee
  1133  	//
  1134  	// NOTE: kept this field for backwards compatibility
  1135  	ContractFees types.Currency `json:"contractfees"`
  1136  }
  1137  
  1138  // SkynetFee returns the total amount spent on the skynet fee.
  1139  //
  1140  // NOTE: this is the theoretical amount of money that is going to be spent, it
  1141  // might've not been spent yet as we only pay the skynet fee in 24h intervals.
  1142  func (cs *ContractorSpending) SkynetFee() (spending types.Currency) {
  1143  	var total types.Currency
  1144  	total = total.Add(cs.DownloadSpending)
  1145  	total = total.Add(cs.FundAccountSpending)
  1146  	total = total.Add(cs.MaintenanceSpending.Sum())
  1147  	total = total.Add(cs.StorageSpending)
  1148  	total = total.Add(cs.UploadSpending)
  1149  	total = total.Add(cs.Fees.Sum())
  1150  	total = total.Div64(SkynetFeeDivider)
  1151  	return
  1152  }
  1153  
  1154  // Fees is a helper struct that bundles all of the different types of fees.
  1155  type Fees struct {
  1156  	// ContractFees is the total amount of money paid to the host to cover
  1157  	// potential future transaction fees that the host may incur.
  1158  	ContractFees types.Currency `json:"contractfees"`
  1159  
  1160  	// SiafundFees is the total amount of money spent on siafund fees when
  1161  	// creating the contract.
  1162  	SiafundFees types.Currency `json:"siafundfees"`
  1163  
  1164  	// TxnFees is the total amount of money spent on the transaction fee when
  1165  	// putting the renter contract on the blockchain.
  1166  	TransactionFees types.Currency `json:"transactionfees"`
  1167  }
  1168  
  1169  // Sum returns the sum of all fees in the Fees struct.
  1170  func (f Fees) Sum() types.Currency {
  1171  	return f.ContractFees.Add(f.SiafundFees).Add(f.TransactionFees)
  1172  }
  1173  
  1174  // SpendingBreakdown provides a breakdown of a few fields in the Contractor
  1175  // Spending
  1176  func (cs ContractorSpending) SpendingBreakdown() (totalSpent, unspentAllocated, unspentUnallocated types.Currency) {
  1177  	totalSpent = cs.Fees.Sum().Add(cs.UploadSpending).
  1178  		Add(cs.DownloadSpending).Add(cs.StorageSpending).Add(cs.FundAccountSpending).Add(cs.MaintenanceSpending.Sum())
  1179  
  1180  	// Calculate unspent allocated
  1181  	if cs.TotalAllocated.Cmp(totalSpent) >= 0 {
  1182  		unspentAllocated = cs.TotalAllocated.Sub(totalSpent)
  1183  	}
  1184  	// Calculate unspent unallocated
  1185  	if cs.Unspent.Cmp(unspentAllocated) >= 0 {
  1186  		unspentUnallocated = cs.Unspent.Sub(unspentAllocated)
  1187  	}
  1188  	return totalSpent, unspentAllocated, unspentUnallocated
  1189  }
  1190  
  1191  // ContractorChurnStatus contains the current churn budgets for the Contractor's
  1192  // churnLimiter and the aggregate churn for the current period.
  1193  type ContractorChurnStatus struct {
  1194  	// AggregateCurrentPeriodChurn is the total size of files from churned contracts in this
  1195  	// period.
  1196  	AggregateCurrentPeriodChurn uint64 `json:"aggregatecurrentperiodchurn"`
  1197  	// MaxPeriodChurn is the (adjustable) maximum churn allowed per period.
  1198  	MaxPeriodChurn uint64 `json:"maxperiodchurn"`
  1199  }
  1200  
  1201  // UploadedBackup contains metadata about an uploaded backup.
  1202  type UploadedBackup struct {
  1203  	Name           string
  1204  	UID            [16]byte
  1205  	CreationDate   types.Timestamp
  1206  	Size           uint64 // size of snapshot .sia file
  1207  	UploadProgress float64
  1208  }
  1209  
  1210  type (
  1211  	// WorkerPoolStatus contains information about the status of the workerPool
  1212  	// and the workers
  1213  	WorkerPoolStatus struct {
  1214  		NumWorkers                   int            `json:"numworkers"`
  1215  		TotalDownloadCoolDown        int            `json:"totaldownloadcooldown"`
  1216  		TotalHasSectorCoolDown       int            `json:"totalhassectorcooldown"`
  1217  		TotalLowPrioDownloadCoolDown int            `json:"totallowpriodownloadcooldown"`
  1218  		TotalMaintenanceCoolDown     int            `json:"totalmaintenancecooldown"`
  1219  		TotalUploadCoolDown          int            `json:"totaluploadcooldown"`
  1220  		Workers                      []WorkerStatus `json:"workers"`
  1221  	}
  1222  
  1223  	// WorkerStatus contains information about the status of a worker
  1224  	WorkerStatus struct {
  1225  		// Worker contract information
  1226  		ContractID      types.FileContractID `json:"contractid"`
  1227  		ContractUtility ContractUtility      `json:"contractutility"`
  1228  		HostPubKey      types.SiaPublicKey   `json:"hostpubkey"`
  1229  
  1230  		// Download status information
  1231  		DownloadCoolDownError string        `json:"downloadcooldownerror"`
  1232  		DownloadCoolDownTime  time.Duration `json:"downloadcooldowntime"`
  1233  		DownloadOnCoolDown    bool          `json:"downloadoncooldown"`
  1234  		DownloadQueueSize     int           `json:"downloadqueuesize"`
  1235  		DownloadTerminated    bool          `json:"downloadterminated"`
  1236  
  1237  		// Has Sector status information
  1238  		HasSectorCoolDownError string        `json:"hassectorcooldownerror"`
  1239  		HasSectorCoolDownTime  time.Duration `json:"hassectorcooldowntime"`
  1240  		HasSectorOnCoolDown    bool          `json:"hassectoroncooldown"`
  1241  		HasSectorQueueSize     int           `json:"hassectorqueuesize"`
  1242  		HasSectorTerminated    bool          `json:"hassectorterminated"`
  1243  
  1244  		// Low Prio Download (repairs) status information
  1245  		LowPrioDownloadCoolDownError string        `json:"lowpriodownloadcooldownerror"`
  1246  		LowPrioDownloadCoolDownTime  time.Duration `json:"lowpriodownloadcooldowntime"`
  1247  		LowPrioDownloadOnCoolDown    bool          `json:"lowpriodownloadoncooldown"`
  1248  		LowPrioDownloadQueueSize     int           `json:"lowpriodownloadqueuesize"`
  1249  		LowPrioDownloadTerminated    bool          `json:"lowpriodownloadterminated"`
  1250  
  1251  		// Upload status information
  1252  		UploadCoolDownError string        `json:"uploadcooldownerror"`
  1253  		UploadCoolDownTime  time.Duration `json:"uploadcooldowntime"`
  1254  		UploadOnCoolDown    bool          `json:"uploadoncooldown"`
  1255  		UploadQueueSize     int           `json:"uploadqueuesize"`
  1256  		UploadTerminated    bool          `json:"uploadterminated"`
  1257  
  1258  		// Maintenance Cooldown information
  1259  		MaintenanceOnCooldown    bool          `json:"maintenanceoncooldown"`
  1260  		MaintenanceCoolDownError string        `json:"maintenancecooldownerror"`
  1261  		MaintenanceCoolDownTime  time.Duration `json:"maintenancecooldowntime"`
  1262  
  1263  		// Ephemeral Account information
  1264  		AccountBalanceTarget types.Currency      `json:"accountbalancetarget"`
  1265  		AccountStatus        WorkerAccountStatus `json:"accountstatus"`
  1266  
  1267  		// PriceTable information
  1268  		PriceTableStatus WorkerPriceTableStatus `json:"pricetablestatus"`
  1269  
  1270  		// Job Queues
  1271  		DownloadSnapshotJobQueueSize int `json:"downloadsnapshotjobqueuesize"`
  1272  		UploadSnapshotJobQueueSize   int `json:"uploadsnapshotjobqueuesize"`
  1273  
  1274  		// Read Jobs Information
  1275  		ReadJobsStatus WorkerReadJobsStatus `json:"readjobsstatus"`
  1276  
  1277  		// HasSector Job Information
  1278  		HasSectorJobsStatus WorkerHasSectorJobsStatus `json:"hassectorjobsstatus"`
  1279  
  1280  		// ReadRegistry Job Information
  1281  		ReadRegistryJobsStatus WorkerReadRegistryJobStatus `json:"readregistryjobsstatus"`
  1282  
  1283  		// UpdateRegistry Job information
  1284  		UpdateRegistryJobsStatus WorkerUpdateRegistryJobStatus `json:"updateregistryjobsstatus"`
  1285  	}
  1286  
  1287  	// WorkerGenericJobsStatus contains the common information for worker jobs.
  1288  	WorkerGenericJobsStatus struct {
  1289  		ConsecutiveFailures uint64    `json:"consecutivefailures"`
  1290  		JobQueueSize        uint64    `json:"jobqueuesize"`
  1291  		OnCooldown          bool      `json:"oncooldown"`
  1292  		OnCooldownUntil     time.Time `json:"oncooldownuntil"`
  1293  		RecentErr           string    `json:"recenterr"`
  1294  		RecentErrTime       time.Time `json:"recenterrtime"`
  1295  	}
  1296  
  1297  	// WorkerAccountStatus contains detailed information about the account
  1298  	WorkerAccountStatus struct {
  1299  		AvailableBalance types.Currency `json:"availablebalance"`
  1300  		NegativeBalance  types.Currency `json:"negativebalance"`
  1301  		HostBalance      types.Currency `json:"hostbalance"`
  1302  
  1303  		SyncAt       time.Time `json:"syncat"`
  1304  		ForcedSyncAt time.Time `json:"forcedsyncat"`
  1305  
  1306  		RecentErr         string    `json:"recenterr"`
  1307  		RecentErrTime     time.Time `json:"recenterrtime"`
  1308  		RecentSuccessTime time.Time `json:"recentsuccesstime"`
  1309  	}
  1310  
  1311  	// WorkerPriceTableStatus contains detailed information about the price
  1312  	// table
  1313  	WorkerPriceTableStatus struct {
  1314  		ExpiryTime time.Time `json:"expirytime"`
  1315  		UpdateTime time.Time `json:"updatetime"`
  1316  
  1317  		Active bool `json:"active"`
  1318  
  1319  		RecentErr     string    `json:"recenterr"`
  1320  		RecentErrTime time.Time `json:"recenterrtime"`
  1321  	}
  1322  
  1323  	// WorkerReadJobsStatus contains detailed information about the read jobs
  1324  	WorkerReadJobsStatus struct {
  1325  		AvgJobTime64k uint64 `json:"avgjobtime64k"` // in ms
  1326  		AvgJobTime1m  uint64 `json:"avgjobtime1m"`  // in ms
  1327  		AvgJobTime4m  uint64 `json:"avgjobtime4m"`  // in ms
  1328  
  1329  		ConsecutiveFailures uint64 `json:"consecutivefailures"`
  1330  
  1331  		JobQueueSize uint64 `json:"jobqueuesize"`
  1332  
  1333  		RecentErr     string    `json:"recenterr"`
  1334  		RecentErrTime time.Time `json:"recenterrtime"`
  1335  	}
  1336  
  1337  	// WorkerHasSectorJobsStatus contains detailed information about the has
  1338  	// sector jobs
  1339  	WorkerHasSectorJobsStatus struct {
  1340  		AvgJobTime uint64 `json:"avgjobtime"` // in ms
  1341  
  1342  		ConsecutiveFailures uint64 `json:"consecutivefailures"`
  1343  
  1344  		JobQueueSize uint64 `json:"jobqueuesize"`
  1345  
  1346  		RecentErr     string    `json:"recenterr"`
  1347  		RecentErrTime time.Time `json:"recenterrtime"`
  1348  	}
  1349  
  1350  	// WorkerReadRegistryJobStatus contains detailed information about the read
  1351  	// registry jobs.
  1352  	WorkerReadRegistryJobStatus struct {
  1353  		WorkerGenericJobsStatus
  1354  	}
  1355  
  1356  	// WorkerUpdateRegistryJobStatus contains detailed information about the update
  1357  	// registry jobs.
  1358  	WorkerUpdateRegistryJobStatus struct {
  1359  		WorkerGenericJobsStatus
  1360  	}
  1361  
  1362  	// SkynetBlocklistInvalidInput is a helper struct that contains an input
  1363  	// that failed to get added or removed from the blocklist alongside an error
  1364  	// string that indicates why.
  1365  	SkynetBlocklistInvalidInput struct {
  1366  		Input string `json:"input"`
  1367  		Error string `json:"error"`
  1368  	}
  1369  )
  1370  
  1371  // ChunkReader is the interface for a reader reading full erasure-coded chunks
  1372  // from a stream.
  1373  type ChunkReader interface {
  1374  	// Peek returns whether the next call to ReadChunk is expected to return a
  1375  	// chunk or if there is no more data.
  1376  	Peek() bool
  1377  
  1378  	// ReadChunk reads the next chunk from the reader. The returned chunk is
  1379  	// erasure coded, encrypted and will always be a full chunk ready for
  1380  	// upload. It also returns the number of bytes that this chunk was created
  1381  	// from which is useful because the last chunk might be padded. ReadChunk
  1382  	// will only return >0 bytes read if err == nil.
  1383  	ReadChunk() ([][]byte, uint64, error)
  1384  }
  1385  
  1386  // FanoutChunkReader defines a chunk reader that computes a skylink fanout on
  1387  // the fly.
  1388  type FanoutChunkReader interface {
  1389  	ChunkReader
  1390  
  1391  	// Fanout returns the computed fanout.
  1392  	Fanout() []byte
  1393  }
  1394  
  1395  // SubscriptionRequest is a helper type which contains information required to
  1396  // subscribe to a registry entry.
  1397  type SubscriptionRequest struct {
  1398  	EntryID modules.RegistryEntryID
  1399  
  1400  	// Pubkey and Tweak are optional but allow for subscribing to entries on
  1401  	// older hosts.
  1402  	PubKey *types.SiaPublicKey
  1403  	Tweak  *crypto.Hash
  1404  
  1405  	// Ratelimit in milliseconds. This is not used yet but carved out to
  1406  	// avoid a breaking protocol change later on. The idea is that for every
  1407  	// subscribed entry, a ratelimit can be specified to avoid spam and
  1408  	// reduce cost.
  1409  	Ratelimit uint32
  1410  }
  1411  
  1412  // HasKeyAndTweak returns whether a request has the optional fields set.
  1413  func (sr *SubscriptionRequest) HasKeyAndTweak() bool {
  1414  	return sr.PubKey != nil && sr.Tweak != nil
  1415  }
  1416  
  1417  // RegistrySubscriber is the interface for an object capable of subscribing to
  1418  // the skynet registry.
  1419  type RegistrySubscriber interface {
  1420  	io.Closer
  1421  
  1422  	// Subscribe subscribes to a new entry.
  1423  	Subscribe(eid modules.RegistryEntryID, spk *types.SiaPublicKey, tweak *crypto.Hash) *LatestRegistryEntry
  1424  
  1425  	// Subscriptions returns the currently active subscriptions of the
  1426  	// subscriber.
  1427  	Subscriptions() []modules.RegistryEntryID
  1428  
  1429  	// Unsubscribe unsubscribes from an entry.
  1430  	Unsubscribe(eid modules.RegistryEntryID)
  1431  }
  1432  
  1433  // A Renter uploads, tracks, repairs, and downloads a set of files for the
  1434  // user.
  1435  type Renter interface {
  1436  	modules.Alerter
  1437  
  1438  	// ActiveHosts provides the list of hosts that the renter is selecting,
  1439  	// sorted by preference.
  1440  	ActiveHosts() ([]HostDBEntry, error)
  1441  
  1442  	// AllHosts returns the full list of hosts known to the renter.
  1443  	AllHosts() ([]HostDBEntry, error)
  1444  
  1445  	// BlockDomains blocks all hosts with matching domains
  1446  	BlockDomains(domains []string) error
  1447  
  1448  	// BlockedDomains returns a list of all the blocked domains
  1449  	BlockedDomains() ([]string, error)
  1450  
  1451  	// UnblockDomains removes domains from the blocked domains
  1452  	UnblockDomains(domains []string) error
  1453  
  1454  	// Close closes the Renter.
  1455  	Close() error
  1456  
  1457  	// CancelContract cancels a specific contract of the renter.
  1458  	CancelContract(id types.FileContractID) error
  1459  
  1460  	// Contracts returns the staticContracts of the renter's hostContractor.
  1461  	Contracts() []RenterContract
  1462  
  1463  	// ContractStatus returns the status of the contract with the given ID in the
  1464  	// watchdog, and a bool indicating whether or not the watchdog is aware of it.
  1465  	ContractStatus(fcID types.FileContractID) (ContractWatchStatus, bool)
  1466  
  1467  	// CreateBackup creates a backup of the renter's siafiles. If a secret is not
  1468  	// nil, the backup will be encrypted using the provided secret.
  1469  	CreateBackup(dst string, secret []byte) error
  1470  
  1471  	// DecryptBaseSector attempts to decrypt the baseSector. If it has the
  1472  	// necessary Skykey, it will decrypt the baseSector in-place. It returns the
  1473  	// file-specific skykey to be used for decrypting the rest of the associated
  1474  	// skyfile.
  1475  	DecryptBaseSector(baseSector []byte) (skykey.Skykey, error)
  1476  
  1477  	// LoadBackup loads the siafiles of a previously created backup into the
  1478  	// renter. If the backup is encrypted, secret will be used to decrypt it.
  1479  	// Otherwise the argument is ignored.
  1480  	// If a file from the backup would have the same path as an already
  1481  	// existing file, a suffix of the form _[num] is appended to the siapath.
  1482  	// [num] is incremented until a siapath is found that is not already in
  1483  	// use.
  1484  	LoadBackup(src string, secret []byte) error
  1485  
  1486  	// InitRecoveryScan starts scanning the whole blockchain for recoverable
  1487  	// contracts within a separate thread.
  1488  	InitRecoveryScan() error
  1489  
  1490  	// OldContracts returns the oldContracts of the renter's hostContractor.
  1491  	OldContracts() []RenterContract
  1492  
  1493  	// ContractorChurnStatus returns contract churn stats for the current period.
  1494  	ContractorChurnStatus() ContractorChurnStatus
  1495  
  1496  	// ContractUtility provides the contract utility for a given host key.
  1497  	ContractUtility(pk types.SiaPublicKey) (ContractUtility, bool)
  1498  
  1499  	// CurrentPeriod returns the height at which the current allowance period
  1500  	// began.
  1501  	CurrentPeriod() types.BlockHeight
  1502  
  1503  	// MemoryStatus returns the current status of the memory manager
  1504  	MemoryStatus() (MemoryStatus, error)
  1505  
  1506  	// Mount mounts a FUSE filesystem at mountPoint, making the contents of sp
  1507  	// available via the local filesystem.
  1508  	Mount(mountPoint string, sp SiaPath, opts MountOptions) error
  1509  
  1510  	// MountInfo returns the list of currently mounted FUSE filesystems.
  1511  	MountInfo() []MountInfo
  1512  
  1513  	// ParseSkyfileMetadata parses all the information from a base sector
  1514  	// similar to skymodules.ParseSkyfileMetadata. The difference is that it
  1515  	// can also parse a recursive base sector.
  1516  	ParseSkyfileMetadata(baseSector []byte) (sl SkyfileLayout, fanoutBytes []byte, sm SkyfileMetadata, rawSM, baseSectorPayload, baseSectorExtension []byte, err error)
  1517  
  1518  	// NewRegistrySubscriber creates a new registry subscriber which can be
  1519  	// used to subscribe to registry entries for updates.
  1520  	NewRegistrySubscriber(notifyFunc func(entry LatestRegistryEntry) error) (RegistrySubscriber, error)
  1521  
  1522  	// Unmount unmounts the FUSE filesystem currently mounted at mountPoint.
  1523  	Unmount(mountPoint string) error
  1524  
  1525  	// Performance returns performance information about the renter.
  1526  	Performance() (RenterPerformance, error)
  1527  
  1528  	// ResetContractUtilities will reset all bad and locked contracts, as well
  1529  	// as trigger a contract maintenance.
  1530  	ResetContractUtilities() error
  1531  
  1532  	// ResetStats allows resetting the renter stats. A specifier can be passed
  1533  	// in to specify what to reset.
  1534  	ResetStats(types.Specifier) error
  1535  
  1536  	// PeriodSpending returns the amount spent on contracts in the current
  1537  	// billing period, as well as a breakdown of the ephemeral account spending.
  1538  	PeriodSpending() (FinancialMetrics, error)
  1539  
  1540  	// RecoverableContracts returns the contracts that the contractor deems
  1541  	// recoverable. That means they are not expired yet and also not part of the
  1542  	// active contracts. Usually this should return an empty slice unless the host
  1543  	// isn't available for recovery or something went wrong.
  1544  	RecoverableContracts() []RecoverableContract
  1545  
  1546  	// RecoveryScanStatus returns a bool indicating if a scan for recoverable
  1547  	// contracts is in progress and if it is, the current progress of the scan.
  1548  	RecoveryScanStatus() (bool, types.BlockHeight)
  1549  
  1550  	// RefreshedContract checks if the contract was previously refreshed
  1551  	RefreshedContract(fcid types.FileContractID) bool
  1552  
  1553  	// SetFileStuck sets the 'stuck' status of a file.
  1554  	SetFileStuck(siaPath SiaPath, stuck bool) error
  1555  
  1556  	// SkynetTUSUploader returns the TUSUploader that can be used to initiate
  1557  	// resumable uploads to skynet.
  1558  	SkynetTUSUploader() SkynetTUSDataStore
  1559  
  1560  	// UploadBackup uploads a backup to hosts, such that it can be retrieved
  1561  	// using only the seed.
  1562  	UploadBackup(src string, name string) error
  1563  
  1564  	// DownloadBackup downloads a backup previously uploaded to hosts.
  1565  	DownloadBackup(dst string, name string) error
  1566  
  1567  	// UploadedBackups returns a list of backups previously uploaded to hosts,
  1568  	// along with a list of which hosts are storing all known backups.
  1569  	UploadedBackups() ([]UploadedBackup, []types.SiaPublicKey, error)
  1570  
  1571  	// BackupsOnHost returns the backups stored on the specified host.
  1572  	BackupsOnHost(hostKey types.SiaPublicKey) ([]UploadedBackup, error)
  1573  
  1574  	// DeleteFile deletes a file entry from the renter.
  1575  	DeleteFile(siaPath SiaPath) error
  1576  
  1577  	// Download creates a download according to the parameters passed, including
  1578  	// downloads of `offset` and `length` type. It returns a method to
  1579  	// start the download.
  1580  	Download(params RenterDownloadParameters) (DownloadID, func() error, error)
  1581  
  1582  	// DownloadAsync creates a file download using the passed parameters without
  1583  	// blocking until the download is finished. The download needs to be started
  1584  	// using the method returned by DownloadAsync. DownloadAsync also accepts an
  1585  	// optional input function which will be registered to be called when the
  1586  	// download is finished.
  1587  	DownloadAsync(params RenterDownloadParameters, onComplete func(error) error) (uid DownloadID, start func() error, cancel func(), err error)
  1588  
  1589  	// ClearDownloadHistory clears the download history of the renter
  1590  	// inclusive for before and after times.
  1591  	ClearDownloadHistory(after, before time.Time) error
  1592  
  1593  	// DownloadByUID returns a download from the download history given its uid.
  1594  	DownloadByUID(uid DownloadID) (DownloadInfo, bool)
  1595  
  1596  	// DownloadHistory lists all the files that have been scheduled for download.
  1597  	DownloadHistory() ([]DownloadInfo, error)
  1598  
  1599  	// File returns information on specific file queried by user
  1600  	File(siaPath SiaPath) (FileInfo, error)
  1601  
  1602  	// FileList returns information on all of the files stored by the renter at the
  1603  	// specified folder. The 'cached' argument specifies whether cached values
  1604  	// should be returned or not.
  1605  	FileList(siaPath SiaPath, recursive, cached bool, flf FileListFunc) error
  1606  
  1607  	// Filter returns the renter's hostdb's filterMode and filteredHosts
  1608  	Filter() (FilterMode, map[string]types.SiaPublicKey, error)
  1609  
  1610  	// ForceAccountsSync schedules a forced balance sync for all the workers, a
  1611  	// forced sync means that the renter balance will be updated to match the
  1612  	// host balance, regardless of whether it was higher or lower.
  1613  	ForceAccountsSync()
  1614  
  1615  	// SetFilterMode sets the renter's hostdb filter mode
  1616  	SetFilterMode(fm FilterMode, hosts []types.SiaPublicKey) error
  1617  
  1618  	// Host provides the DB entry and score breakdown for the requested host.
  1619  	Host(pk types.SiaPublicKey) (HostDBEntry, bool, error)
  1620  
  1621  	// HostsForRegistryUpdate returns a list of hosts that the renter would be using
  1622  	// for updating the registry.
  1623  	HostsForRegistryUpdate() ([]HostForRegistryUpdate, error)
  1624  
  1625  	// InitialScanComplete returns a boolean indicating if the initial scan of the
  1626  	// hostdb is completed.
  1627  	InitialScanComplete() (bool, error)
  1628  
  1629  	// PriceEstimation estimates the cost in siacoins of performing various
  1630  	// storage and data operations.
  1631  	PriceEstimation(allowance Allowance) (RenterPriceEstimation, Allowance, error)
  1632  
  1633  	// RenameFile changes the path of a file.
  1634  	RenameFile(siaPath, newSiaPath SiaPath) error
  1635  
  1636  	// RenameDir changes the path of a dir.
  1637  	RenameDir(oldPath, newPath SiaPath) error
  1638  
  1639  	// EstimateHostScore will return the score for a host with the provided
  1640  	// settings, assuming perfect age and uptime adjustments
  1641  	EstimateHostScore(entry HostDBEntry, allowance Allowance) (HostScoreBreakdown, error)
  1642  
  1643  	// ReadRegistry starts a registry lookup on all available workers. The jobs
  1644  	// have time to finish their jobs and return a response until the context is
  1645  	// closed. Otherwise the response with the highest revision number will be
  1646  	// used.
  1647  	ReadRegistry(ctx context.Context, spk types.SiaPublicKey, tweak crypto.Hash) (RegistryEntry, error)
  1648  
  1649  	// RegistryEntryHealth returns the health of a registry entry specified by
  1650  	// either the spk and tweak or the rid.
  1651  	RegistryEntryHealth(ctx context.Context, spk types.SiaPublicKey, tweak crypto.Hash) (RegistryEntryHealth, error)
  1652  
  1653  	// RegistryEntryHealthRID returns the health of a registry entry specified
  1654  	// by either the spk and tweak or the rid.
  1655  	RegistryEntryHealthRID(ctx context.Context, rid modules.RegistryEntryID) (RegistryEntryHealth, error)
  1656  
  1657  	// ReadRegistryRID starts a registry lookup on all available workers.
  1658  	// The jobs have time to finish their jobs and return a response until
  1659  	// the context is closed. Otherwise the response with the highest
  1660  	// revision number will be used.
  1661  	ReadRegistryRID(ctx context.Context, rid modules.RegistryEntryID) (RegistryEntry, error)
  1662  
  1663  	// ResolveSkylinkV2 resolves a V2 skylink to a V1 skylink if possible.
  1664  	ResolveSkylinkV2(ctx context.Context, sl Skylink) (Skylink, []RegistryEntry, error)
  1665  
  1666  	// ScoreBreakdown will return the score for a host db entry using the
  1667  	// hostdb's weighting algorithm.
  1668  	ScoreBreakdown(entry HostDBEntry) (HostScoreBreakdown, error)
  1669  
  1670  	// Settings returns the Renter's current settings.
  1671  	Settings() (RenterSettings, error)
  1672  
  1673  	// SetSettings sets the Renter's settings.
  1674  	SetSettings(RenterSettings) error
  1675  
  1676  	// SetFileTrackingPath sets the on-disk location of an uploaded file to a
  1677  	// new value. Useful if files need to be moved on disk.
  1678  	SetFileTrackingPath(siaPath SiaPath, newPath string) error
  1679  
  1680  	// UpdateRegistry updates the registries on all workers with the given
  1681  	// registry value.
  1682  	UpdateRegistry(ctx context.Context, spk types.SiaPublicKey, srv modules.SignedRegistryValue) error
  1683  
  1684  	// UpdateRegistryMulti updates the registries on the given workers with the
  1685  	// corresponding registry values.
  1686  	UpdateRegistryMulti(ctx context.Context, srvs map[string]RegistryEntry) error
  1687  
  1688  	// PauseRepairsAndUploads pauses the renter's repairs and uploads for a time
  1689  	// duration
  1690  	PauseRepairsAndUploads(duration time.Duration) error
  1691  
  1692  	// ResumeRepairsAndUploads resumes the renter's repairs and uploads
  1693  	ResumeRepairsAndUploads() error
  1694  
  1695  	// Streamer creates a io.ReadSeeker that can be used to stream downloads
  1696  	// from the Sia network and also returns the fileName of the streamed
  1697  	// resource.
  1698  	Streamer(siapath SiaPath, disableLocalFetch bool) (string, Streamer, error)
  1699  
  1700  	// Upload uploads a file using the input parameters.
  1701  	Upload(FileUploadParams) error
  1702  
  1703  	// UploadStreamFromReader reads from the provided reader until io.EOF is
  1704  	// reached and upload the data to the Sia network.
  1705  	UploadStreamFromReader(up FileUploadParams, reader io.Reader) error
  1706  
  1707  	// CreateDir creates a directory for the renter
  1708  	CreateDir(siaPath SiaPath, mode os.FileMode) error
  1709  
  1710  	// DeleteDir deletes a directory from the renter
  1711  	DeleteDir(siaPath SiaPath) error
  1712  
  1713  	// DirList lists the directories in a siadir
  1714  	DirList(siaPath SiaPath) ([]DirectoryInfo, error)
  1715  
  1716  	// AddSkykey adds the skykey to the renter's skykey manager.
  1717  	AddSkykey(skykey.Skykey) error
  1718  
  1719  	// CreateSkykey creates a new Skykey with the given name and SkykeyType.
  1720  	CreateSkykey(string, skykey.SkykeyType) (skykey.Skykey, error)
  1721  
  1722  	// DeleteSkykeyByID deletes the Skykey with the given name from the renter's
  1723  	// skykey manager if it exists.
  1724  	DeleteSkykeyByID(skykey.SkykeyID) error
  1725  
  1726  	// DeleteSkykeyByName deletes the Skykey with the given name from the renter's skykey
  1727  	// manager if it exists.
  1728  	DeleteSkykeyByName(string) error
  1729  
  1730  	// SkykeyByName gets the Skykey with the given name from the renter's skykey
  1731  	// manager if it exists.
  1732  	SkykeyByName(string) (skykey.Skykey, error)
  1733  
  1734  	// SkykeyByID gets the Skykey with the given ID from the renter's skykey
  1735  	// manager if it exists.
  1736  	SkykeyByID(skykey.SkykeyID) (skykey.Skykey, error)
  1737  
  1738  	// SkykeyIDByName gets the SkykeyID of the key with the given name if it
  1739  	// exists.
  1740  	SkykeyIDByName(string) (skykey.SkykeyID, error)
  1741  
  1742  	// Skykeys returns a slice containing each Skykey being stored by the renter.
  1743  	Skykeys() ([]skykey.Skykey, error)
  1744  
  1745  	// CreateSkylinkFromSiafile will create a skylink from a siafile. This will
  1746  	// result in some uploading - the base sector skyfile needs to be uploaded
  1747  	// separately, and if there is a fanout expansion that needs to be uploaded
  1748  	// separately as well.
  1749  	CreateSkylinkFromSiafile(SkyfileUploadParameters, SiaPath) (Skylink, error)
  1750  
  1751  	// DownloadByRoot will fetch data using the merkle root of that data. The
  1752  	// pricePerMS acts as a budget to spend on faster, and thus potentially more
  1753  	// expensive, hosts.
  1754  	DownloadByRoot(ctx context.Context, root crypto.Hash, offset, length uint64, pricePerMS types.Currency) ([]byte, [][]byte, [][]crypto.Hash, error)
  1755  
  1756  	// DownloadSkylink will fetch a file from the Sia network using the given
  1757  	// skylink. The given timeout will make sure this call won't block for a
  1758  	// time that exceeds the given timeout value. Passing a timeout of 0 is
  1759  	// considered as no timeout. The pricePerMS acts as a budget to spend on
  1760  	// faster, and thus potentially more expensive, hosts.
  1761  	DownloadSkylink(link Skylink, timeout time.Duration, pricePerMS types.Currency) (SkyfileStreamer, []RegistryEntry, error)
  1762  
  1763  	// DownloadSkylinkBaseSector will take a link and turn it into the data of a
  1764  	// download without any decoding of the metadata, fanout, or decryption. The
  1765  	// given timeout will make sure this call won't block for a time that
  1766  	// exceeds the given timeout value. Passing a timeout of 0 is considered as
  1767  	// no timeout. The pricePerMS acts as a budget to spend on faster, and thus
  1768  	// potentially more expensive, hosts.
  1769  	DownloadSkylinkBaseSector(link Skylink, timeout time.Duration, pricePerMS types.Currency) (Streamer, []RegistryEntry, Skylink, error)
  1770  
  1771  	// SkylinkHealth returns the health of a skylink on the network.
  1772  	SkylinkHealth(ctx context.Context, link Skylink, ppms types.Currency) (SkylinkHealth, error)
  1773  
  1774  	// UploadSkyfile will upload data to the Sia network from a reader and
  1775  	// create a skyfile, returning the skylink that can be used to access the
  1776  	// file.
  1777  	//
  1778  	// NOTE: A skyfile is a file that is tracked and repaired by the renter.  A
  1779  	// skyfile contains more than just the file data, it also contains metadata
  1780  	// about the file and other information which is useful in fetching the
  1781  	// file.
  1782  	UploadSkyfile(context.Context, SkyfileUploadParameters, SkyfileUploadReader) (Skylink, error)
  1783  
  1784  	// Blocklist returns the merkleroots that are blocked
  1785  	Blocklist() ([]crypto.Hash, error)
  1786  
  1787  	// PinSkylink re-uploads the data stored at the file under that skylink with
  1788  	// the given parameters. Alongside the parameters we can pass a timeout and
  1789  	// a price per millisecond. The timeout applies to downloading only,
  1790  	// including the base sector download and to every chunk in the fanout. The
  1791  	// price per millisecond is the budget we are allowed to spend on faster
  1792  	// hosts.
  1793  	PinSkylink(ctx context.Context, link Skylink, sup SkyfileUploadParameters, downloadTimeout time.Duration, pricePerMS types.Currency, lazy bool) error
  1794  
  1795  	// UnpinSkylink unpins a skylink from the renter by removing the underlying
  1796  	// siafile.
  1797  	UnpinSkylink(skylink Skylink) error
  1798  
  1799  	// Portals returns the list of known skynet portals.
  1800  	Portals() ([]SkynetPortal, error)
  1801  
  1802  	// RestoreSkyfile restores a skyfile such that the skylink is preserved.
  1803  	RestoreSkyfile(reader io.Reader) (Skylink, error)
  1804  
  1805  	// UpdateSkynetBlocklist updates the list of hashed merkleroots that are
  1806  	// blocked
  1807  	UpdateSkynetBlocklist(ctx context.Context, additions, removals []string, isHash bool, probationaryPeriod int64) ([]SkynetBlocklistInvalidInput, error)
  1808  
  1809  	// UpdateSkynetPortals updates the list of known skynet portals.
  1810  	UpdateSkynetPortals(additions []SkynetPortal, removals []modules.NetAddress) error
  1811  
  1812  	// WorkerPoolStatus returns the current status of the Renter's worker pool
  1813  	WorkerPoolStatus() (WorkerPoolStatus, error)
  1814  
  1815  	// UpdateMetadata will ensure that the metadata of the provided directory is
  1816  	// updated and that the updated stats are represented in the aggregate
  1817  	// statistics of the root folder.
  1818  	UpdateMetadata(siaPath SiaPath, recursive bool) error
  1819  }
  1820  
  1821  // Streamer is the interface implemented by the Renter's streamer type which
  1822  // allows for streaming files uploaded to the Sia network.
  1823  type Streamer interface {
  1824  	io.ReadSeeker
  1825  	io.Closer
  1826  }
  1827  
  1828  // SkyfileStreamer is the interface implemented by the Renter's skyfile type
  1829  // which allows for streaming files uploaded to the Sia network.
  1830  type SkyfileStreamer interface {
  1831  	io.ReadSeeker
  1832  	io.Closer
  1833  
  1834  	// CacheRatio returns the percentage of data served by the streamer that
  1835  	// was cached.
  1836  	CacheRatio() float64
  1837  	Layout() SkyfileLayout
  1838  	Metadata() SkyfileMetadata
  1839  	RawLayout() (SkyfileLayout, []byte, []crypto.Hash)
  1840  	RawMetadata() []byte
  1841  	Skylink() Skylink
  1842  
  1843  	// TrustlessWrite writes the trustless download of a certain length to
  1844  	// the writer.
  1845  	TrustlessWrite(w io.Writer, length uint64) error
  1846  }
  1847  
  1848  // SkylinkHealth describes the health of a skylink on the network.
  1849  type SkylinkHealth struct {
  1850  	// BaseSectorRedundancy is the number of base sector pieces on the
  1851  	// network.
  1852  	BaseSectorRedundancy uint64 `json:"basesectorredundancy"`
  1853  
  1854  	// FanoutEffectiveRedundancy is the worst redundancy of any of the
  1855  	// fanout's chunks on the network.
  1856  	FanoutEffectiveRedundancy float64 `json:"fanouteffectiveredundancy,omitempty"`
  1857  
  1858  	// FanoutDataPieces are the datapieces of the erasure coder specified in
  1859  	// the layout of the skyfile.
  1860  	FanoutDataPieces uint8 `json:"fanoutdatapieces,omitempty"`
  1861  
  1862  	// FanoutDataPieces are the paritypieces of the erasure coder specified
  1863  	// in the layout of the skyfile.
  1864  	FanoutParityPieces uint8 `json:"fanoutparitypieces,omitempty"`
  1865  
  1866  	// FanoutRedundancy is the individual redundancy of all chunks in the
  1867  	// fanout.
  1868  	FanoutRedundancy []float64 `json:"fanoutredundancy,omitempty"`
  1869  }
  1870  
  1871  // RenterDownloadParameters defines the parameters passed to the Renter's
  1872  // Download method.
  1873  type RenterDownloadParameters struct {
  1874  	Async            bool
  1875  	Httpwriter       io.Writer
  1876  	Length           uint64
  1877  	Offset           uint64
  1878  	SiaPath          SiaPath
  1879  	Destination      string
  1880  	DisableDiskFetch bool
  1881  }
  1882  
  1883  // HealthPercentage returns the health in a more human understandable format out
  1884  // of 100%
  1885  //
  1886  // The percentage is out of 1.25, this is to account for the RepairThreshold of
  1887  // 0.25 and assumes that the worst health is 1.5. Since we do not repair until
  1888  // the health is worse than the RepairThreshold, a health of 0 - 0.25 is full
  1889  // health. Likewise, a health that is greater than 1.25 is essentially 0 health.
  1890  func HealthPercentage(health float64) float64 {
  1891  	healthPercent := 100 * (1.25 - health)
  1892  	if healthPercent > 100 {
  1893  		healthPercent = 100
  1894  	}
  1895  	if healthPercent < 0 {
  1896  		healthPercent = 0
  1897  	}
  1898  	return healthPercent
  1899  }
  1900  
  1901  var (
  1902  	// RepairThreshold defines the threshold at which the renter decides to
  1903  	// repair a file. The renter will start repairing the file when the health
  1904  	// is equal to or greater than this value.
  1905  	RepairThreshold = build.Select(build.Var{
  1906  		Dev:      0.25,
  1907  		Standard: 0.25,
  1908  		Testing:  0.25,
  1909  	}).(float64)
  1910  )
  1911  
  1912  // NeedsRepair is a helper to ensure consistent comparison with the
  1913  // RepairThreshold
  1914  func NeedsRepair(health float64) bool {
  1915  	return health >= RepairThreshold
  1916  }
  1917  
  1918  // A HostDB is a database of hosts that the renter can use for figuring out who
  1919  // to upload to, and download from.
  1920  type HostDB interface {
  1921  	modules.Alerter
  1922  
  1923  	// ActiveHosts returns the list of hosts that are actively being selected
  1924  	// from.
  1925  	ActiveHosts() ([]HostDBEntry, error)
  1926  
  1927  	// AllHosts returns the full list of hosts known to the hostdb, sorted in
  1928  	// order of preference.
  1929  	AllHosts() ([]HostDBEntry, error)
  1930  
  1931  	// BlockDomains blocks all hosts with matching domains
  1932  	BlockDomains(domains []string) error
  1933  
  1934  	// BlockedDomains returns a list of all the blocked domains
  1935  	BlockedDomains() ([]string, error)
  1936  
  1937  	// CheckForIPViolations accepts a number of host public keys and returns the
  1938  	// ones that violate the rules of the addressFilter.
  1939  	CheckForIPViolations([]types.SiaPublicKey) ([]types.SiaPublicKey, error)
  1940  
  1941  	// Close closes the hostdb.
  1942  	Close() error
  1943  
  1944  	// EstimateHostScore returns the estimated score breakdown of a host with the
  1945  	// provided settings.
  1946  	EstimateHostScore(HostDBEntry, Allowance) (HostScoreBreakdown, error)
  1947  
  1948  	// Filter returns the hostdb's filterMode and filteredHosts
  1949  	Filter() (FilterMode, map[string]types.SiaPublicKey, error)
  1950  
  1951  	// SetFilterMode sets the renter's hostdb filter mode
  1952  	SetFilterMode(lm FilterMode, hosts []types.SiaPublicKey) error
  1953  
  1954  	// Host returns the HostDBEntry for a given host.
  1955  	Host(pk types.SiaPublicKey) (HostDBEntry, bool, error)
  1956  
  1957  	// IncrementSuccessfulInteractions increments the number of successful
  1958  	// interactions with a host for a given key
  1959  	IncrementSuccessfulInteractions(types.SiaPublicKey) error
  1960  
  1961  	// IncrementFailedInteractions increments the number of failed interactions with
  1962  	// a host for a given key
  1963  	IncrementFailedInteractions(types.SiaPublicKey) error
  1964  
  1965  	// InitialScanComplete returns a boolean indicating if the initial scan of
  1966  	// the hostdb is completed.
  1967  	InitialScanComplete() (bool, error)
  1968  
  1969  	// IPViolationsCheck returns a boolean indicating if the IP violation check is
  1970  	// enabled or not.
  1971  	IPViolationsCheck() (bool, error)
  1972  
  1973  	// IsMalicious indicates whether the host is considered to be malicious
  1974  	// according to the hostdb.
  1975  	IsMalicious(HostDBEntry) (bool, error)
  1976  
  1977  	// PriceTable returns the most recent pricetable for the host that
  1978  	// corresponds with given public key. If the pricetable was not found, nil
  1979  	// is returned.
  1980  	PriceTable(pk types.SiaPublicKey) *modules.RPCPriceTable
  1981  
  1982  	// RandomHosts returns a set of random hosts, weighted by their estimated
  1983  	// usefulness / attractiveness to the renter. RandomHosts will not return
  1984  	// any offline or inactive hosts.
  1985  	RandomHosts(int, []types.SiaPublicKey, []types.SiaPublicKey) ([]HostDBEntry, error)
  1986  
  1987  	// RandomHostsWithWhitelist returns a set of random hosts, weighted by their
  1988  	// estimated usefulness / attractiveness to the renter. RandomHosts will not
  1989  	// return any offline or inactive hosts.
  1990  	RandomHostsWithWhitelist(int, []types.SiaPublicKey, []types.SiaPublicKey, map[string]struct{}) ([]HostDBEntry, error)
  1991  
  1992  	// RandomHostsWithAllowance is the same as RandomHosts but accepts an
  1993  	// allowance as an argument to be used instead of the allowance set in the
  1994  	// renter.
  1995  	RandomHostsWithAllowance(int, []types.SiaPublicKey, []types.SiaPublicKey, Allowance) ([]HostDBEntry, error)
  1996  
  1997  	// RegisterPriceTable will set the given price table as the most recent
  1998  	// pricetable for the host that corresponds with the given public key.
  1999  	RegisterPriceTable(types.SiaPublicKey, modules.RPCPriceTable)
  2000  
  2001  	// ScoreBreakdown returns a detailed explanation of the various properties
  2002  	// of the host.
  2003  	ScoreBreakdown(HostDBEntry) (HostScoreBreakdown, error)
  2004  
  2005  	// SetAllowance updates the allowance used by the hostdb for weighing hosts by
  2006  	// updating the host weight function. It will completely rebuild the hosttree so
  2007  	// it should be used with care.
  2008  	SetAllowance(Allowance) error
  2009  
  2010  	// SetIPViolationCheck enables/disables the IP violation check within the
  2011  	// hostdb.
  2012  	SetIPViolationCheck(enabled bool) error
  2013  
  2014  	// UpdateContracts rebuilds the knownContracts of the HostBD using the provided
  2015  	// contracts.
  2016  	UpdateContracts([]RenterContract) error
  2017  
  2018  	// UnblockDomains removes domains from the blocked domains
  2019  	UnblockDomains(domains []string) error
  2020  }
  2021  
  2022  // RenterPayoutsPreTax calculates the renterPayout before tax and the hostPayout
  2023  // given a host, the available renter funding, the expected txnFee for the
  2024  // transaction and an optional basePrice in case this helper is used for a
  2025  // renewal. It also returns the hostCollateral.
  2026  func RenterPayoutsPreTax(host HostDBEntry, funding, txnFee, basePrice, baseCollateral types.Currency, period types.BlockHeight, expectedStorage uint64) (renterPayout, hostPayout, hostCollateral types.Currency, err error) {
  2027  	// Divide by zero check.
  2028  	if host.StoragePrice.IsZero() {
  2029  		host.StoragePrice = types.NewCurrency64(1)
  2030  	}
  2031  	// Underflow check.
  2032  	if funding.Cmp(host.ContractPrice.Add(txnFee).Add(basePrice)) <= 0 {
  2033  		err = fmt.Errorf("contract price (%v) plus transaction fee (%v) plus base price (%v) exceeds funding (%v)",
  2034  			host.ContractPrice.HumanString(), txnFee.HumanString(), basePrice.HumanString(), funding.HumanString())
  2035  		return
  2036  	}
  2037  	// Calculate renterPayout.
  2038  	renterPayout = funding.Sub(host.ContractPrice).Sub(txnFee).Sub(basePrice)
  2039  	// Calculate hostCollateral by calculating the maximum amount of storage
  2040  	// the renter can afford with 'funding' and calculating how much collateral
  2041  	// the host wouldl have to put into the contract for that. We also add a
  2042  	// potential baseCollateral.
  2043  	maxStorageSizeTime := renterPayout.Div(host.StoragePrice)
  2044  	hostCollateral = maxStorageSizeTime.Mul(host.Collateral).Add(baseCollateral)
  2045  	// Don't add more collateral than 10x the collateral for the expected
  2046  	// storage to save on fees.
  2047  	maxRenterCollateral := host.Collateral.Mul64(uint64(period)).Mul64(expectedStorage).Mul64(5)
  2048  	if hostCollateral.Cmp(maxRenterCollateral) > 0 {
  2049  		hostCollateral = maxRenterCollateral
  2050  	}
  2051  	// Don't add more collateral than the host is willing to put into a single
  2052  	// contract.
  2053  	if hostCollateral.Cmp(host.MaxCollateral) > 0 {
  2054  		hostCollateral = host.MaxCollateral
  2055  	}
  2056  	// Calculate hostPayout.
  2057  	hostPayout = hostCollateral.Add(host.ContractPrice).Add(basePrice)
  2058  	return
  2059  }