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