I meandered around the WindowPost deadline and vesting schedule logic in the builtin Actors code today. I'm sharing my notes here in case others find them helpful.
Window Posts, Proving Periods, and Deadlines
- All miners must submit a proof ("WindowPost") for each of their sectors once within a 24-hour period.
- The 24-hour Window Post duration is divided into 48 "deadlines". Each deadline is 30 minutes long, and a miner must submit WindowPosts for a subset of its "partitions" during each deadline. A "partition" is essentially a grouping/subset of the miner's sectors (for which it has already submitted a PoRep). Sectors can be moved between partitions, and partitions can be moved between deadlines.
- For the sake of this discussion, assume that the miner has partitions to prove for all of its 48 deadlines.
- WindowPosts are only submitted for sectors that haven't expired, been terminated, or declared faulty.
- When the Miner Actor is created, it is assigned a "
proving_period_start
" epoch.
- This represents the epoch after which the miner will have to submit a WindowPost for its first deadline (i.e., the start of the 0th deadline where deadline indices range from [0, 47]).
- The logic to initialize this
proving_period_start
can be found at:
- Link to the code
- Essentially, a random offset in [0, 2880] is selected (each epoch lasts 30 seconds, so 2880 epochs equal the Window Post duration of 24 hours). The code ensures that the miner's proving period start falls a few epochs after the current epoch, allowing miners a grace period post initialisation before they need to submit WindowPosts. The offset helps randomize/shard proving period starts across different miners to avoid the thundering herds problem.
- The "
proving_period_start
" resets after the WindowPost for the last (i.e., the 47th) deadline is submitted (assuming all 48 deadlines have partitions to prove).
- The logic for this reset can be found here.
- It is basically
new_proving_period_start
= **
proving_period_start**
+ 24 hours
Locking/Unlocking of Rewards and the Vesting Schedule
- When a miner receives a block reward, 25% is unlocked immediately and added to the miner's unlocked balance. The remaining 75% is set up for linear vesting over 180 days. This vesting schedule is "quantized" to every 12 hours meaning vesting occurs every 12 hour boundaries, starting from the current
proving_period_start
, and lasts up to 180 days.
- The vesting schedule essentially consists of a list of (vesting epoch → token amount) sorted in ascending order of epochs, maintained on the Miner Actor state.
- As new rewards are introduced, these vesting schedules are merged. If two vesting events fall on the same epoch, their token amounts are summed. Hence, the top-level Miner Actor state only ever tracks one vesting schedule.
- The code for building/merging these vesting schedules is available here.
- Unlocking the vested funds is straightforward. During every "handle proving deadline" cron job (which runs every 30 minutes), the vested funds for the current epoch are unlocked and added to the miner's balance.
- This process can be found here.
- Interestingly, although rewards are quantized to vest every 12 hours, the system tries to vest funds during every "handle proving deadline" cron job, which occurs every 30 minutes. This redundancy can be optimised to make the cron job more efficient, as highlighted in this discussion.