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 }