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