## Motivation

The StorageDurationMultiplier FIP proposes increasing the maximum sector commitment length from 1.5 to 5 years. The naive way to achieve this goal is to increase the `MaxSectorDuration`

parameter from 1.5 to 5 years. This parameter tweak seems very simple, but it has an unaccounted externality of causing mitigation of possible PoRep bug to be much more difficult.

What follows is an implementation proposal allowing for a significant reduction in the effort required for future mitigation, while causing only a slight increase in complexity.

## Proposal

The core of the proposal is to separate the period of validity of a proof from the period of commitment for a sector. This leaves the 1.5-year sector extension process in place to maintain proof validity, but allows SPs to commit to longer periods.

The existing sector `Expiration`

property would be renamed to `CommitmentExpiration`

with a duration range from `MinSectorLifetime`

to `MaxSectorLifetime`

.

A new sector property is introduced called `ProofExpiration`

. The initial value of `ProofExpiration`

always falls into the range of `(CurrentEpoch + MaxProofDuration - ProofRefereshWindow, CurrentEpoch + MaximumProofDuration]`

or `CommitmentExpiration`

whichever is smaller.

`MaxProofDuration`

: maximum period from last commitment or refresh for which a PoRep is valid, set to 1.5y to match current behaviour`ProofRefreshWindow`

: a window of time before ProofExpiration when the proof can be extended, set to 0.5y

The proof refresh window creates a trade-off: the larger the window, the more refreshes can happen in a singular batch, but more frequently each proof must be refreshed.
For example with `MaxProofDuration`

of 1.5y and `ProofRefreshWindow`

of 0.5y, each extension will be at least 1y and at most 1.5y. SPs will have to refresh sectors every `MaxProofDuration - ProofRefereshWindow`

epochs.

The proof expiration is not freely chosen by the SP, but takes a value that is derived and quantised from the sector’s activation epoch. It is calculated as:

$\begin{align*} \Delta E =\ & \mathrm{MaxProofDuration} - \mathrm{ProofRefereshWindow} \\ \text{ProofExpiration} =\ & \text{SectorActivation} + \Delta E \cdot \left\lceil \frac{\text{CurrentEpoch - SectorActivation} + 1}{\Delta E}\right \rceil + \mathrm{ProofRefereshWindow} \end{align*}$Current Epoch | Current Proof Expiration | New Proof Expiration | New Proof Duration |

0 - Sector Activation | NaN | 1.5y | 1.5y |

1.0000y - Refresh | 1.5y | 2.5y | 1.5y |

1.4999y - Refresh | 1.5y | 2.5y | 1y |

1.6y - Refresh does nothing | 2.5y | 2.5y | 0.9y |

2.0000y - Refresh | 2.5y | 3.5y | 1.5y |

2.4999y - Refresh | 2.5y | 3.5y | 1y |

At initial commitment, it should calculate `MaxProofDuration`

, then the refresh has to be made every year. We can play with longer durations or shorter refresh windows, but shorter refresh window doesn’t buy us much.

Storage Provider can at any point call `RefreshProofEpiration(SectorSelector)`

requesting a refreshed proof expiration. This call only results in an actual refresh of the `ProofExpiration`

if called within `ProofRefereshWindow`

of the `ProofExpiration`

.
This call will refresh the `ProofExpiration`

of each of the requested sectors to fall into `(CurrentEpoch + MaxProofDuration - ProofRefereshWindow, CurrentEpoch + MaximumProofDuration]`

according to the above formula or `CommitmentExpiration`

whichever is smaller.

In case of a PoRep bug, the `RefreshProofExpiration`

method would be disallowed for sectors created with insecure PoRep.
Other policies are possible too, such as requiring re-sealing or some other computation. The mechanism can support other policies developed in response to a concrete security flaw.

It also has the following benefits:

- The bug response upgrade does not need to iterate over all sectors within one epoch. The mechanism to iterate over all sectors exists in form of an expiration schedule.
- Sectors’ ProofExpirations are spread out uniformly (according to onboarding) and are not possible to manipulate on a short timescale, which could be an issue otherwise leading to non-even distribution and terminations of sectors.
- Storage Providers must take action to avoid early sector termination when a Bug Response Policy is implemented, instead of the network having to create a new mechanism to enforce the Bug Response Policy.

Limitations of this mechanism include:

- The response period must be specified now but can be modified at cost of some additional complexity in future.
- Relative to the naive approach of just increasing the maximum sector duration, this mechanism requires more SP operational costs and on-chain activity. But only a little less than the amount required today to extend sectors. (Less because we won’t recompute pledge, etc).
- Relative to the naive approach, this mechanism introduces operational risk to SPs, who will pay a termination fee for failing to refresh expiring proofs. Since the sector duration multiplier proposal greatly increases rewards for long commitments, this operational cost might be considered just part of the risk taken in pursuit of those rewards. On the other hand, SPs are given a generous window of time to refresh their sectors.

## Implementation

It should be possible to avoid changing the sector state as there are only three valid `ProofExpiration`

values for a given active sector:

`SectorActivation + ΔE * ceil((CurrentEpoch - SectorActivation + 1) / ΔE) - ΔE + ProofRefereshWindow`

(1)`SectorActivation + ΔE * ceil((CurrentEpoch - SectorActivation + 1) / ΔE) + ProofRefereshWindow`

(2)`CommitmentExpiration`

if it is smaller than either of the above (3)

Currently, sectors are scheduled for expiration in the `ExpirationSet`

at the epoch of `Expiration`

(called`CommitmentExpiration`

in this document). All future extensions and new sectors should be scheduled at the `ProofExpiration`

epoch.

To check when a given sector is scheduled for expiration, the `ExpirationSet`

would have to be checked at most two points out of the candidate `ProofExpiration`

values.

On the other hand, when refreshing the sector’s expiration two operations have to be performed:

- removal of old expiration: always at (1), if not present at epoch (1), then the sector cannot be refreshed
- scheduling of new expiration: at (2) or (3), whichever is smaller

### Accelerated Expiration Set

If in case of a significant PoRep bug, proofs had to be updated sooner than the 1.5y timeline, it should be possible to accelerate the `ExpirationSet`

.

Today the epoch number within the expiration set has the same definition as the chain epoch. A mapping function could be introduced to the `ExpirationSet`

, such that the schedule is accelerated.

For example, if the mapping function $f(x) = x$, is changed to $f(x) = \begin{cases} x & \text{if}\ x < E \\ E + \alpha \cdot (x -E) & \text{otherwise} \end{cases}$ where $E$ is the upgrade epoch and $\alpha$ is the acceleration factor, and expirations are processed within the range $\big(f(x - 1), f(x)\big]$ at epoch $x$. If for example $\alpha = 2$ is used, the expiration set will be integrated at twice the normal rate, resulting in maximum proof expiration of 0.75y. If a new expiration is to be scheduled, it should also use the updated $f(x)$ function.