gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/contractor/README.md (about)

     1  # Contractor
     2  
     3  The Contractor is responsible for forming and renewing file contracts with
     4  hosts. Its goal is to manage the low-level details of the negotiation, revision,
     5  and renewal protocols, such that the renter can operate at a higher level of
     6  abstraction. Ideally, the renter should be mostly ignorant of the Sia protocol,
     7  instead focusing on file management, redundancy, and upload/download algorithms.
     8  
     9  The Contractor is also responsible for various forms of contract maintenance
    10  including contract recovery, utility checking, archiving, and monitoring its own
    11  contracts using the watchdog subsystem.
    12  
    13  ## Design Challenges
    14  
    15  The primary challenge of the Contractor is that it must be smart enough for the
    16  user to feel comfortable allowing it to spend their money. Because contract
    17  renewal is a background task, it is difficult to report errors to the user and
    18  defer to their decision. For example, what should the Contractor do in the
    19  following scenarios?
    20  
    21  - The contract set is up for renewal, but the average host price has increased,
    22    and now the allowance is not sufficient to cover all of the user's uploaded
    23    data.
    24  
    25  - The user sets an allowance of 10 hosts. The Contractor forms 5 contracts, but
    26    the rest fail, and the remaining hosts in the HostDB are too expensive.
    27  
    28  - After contract formation succeeds, 2 of 10 hosts become unresponsive. Later,
    29    another 4 become unresponsive.
    30  
    31  Waiting for user input is dangerous because if the contract period elapses, data
    32  is permanently lost. The Contractor should treat this as the worst-case
    33  scenario, and take steps to prevent it, so long as the allowance is not
    34  exceeded. However, since the Contractor has no concept of redundancy, it is not
    35  well-positioned to determine which sectors to sacrifice and which to preserve.
    36  The Contractor also lacks the ability to reupload data; it can download sectors,
    37  but it does not know the decryption keys or erasure coding metadata required to
    38  reconstruct the original data. It follows that these responsibilities must be
    39  delegated to the renter.
    40  
    41  ## Alerts
    42  
    43  `WalletLockedDuringMaintenance` is registered if the wallet is locked while the
    44  contractor is attempting to create contracts.
    45  
    46  `AllowanceLowFunds`  is registered if the contractor lacks the necessary fund to
    47  renew or form contracts.
    48  
    49  ## TODOs
    50  * [ ] (watchdog) Perform action when storage proof is found and when missing at the end of the window.
    51  * [ ] (watchdog) Add renter dependencies in `sweepContractInputs` if necessary.
    52  
    53  
    54  ## Subsystems
    55  The Contractor is split up into the following subsystems:
    56  - [Allowance](#allowance-subsystem)
    57  - [Contract Maintenance Subsystem](#contract-maintenance-subsystem)
    58  - [Churn Limiter Subsystem](#churn-limiter-subsystem)
    59  - [Recovery Subsystem](#recovery-subsystem)
    60  - [Session Subsystem](#session-subsystem)
    61  - [Persistence Subsystem](#persistence-subsystem)
    62  - [Watchdog Subsystem](#watchdog-subsystem)
    63  
    64  
    65  ## Allowance Subsystem
    66  **Key Files**
    67  - [Allowance](./allowance.go)
    68  
    69  The allowance subsystem is used for setting and cancelling allowances. A change
    70  in allowance does not necessarily cause changes in contract formation.
    71  
    72  ### Exports
    73  - `SetAllowance` is exported by the `Contractor` and allows the caller to
    74    dictate the contract spendings of the `Renter`.
    75  
    76  ### Outbound Complexities
    77  - `callInterruptContractMaintenance` is used when setting the allowance to
    78    stop and restart contract maintenance with the new allowance settings in
    79    place.
    80  
    81  
    82  ## Contract Maintenance Subsystem
    83  **Key Files**
    84  - [contractmaintenance.go](./contractmaintenance.go)
    85  
    86  The contract maintenance subsystem is responsible for forming and renewing
    87  contracts, and for other general maintenance tasks.
    88  
    89  ### Contract Formation
    90  
    91  Contract formation does not begin until the user first calls `SetAllowance`. An
    92  allowance dictates how much money the Contractor is allowed to spend on file
    93  contracts during a given period. When the user calls `SetAllowance` the
    94  [Allowance subsystem](#allowance-subsytem) updates the allowance and restarts the
    95  Maintenance subsystem so that it will form new contracts with the changed
    96  settings. New contracts will only be formed if needed and if the allowance is
    97  sufficiently greater than the previous allowance, where "sufficiently greater"
    98  currently means "enough money to pay for at least one additional sector on every
    99  host." This allows the user to increase the amount of available storage
   100  immediately, at the cost of some complexity.
   101  
   102  The Contractor forms many contracts in parallel with different host, and tries
   103  to keep all the contracts "consistent" -- that is, they should all have the same
   104  storage capacity, and they should all end at the same height. Hosts are selected
   105  from the HostDB. There is no support for manually specifying hosts, but the
   106  Contractor will not form contracts with multiple hosts within the same subnet.
   107  
   108  **Contract Renewal**
   109  
   110  Contracts are automatically renewed by the Contractor at a safe threshold before
   111  they are set to expire. This value is set in the allowance. When contracts are
   112  renewed, they are renewed with the current allowance, which may differ from the
   113  allowance that was used to form the initial contracts. In general, this means
   114  that allowance modifications only take effect upon the next "contract cycle".
   115  
   116  ### Other Maintenance Checks
   117  
   118  - Check the contract set for **duplicate contracts** and remove them.
   119  - **Prune hosts**  that are no longer used for any contracts and hosts that violate rules about address ranges
   120  - **Check the utility of opened contracts** by figuring out which contracts are still useful for uploading or for renewing
   121  - **Archive contracts** which have expired by placing them in a historic contract set.
   122  
   123  ### Inbound Complexities
   124  - `threadedContractMaintenance` is called by the
   125    [Allowance subsystem](#allowance-subsystem) when setting allowances, when `CancelContract`
   126    is called from the `Contractor`, and also with every `ConsensusChange` by the
   127    `Contractor` in the `ProcessConsensusChange` when the `Contractor` is synced.
   128  - `callInterruptContractMaintenance` is used by [Allowance
   129    subsystem](#allowance-subsystem) when setting the allowance to
   130    stop and restart contract maintenance with the new allowance settings in
   131    place.
   132  - `callNotifyDoubleSpend` is a Contract Maintenance call used by the watchdog to
   133    indicate that a contract is double-spent and triggers actions from the
   134    Contractor.
   135  
   136  ### Outbound Complexities
   137  - `callInitRecoveryScan` in the [Recovery subsystem](#recovery-subsystem) is
   138    called to scan blocks for recoverable contracts.
   139  - `save` is called to persist the contractor whenever the `Contractor's` state
   140    is updated during maintenance.
   141  - Funds established by the [Allowance subsystem](#allowance-subsystem) are used
   142    and deducted appropriately during maintenance to form and renew contracts.
   143  - `callNotifyChurnedContract` is used when a contract utility changes from GFR
   144    to !GFR.
   145  - `threadedSendMostRecentRevision` in the [Watchdog subsystem](#watchdog-subsystem)
   146     is called when a contract is renewed and no new revisions are expected.
   147  
   148  
   149  ## Churn Limiter Subsystem
   150  **Key Files**
   151  - [churnlimiter.go](./churnlimiter.go)
   152  
   153  The Churn Limiter is responsible for decreasing contract churn. It keeps track
   154  of the aggregate size of all contracts churned in the current period. Churn is
   155  limited by keeping contracts with low-scoring hosts around if the maximum
   156  aggregate for the period has been reached.
   157  
   158  ### Exports
   159  - `SetMaxPeriodChurn` is exported by the `Contractor` and allows the caller
   160     to set the maximum allowed churn in bytes per period.
   161  
   162  ### Inbound Complexities
   163  - `callNotifyChurnedContract` is used when contracts are marked GFR after
   164     previously being !GFR.
   165  - `callBumpChurnBudget` is used to increase the churn budget when new blocks
   166     are processed.
   167  - `callResetAggregateChurn` resets the aggregate churn and is called every
   168     time the contractor enters a new period.
   169  - `callPersistData` is called whenever the contractor's `persistData` is
   170     called.
   171  
   172  
   173  ## Recovery Subsystem
   174  **Key Files**
   175  - [recovery.go](./recovery.go)
   176  
   177  The Contractor is also responsible for scanning the Sia blockchain and
   178  recovering all unexpired contracts which belong to the current wallet seed. The
   179  relevant contracts are found by examining the contract identifier attached to
   180  every file contract. Recovery scans are initiated whenever the wallet is
   181  unlocked or when a new seed is imported.
   182  
   183  A recoverable contract is recovered by reinitiating a session with the relevant
   184  host and by getting the most recent revision from the host using this session.
   185  
   186  ### Inbound Complexities
   187  - `callInitRecoveryScan` is called in the [Maintenance
   188    subsystem](#contract-maintenance-subsystem) to initiate recovery scans.
   189  - `callRecoverContracts` is called in the [Maintenance
   190    subsystem](#contract-maintenance-subsystem) to recover contracts found in a
   191    recovery scan.
   192  
   193  
   194  ## Session Subsystem
   195  **Key Files**
   196  - [session.go](./session.go)
   197  - [downloader.go](./downloader.go)
   198  - [editor.go](./editor.go)
   199  
   200  The Session subsystem provides an interface for communication with hosts. It
   201  allows the contractor to modify its contracts through the renter-host protocol.
   202  Sessions are used to initiate uploads, downloads, and file modifications. This
   203  subsystem exports several methods used outside of the `Contractor` for this
   204  purpose.
   205  
   206  The session subsystem will watch out for certain host behaviors that indicate
   207  the host is permanently unusable. If this happens, the session subsystem will
   208  call 'MarkBadContract', which will prevent the contract from being considered a
   209  part of the usable contracts, and allow the repair process to happen.
   210  
   211  Pre-v1.4.0 contracts using an older version of the renter-host protocol use the
   212  Editor and Downloader interfaces to interact with hosts.
   213  
   214  ### Pre-v1.4.0 Contract Modification
   215  
   216  Modifications to file contracts are mediated through the Editor interface. An
   217  Editor maintains a network connection to a host, over which is sends
   218  modification requests, such as "delete sector 12." After each modification, the
   219  Editor revises the underlying file contract and saves it to disk.
   220  
   221  ### Exports
   222  The following `Session` methods are all exported by the Contractor:
   223  - `Address`
   224  - `Close`
   225  - `ContractID`
   226  - `Download`
   227  - `DownloadIndex`
   228  - `EndHeight`
   229  - `Upload`
   230  - `Replace`
   231  
   232  
   233  ## Persistence Subsystem
   234  **Key Files**
   235  - [persist.go](./persist.go)
   236  - [persist\_journal.go](./persist_journal.go)
   237  
   238  
   239  The Persistence subsystem is used to persist Contractor data across sessions.
   240  Currently it uses the Sia persist package. Prior to v1.3.0 the persistence
   241  subsystem used a journal system which is no longer used. If, on startup, this
   242  old journal system is found, the Contractor will convert it into the new
   243  Persistence subsystem.
   244  
   245  ### Inbound Complexities
   246  - `save` is called from the [Allowance](#allowance-subsystem), and
   247    [Maintenance](#contract-maintenance-subsystem) subsystems to persist the
   248    `Contractor` when its internal state is updated.
   249  
   250  ### Outbound Complexities
   251  The persist system is also responsible for persisting the [Watchdog
   252  subsystem](#watchdog-subsystem).
   253  
   254  
   255  ## Watchdog Subsystem
   256  **Key Files**
   257  - [watchdog.go](./watchdog.go)
   258  - [watchdog\_persist.go](./watchdog\_persist.go)
   259  
   260  The watchdog is responsible for monitoring the blockchain for file contracts,
   261  revisions, and storage proofs that are relevant to the contractor.
   262  
   263  To scan for revisions, the watchdog is used during the Contractor's
   264  `ProcessConsensusChange` method and during the recovery subsystem's
   265  `ProcessConsensusChange` method. 
   266  
   267  When processing a newly added block the watchdog checks if any contracts,
   268  revision, or storage proofs for a monitored contract have appeared on-chain. For
   269  file contracts being monitored that haven't yet appeared on-chain, the watchdog
   270  also monitors all the parent Siacoin outputs used in the creation of the
   271  contract. It will update the dependency set of that contract as blocks are added
   272  and reverted. If a contract's inputs are ever double-spent, the  watchdog
   273  notifies the Contractor. The Contractor returns the contract's funds to the
   274  allowance, and marks the contract as `!GoodForUpload` and `!GoodForRenew`,
   275  
   276  The watchdog will also check if any monitored contracts revisions or storage
   277  proofs were removed in a reverted blocks and marks them as such. Note that once
   278  a the storage proof window for a file contract elapses for the first time, the
   279  watchdog will no longer monitor that contract. This is acceptable because even
   280  if the storage proof is reorged out, the host has at least proven they fulfilled
   281  their storage obligation once. It is up to the host to re-post storage proofs
   282  if they are reorged out, if they want to claim valid proof outputs afterwards.
   283  
   284  When the watchdog is synced to the `consensusset` it will do all of its checks
   285  on monitored contracts in `managedCheckContracts`. It waits until being synced,
   286  rather than taking action in the middle of a `ProcessConsensusChange` call to
   287  avoid taking actions that would be prevented if e.g. the next block in a
   288  `ConsensusChange` was checked. For example, a formation transaction may be
   289  reverted and re-applied in the same consensus change. In this case, the watchdog
   290  should not take any actions.
   291  
   292  The watchdog does the following checks on monitored contracts.
   293  - check that monitored file contract formation transaction sets appeared
   294    on-chain in the expected number of blocks. 
   295  - re-send the transaction set if not, and double-spend the inputs used with the
   296    set if much more time has elapsed.
   297  - check if any monitored contracts should have a more recent revision on-chain
   298    already. If not, the watchdog will send the latest revision transaction out.
   299  - Check if storage proofs for a contract were found at the end of the expiration
   300    window
   301  
   302  ## Inbound Complexities
   303  - `threadedSendMostRecentRevision` is called in a go-routine from the Contract
   304    Maintenance subsystem when a contract is renewed and no new revisions are
   305    expected.
   306  - `callMonitorContract` is called from the Contract Maintenance and Recovery
   307    subsystems whenever contracts are formed, renewed, or recovered.
   308  - `callScanConsensusChange`is used in the `ProcessConsensusChange` method of the
   309    contractor to let the watchdog scan blocks.
   310  - `callPersistData` is called whenever the contractor's `persistData` is
   311    called.
   312  
   313  ## Outbound Complexities
   314  - `callNotifyDoubleSpend` is a Contract Maintenance call used by the watchdog to
   315    indicate that a contract is double-spent and triggers actions from the
   316    Contractor.
   317  
   318  ## State Complexities
   319  All state updates from the watchdog are driven by changes observed in
   320  `ProcessConsensusChange` and from contract formation and renewal which cause a
   321  file contract to be monitored. Therefore, the watchdog persist needs to be
   322  synced with the most recent consensus change.
   323  
   324  ## Why The Watchdog Should Sweep Renter Inputs
   325  
   326  If the watchdog fails to find a monitored file contract on-chain before its
   327  `formationSweepHeight` the watchdog will sweep the inputs used by the renter to
   328  create the file contract. This action must take place to prevent the renter from
   329  overspending its allowance.
   330  
   331  If the contractor were to simply create new contracts while other contracts were
   332  still unconfirmed, it would be possible to overspend the set allowance. When the
   333  watchdog sweeps its inputs successfully, the contract will be marked as
   334  double-spent in which case the allowance funds are returned for further use.