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.
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
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:
Current Proof Expiration
New Proof Expiration
New Proof Duration
0 - Sector Activation
1.0000y - Refresh
1.4999y - Refresh
1.6y - Refresh does nothing
2.0000y - Refresh
2.4999y - Refresh
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
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.
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)
CommitmentExpirationif it is smaller than either of the above (3)
Currently, sectors are scheduled for expiration in the
ExpirationSet at the epoch of
CommitmentExpiration in this document). All future extensions and new sectors should be scheduled at the
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
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
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 , is changed to where is the upgrade epoch and is the acceleration factor, and expirations are processed within the range at epoch . If for example 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 function.