github.com/ZuluSpl0it/Sia@v1.3.7/modules/renter.go (about)

     1  package modules
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"time"
     7  
     8  	"github.com/NebulousLabs/Sia/crypto"
     9  	"github.com/NebulousLabs/Sia/types"
    10  
    11  	"github.com/NebulousLabs/errors"
    12  )
    13  
    14  // ErrHostFault is an error that is usually extended to indicate that an error
    15  // is the host's fault.
    16  var ErrHostFault = errors.New("host has returned an error")
    17  
    18  // IsHostsFault indicates if a returned error is the host's fault.
    19  func IsHostsFault(err error) bool {
    20  	return errors.Contains(err, ErrHostFault)
    21  }
    22  
    23  const (
    24  	// RenterDir is the name of the directory that is used to store the
    25  	// renter's persistent data.
    26  	RenterDir = "renter"
    27  
    28  	// EstimatedFileContractTransactionSetSize is the estimated blockchain size
    29  	// of a transaction set between a renter and a host that contains a file
    30  	// contract. This transaction set will contain a setup transaction from each
    31  	// the host and the renter, and will also contain a file contract and file
    32  	// contract revision that have each been signed by all parties.
    33  	EstimatedFileContractTransactionSetSize = 2048
    34  )
    35  
    36  // An ErasureCoder is an error-correcting encoder and decoder.
    37  type ErasureCoder interface {
    38  	// NumPieces is the number of pieces returned by Encode.
    39  	NumPieces() int
    40  
    41  	// MinPieces is the minimum number of pieces that must be present to
    42  	// recover the original data.
    43  	MinPieces() int
    44  
    45  	// Encode splits data into equal-length pieces, with some pieces
    46  	// containing parity data.
    47  	Encode(data []byte) ([][]byte, error)
    48  
    49  	// EncodeShards encodes the input data like Encode but accepts an already
    50  	// sharded input.
    51  	EncodeShards(data [][]byte) ([][]byte, error)
    52  
    53  	// Recover recovers the original data from pieces and writes it to w.
    54  	// pieces should be identical to the slice returned by Encode (length and
    55  	// order must be preserved), but with missing elements set to nil. n is
    56  	// the number of bytes to be written to w; this is necessary because
    57  	// pieces may have been padded with zeros during encoding.
    58  	Recover(pieces [][]byte, n uint64, w io.Writer) error
    59  }
    60  
    61  // An Allowance dictates how much the Renter is allowed to spend in a given
    62  // period. Note that funds are spent on both storage and bandwidth.
    63  type Allowance struct {
    64  	Funds       types.Currency    `json:"funds"`
    65  	Hosts       uint64            `json:"hosts"`
    66  	Period      types.BlockHeight `json:"period"`
    67  	RenewWindow types.BlockHeight `json:"renewwindow"`
    68  }
    69  
    70  // ContractUtility contains metrics internal to the contractor that reflect the
    71  // utility of a given contract.
    72  type ContractUtility struct {
    73  	GoodForUpload bool
    74  	GoodForRenew  bool
    75  	Locked        bool // Locked utilities can only be set to false.
    76  }
    77  
    78  // DownloadInfo provides information about a file that has been requested for
    79  // download.
    80  type DownloadInfo struct {
    81  	Destination     string `json:"destination"`     // The destination of the download.
    82  	DestinationType string `json:"destinationtype"` // Can be "file", "memory buffer", or "http stream".
    83  	Length          uint64 `json:"length"`          // The length requested for the download.
    84  	Offset          uint64 `json:"offset"`          // The offset within the siafile requested for the download.
    85  	SiaPath         string `json:"siapath"`         // The siapath of the file used for the download.
    86  
    87  	Completed            bool      `json:"completed"`            // Whether or not the download has completed.
    88  	EndTime              time.Time `json:"endtime"`              // The time when the download fully completed.
    89  	Error                string    `json:"error"`                // Will be the empty string unless there was an error.
    90  	Received             uint64    `json:"received"`             // Amount of data confirmed and decoded.
    91  	StartTime            time.Time `json:"starttime"`            // The time when the download was started.
    92  	StartTimeUnix        int64     `json:"starttimeunix"`        // The time when the download was started in unix format.
    93  	TotalDataTransferred uint64    `json:"totaldatatransferred"` // Total amount of data transferred, including negotiation, etc.
    94  }
    95  
    96  // FileUploadParams contains the information used by the Renter to upload a
    97  // file.
    98  type FileUploadParams struct {
    99  	Source      string
   100  	SiaPath     string
   101  	ErasureCode ErasureCoder
   102  }
   103  
   104  // FileInfo provides information about a file.
   105  type FileInfo struct {
   106  	SiaPath        string            `json:"siapath"`
   107  	LocalPath      string            `json:"localpath"`
   108  	Filesize       uint64            `json:"filesize"`
   109  	Available      bool              `json:"available"`
   110  	Renewing       bool              `json:"renewing"`
   111  	Redundancy     float64           `json:"redundancy"`
   112  	UploadedBytes  uint64            `json:"uploadedbytes"`
   113  	UploadProgress float64           `json:"uploadprogress"`
   114  	Expiration     types.BlockHeight `json:"expiration"`
   115  }
   116  
   117  // A HostDBEntry represents one host entry in the Renter's host DB. It
   118  // aggregates the host's external settings and metrics with its public key.
   119  type HostDBEntry struct {
   120  	HostExternalSettings
   121  
   122  	// FirstSeen is the last block height at which this host was announced.
   123  	FirstSeen types.BlockHeight `json:"firstseen"`
   124  
   125  	// Measurements that have been taken on the host. The most recent
   126  	// measurements are kept in full detail, historic ones are compressed into
   127  	// the historic values.
   128  	HistoricDowntime time.Duration `json:"historicdowntime"`
   129  	HistoricUptime   time.Duration `json:"historicuptime"`
   130  	ScanHistory      HostDBScans   `json:"scanhistory"`
   131  
   132  	HistoricFailedInteractions     float64 `json:"historicfailedinteractions"`
   133  	HistoricSuccessfulInteractions float64 `json:"historicsuccessfulinteractions"`
   134  	RecentFailedInteractions       float64 `json:"recentfailedinteractions"`
   135  	RecentSuccessfulInteractions   float64 `json:"recentsuccessfulinteractions"`
   136  
   137  	LastHistoricUpdate types.BlockHeight
   138  
   139  	// The public key of the host, stored separately to minimize risk of certain
   140  	// MitM based vulnerabilities.
   141  	PublicKey types.SiaPublicKey `json:"publickey"`
   142  }
   143  
   144  // HostDBScan represents a single scan event.
   145  type HostDBScan struct {
   146  	Timestamp time.Time `json:"timestamp"`
   147  	Success   bool      `json:"success"`
   148  }
   149  
   150  // HostScoreBreakdown provides a piece-by-piece explanation of why a host has
   151  // the score that they do.
   152  //
   153  // NOTE: Renters are free to use whatever scoring they feel appropriate for
   154  // hosts. Some renters will outright blacklist or whitelist sets of hosts. The
   155  // results provided by this struct can only be used as a guide, and may vary
   156  // significantly from machine to machine.
   157  type HostScoreBreakdown struct {
   158  	Score          types.Currency `json:"score"`
   159  	ConversionRate float64        `json:"conversionrate"`
   160  
   161  	AgeAdjustment              float64 `json:"ageadjustment"`
   162  	BurnAdjustment             float64 `json:"burnadjustment"`
   163  	CollateralAdjustment       float64 `json:"collateraladjustment"`
   164  	InteractionAdjustment      float64 `json:"interactionadjustment"`
   165  	PriceAdjustment            float64 `json:"pricesmultiplier"`
   166  	StorageRemainingAdjustment float64 `json:"storageremainingadjustment"`
   167  	UptimeAdjustment           float64 `json:"uptimeadjustment"`
   168  	VersionAdjustment          float64 `json:"versionadjustment"`
   169  }
   170  
   171  // RenterPriceEstimation contains a bunch of files estimating the costs of
   172  // various operations on the network.
   173  type RenterPriceEstimation struct {
   174  	// The cost of downloading 1 TB of data.
   175  	DownloadTerabyte types.Currency `json:"downloadterabyte"`
   176  
   177  	// The cost of forming a set of contracts using the defaults.
   178  	FormContracts types.Currency `json:"formcontracts"`
   179  
   180  	// The cost of storing 1 TB for a month, including redundancy.
   181  	StorageTerabyteMonth types.Currency `json:"storageterabytemonth"`
   182  
   183  	// The cost of consuming 1 TB of upload bandwidth from the host, including
   184  	// redundancy.
   185  	UploadTerabyte types.Currency `json:"uploadterabyte"`
   186  }
   187  
   188  // RenterSettings control the behavior of the Renter.
   189  type RenterSettings struct {
   190  	Allowance        Allowance `json:"allowance"`
   191  	MaxUploadSpeed   int64     `json:"maxuploadspeed"`
   192  	MaxDownloadSpeed int64     `json:"maxdownloadspeed"`
   193  	StreamCacheSize  uint64    `json:"streamcachesize"`
   194  }
   195  
   196  // HostDBScans represents a sortable slice of scans.
   197  type HostDBScans []HostDBScan
   198  
   199  func (s HostDBScans) Len() int           { return len(s) }
   200  func (s HostDBScans) Less(i, j int) bool { return s[i].Timestamp.Before(s[j].Timestamp) }
   201  func (s HostDBScans) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   202  
   203  // MerkleRootSet is a set of Merkle roots, and gets encoded more efficiently.
   204  type MerkleRootSet []crypto.Hash
   205  
   206  // MarshalJSON defines a JSON encoding for a MerkleRootSet.
   207  func (mrs MerkleRootSet) MarshalJSON() ([]byte, error) {
   208  	// Copy the whole array into a giant byte slice and then encode that.
   209  	fullBytes := make([]byte, crypto.HashSize*len(mrs))
   210  	for i := range mrs {
   211  		copy(fullBytes[i*crypto.HashSize:(i+1)*crypto.HashSize], mrs[i][:])
   212  	}
   213  	return json.Marshal(fullBytes)
   214  }
   215  
   216  // UnmarshalJSON attempts to decode a MerkleRootSet, falling back on the legacy
   217  // decoding of a []crypto.Hash if that fails.
   218  func (mrs *MerkleRootSet) UnmarshalJSON(b []byte) error {
   219  	// Decode the giant byte slice, and then split it into separate arrays.
   220  	var fullBytes []byte
   221  	err := json.Unmarshal(b, &fullBytes)
   222  	if err != nil {
   223  		// Encoding the byte slice has failed, try decoding it as a []crypto.Hash.
   224  		var hashes []crypto.Hash
   225  		err := json.Unmarshal(b, &hashes)
   226  		if err != nil {
   227  			return err
   228  		}
   229  		*mrs = MerkleRootSet(hashes)
   230  		return nil
   231  	}
   232  
   233  	umrs := make(MerkleRootSet, len(fullBytes)/32)
   234  	for i := range umrs {
   235  		copy(umrs[i][:], fullBytes[i*crypto.HashSize:(i+1)*crypto.HashSize])
   236  	}
   237  	*mrs = umrs
   238  	return nil
   239  }
   240  
   241  // A RenterContract contains metadata about a file contract. It is read-only;
   242  // modifying a RenterContract does not modify the actual file contract.
   243  type RenterContract struct {
   244  	ID            types.FileContractID
   245  	HostPublicKey types.SiaPublicKey
   246  	Transaction   types.Transaction
   247  
   248  	StartHeight types.BlockHeight
   249  	EndHeight   types.BlockHeight
   250  
   251  	// RenterFunds is the amount remaining in the contract that the renter can
   252  	// spend.
   253  	RenterFunds types.Currency
   254  
   255  	// The FileContract does not indicate what funds were spent on, so we have
   256  	// to track the various costs manually.
   257  	DownloadSpending types.Currency
   258  	StorageSpending  types.Currency
   259  	UploadSpending   types.Currency
   260  
   261  	// Utility contains utility information about the renter.
   262  	Utility ContractUtility
   263  
   264  	// TotalCost indicates the amount of money that the renter spent and/or
   265  	// locked up while forming a contract. This includes fees, and includes
   266  	// funds which were allocated (but not necessarily committed) to spend on
   267  	// uploads/downloads/storage.
   268  	TotalCost types.Currency
   269  
   270  	// ContractFee is the amount of money paid to the host to cover potential
   271  	// future transaction fees that the host may incur, and to cover any other
   272  	// overheads the host may have.
   273  	//
   274  	// TxnFee is the amount of money spent on the transaction fee when putting
   275  	// the renter contract on the blockchain.
   276  	//
   277  	// SiafundFee is the amount of money spent on siafund fees when creating the
   278  	// contract. The siafund fee that the renter pays covers both the renter and
   279  	// the host portions of the contract, and therefore can be unexpectedly high
   280  	// if the the host collateral is high.
   281  	ContractFee types.Currency
   282  	TxnFee      types.Currency
   283  	SiafundFee  types.Currency
   284  }
   285  
   286  // ContractorSpending contains the metrics about how much the Contractor has
   287  // spent during the current billing period.
   288  type ContractorSpending struct {
   289  	// ContractFees are the sum of all fees in the contract. This means it
   290  	// includes the ContractFee, TxnFee and SiafundFee
   291  	ContractFees types.Currency `json:"contractfees"`
   292  	// DownloadSpending is the money currently spent on downloads.
   293  	DownloadSpending types.Currency `json:"downloadspending"`
   294  	// StorageSpending is the money currently spent on storage.
   295  	StorageSpending types.Currency `json:"storagespending"`
   296  	// ContractSpending is the total amount of money that the renter has put
   297  	// into contracts, whether it's locked and the renter gets that money
   298  	// back or whether it's spent and the renter won't get the money back.
   299  	TotalAllocated types.Currency `json:"totalallocated"`
   300  	// UploadSpending is the money currently spent on uploads.
   301  	UploadSpending types.Currency `json:"uploadspending"`
   302  	// Unspent is locked-away, unspent money.
   303  	Unspent types.Currency `json:"unspent"`
   304  	// ContractSpendingDeprecated was renamed to TotalAllocated and always has the
   305  	// same value as TotalAllocated.
   306  	ContractSpendingDeprecated types.Currency `json:"contractspending"`
   307  	// WithheldFunds are the funds from the previous period that are tied up
   308  	// in contracts and have not been released yet
   309  	WithheldFunds types.Currency `json:"withheldfunds"`
   310  	// ReleaseBlock is the block at which the WithheldFunds should be
   311  	// released to the renter, based on worst case.
   312  	// Contract End Height + Host Window Size + Maturity Delay
   313  	ReleaseBlock types.BlockHeight `json:"releaseblock"`
   314  	// PreviousSpending is the total spend funds from old contracts
   315  	// that are not included in the current period spending
   316  	PreviousSpending types.Currency `json:"previousspending"`
   317  }
   318  
   319  // A Renter uploads, tracks, repairs, and downloads a set of files for the
   320  // user.
   321  type Renter interface {
   322  	// ActiveHosts provides the list of hosts that the renter is selecting,
   323  	// sorted by preference.
   324  	ActiveHosts() []HostDBEntry
   325  
   326  	// AllHosts returns the full list of hosts known to the renter.
   327  	AllHosts() []HostDBEntry
   328  
   329  	// Close closes the Renter.
   330  	Close() error
   331  
   332  	// Contracts returns the staticContracts of the renter's hostContractor.
   333  	Contracts() []RenterContract
   334  
   335  	// OldContracts returns the oldContracts of the renter's hostContractor.
   336  	OldContracts() []RenterContract
   337  
   338  	// ContractUtility provides the contract utility for a given host key.
   339  	ContractUtility(pk types.SiaPublicKey) (ContractUtility, bool)
   340  
   341  	// CurrentPeriod returns the height at which the current allowance period
   342  	// began.
   343  	CurrentPeriod() types.BlockHeight
   344  
   345  	// PeriodSpending returns the amount spent on contracts in the current
   346  	// billing period.
   347  	PeriodSpending() ContractorSpending
   348  
   349  	// DeleteFile deletes a file entry from the renter.
   350  	DeleteFile(path string) error
   351  
   352  	// Download performs a download according to the parameters passed, including
   353  	// downloads of `offset` and `length` type.
   354  	Download(params RenterDownloadParameters) error
   355  
   356  	// Download performs a download according to the parameters passed without
   357  	// blocking, including downloads of `offset` and `length` type.
   358  	DownloadAsync(params RenterDownloadParameters) error
   359  
   360  	// ClearDownloadHistory clears the download history of the renter
   361  	// inclusive for before and after times.
   362  	ClearDownloadHistory(after, before time.Time) error
   363  
   364  	// DownloadHistory lists all the files that have been scheduled for download.
   365  	DownloadHistory() []DownloadInfo
   366  
   367  	// File returns information on specific file queried by user
   368  	File(siaPath string) (FileInfo, error)
   369  
   370  	// FileList returns information on all of the files stored by the renter.
   371  	FileList() []FileInfo
   372  
   373  	// Host provides the DB entry and score breakdown for the requested host.
   374  	Host(pk types.SiaPublicKey) (HostDBEntry, bool)
   375  
   376  	// InitialScanComplete returns a boolean indicating if the initial scan of the
   377  	// hostdb is completed.
   378  	InitialScanComplete() (bool, error)
   379  
   380  	// LoadSharedFiles loads a '.sia' file into the renter. A .sia file may
   381  	// contain multiple files. The paths of the added files are returned.
   382  	LoadSharedFiles(source string) ([]string, error)
   383  
   384  	// LoadSharedFilesASCII loads an ASCII-encoded '.sia' file into the
   385  	// renter.
   386  	LoadSharedFilesASCII(asciiSia string) ([]string, error)
   387  
   388  	// PriceEstimation estimates the cost in siacoins of performing various
   389  	// storage and data operations.
   390  	PriceEstimation() RenterPriceEstimation
   391  
   392  	// RenameFile changes the path of a file.
   393  	RenameFile(path, newPath string) error
   394  
   395  	// EstimateHostScore will return the score for a host with the provided
   396  	// settings, assuming perfect age and uptime adjustments
   397  	EstimateHostScore(entry HostDBEntry) HostScoreBreakdown
   398  
   399  	// ScoreBreakdown will return the score for a host db entry using the
   400  	// hostdb's weighting algorithm.
   401  	ScoreBreakdown(entry HostDBEntry) HostScoreBreakdown
   402  
   403  	// Settings returns the Renter's current settings.
   404  	Settings() RenterSettings
   405  
   406  	// SetSettings sets the Renter's settings.
   407  	SetSettings(RenterSettings) error
   408  
   409  	// ShareFiles creates a '.sia' file that can be shared with others.
   410  	ShareFiles(paths []string, shareDest string) error
   411  
   412  	// ShareFilesAscii creates an ASCII-encoded '.sia' file.
   413  	ShareFilesASCII(paths []string) (asciiSia string, err error)
   414  
   415  	// Streamer creates a io.ReadSeeker that can be used to stream downloads
   416  	// from the Sia network and also returns the fileName of the streamed
   417  	// resource.
   418  	Streamer(siaPath string) (string, io.ReadSeeker, error)
   419  
   420  	// Upload uploads a file using the input parameters.
   421  	Upload(FileUploadParams) error
   422  }
   423  
   424  // RenterDownloadParameters defines the parameters passed to the Renter's
   425  // Download method.
   426  type RenterDownloadParameters struct {
   427  	Async       bool
   428  	Httpwriter  io.Writer
   429  	Length      uint64
   430  	Offset      uint64
   431  	SiaPath     string
   432  	Destination string
   433  }