# Actor Spec: StoragePower
[Back to Master Tracking Doc](https://hackmd.io/LOZjAsz-THelSD5lWqSVlw)
## Contents
[TOC]
## At a Glance
The StoragePower actor has a few roles:
* Entry point into Filecoin for Miners
* Keeps track of created Miner instances, as well as miners with power above consensus threshold
* Manages active Miner instances and associated StoragePower accounting
* Tracks deferred cron events for each Miner, and ensures these events are executed at specific epochs (through `OnEpochTickEnd`)
* Aggregates Proofs of Replication (PoReps) for Miners, and submits them for bulk verification once per epoch
* Updates network KPI via Reward actor.
**Actor Type:**
- Singleton
- Address: 4
**Exported Methods:**
1. Constructor
2. CreateMiner
3. UpdateClaimedPower
4. EnrollCronEvent
5. OnEpochTickEnd
6. UpdatePledgeTotal
7. SubmitPoRepForBulkVerify
8. CurrentTotalPower
## Terms
* **RawBytePower**: A Miner's power in terms of the number of bytes in the Miner's committed sectors.
* **QualityAdjPower**: A Miner's RawBytePower adjusted for the number of deals stored in the Miner's committed sectors.
* **ConsensusMinerMinPower**: The minimum QualityAdjPower a Miner must have in order to qualify for leader election.
## State
```go=
type State struct {
TotalRawBytePower abi.StoragePower
TotalBytesCommitted abi.StoragePower
TotalQualityAdjPower abi.StoragePower
TotalQABytesCommitted abi.StoragePower
TotalPledgeCollateral abi.TokenAmount
ThisEpochRawBytePower abi.StoragePower
ThisEpochQualityAdjPower abi.StoragePower
ThisEpochPledgeCollateral abi.TokenAmount
ThisEpochQAPowerSmoothed smoothing.FilterEstimate
MinerCount int64
MinerAboveMinPowerCount int64
CronEventQueue cid.Cid
FirstCronEpoch abi.ChainEpoch
Claims cid.Cid
ProofValidationBatch *cid.Cid
}
```
**`TotalRawBytePower`**: The sum of all RawBytePower from all Miners meeting minimum power (ConsensusMinerMinPower)
* Invariants:
* `TotalRawBytePower >= 0`
**`TotalBytesCommitted`**: The sum of all RawBytePower from all Miners, including those that do not meet minimum power (ConsensusMinerMinPower)
* Invariants:
* `TotalBytesCommitted >= TotalRawBytePower`
**`TotalQualityAdjPower`**: The sum of all QualityAdjPower from all Miners meeting minimum power (ConsensusMinerMinPower)
* Invariants:
* `TotalQualityAdjPower >= TotalRawBytePower`
**`TotalQABytesCommitted`**: The sum of all QualityAdjPower from all Miners, including those that do not meet minimum power (ConsensusMinerMinPower)
* Invariants:
* `TotalQABytesCommitted >= TotalQualityAdjPower`
**`TotalPledgeCollateral`**: Current total amount of pledge collateral held across all Miners
* Invariants:
* `TotalPledgeCollateral >= 0`
**`ThisEpochRawBytePower`**: Total RawBytePower of consensus-eligible Miners. Set each cron tick and remains constant until the next cron tick.
* Invariants:
* `ThisEpochRawBytePower >= 0`
**`ThisEpochQualityAdjPower`**: Total QualityAdjPower of consensus-eligible Miners. Set each cron tick and remains constant until the next cron tick.
* Invariants:
* `ThisEpochQualityAdjPower >= 0`
**`ThisEpochPledgeCollateral`**: Total pledge collateral held across all Miners. Set each cron tick and remains constant until the next cron tick.
* Invariants:
* `ThisEpochPledgeCollateral >= 0`
**`ThisEpochQAPowerSmoothed`**: TODO
**`MinerCount`**: The number of Miner actors created via `CreateMiner`, minus the number deleted via `OnConsensusFault`
* Notes:
* Does not factor in ConsensusMinerMinPower
* Invariants:
* `MinerCount >= MinerAboveMinPowerCount`
**`MinerAboveMinPowerCount`**: The number of Miner Claims with a QualityAdjPower above ConsensusMinerMinPower.
* Notes:
* Miners that meet this threshold are eligible for leader election.
* Invariants:
* `MinerAboveMinPowerCount >= 0`
**`CronEventQueue`**: A collection of CronEvents that are sent to specific Miners at specific epochs.
* Notes:
* Cid type: HAMT, `map[ChainEpoch]AMT[CronEvent]`
* Maps a ChainEpoch to an array of CronEvents to process at that epoch.
* See `CronEvent` below
**`FirstCronEpoch`**: The epoch at which cron tick processing will start.
* Invariants:
* `FirstCronEpoch >= 0`
**`Claims`**: A collection of Claims denoting the StoragePower each Miner has accrued.
* Notes:
* Cid type: HAMT, `map[Address]Claim`
* Maps a Miner's address to its Power Claim
* Uses the Miner's ID address
* See `Claim` below
**`ProofValidationBatch`**: A collection of PoReps for each Miner that will be processed on the next invocation of `OnEpochTickEnd`.
* Notes:
* Cid type, HAMT, `map[Address]AMT[SealVerifyInfo]`
* Maps a Miner's address to an array of SealVerifyInfo that will be provided to `rt.Syscalls().BatchVerifySeals`
* Uses the Miner's ID address
* See `SealVerifyInfo` below
#### CronEvent
```go=
type CronEvent struct {
MinerAddr addr.Address
CallbackPayload []byte
}
```
**`MinerAddr`**: The address of the Miner whose `OnDeferredCronEvent` method will be invoked.
* Notes:
* Uses ID addresses
**`CallbackPayload`**: The parameters with which `OnDeferredCronEvent` will be invoked.
#### Claim
A Claim tracks power accrued by a Miner across all active Sectors.
```go=
type Claim struct {
SealProofType abi.RegisteredSealProof
RawBytePower abi.StoragePower
QualityAdjPower abi.StoragePower
}
```
**`SealProofType`**: The type of proof being used by the Miner
**`RawBytePower`**: Sum of RawBytePower for a Miner's Sectors
* Invariants:
* `RawBytePower >= 0`
**`QualityAdjPower`**: Sum of QualityAdjPower for a Miner's Sectors
* Invariants:
* `QualityAdjPower >= 0`
#### SealVerifyInfo
```go=
type SealVerifyInfo struct {
SealProof RegisteredSealProof
SectorID
DealIDs []DealID
Randomness SealRandomness
InteractiveRandomness
InteractiveSealRandomness
Proof []byte
SealedCID cid.Cid
UnsealedCID cid.Cid
}
```
**`SealProof`**: The proof type used by a Miner for sealing Sectors.
**`SectorID`**: The ID of the sector being proven. Combines the Miner's actor ID and the SectorNumber.
**`DealIDs`**: A slice of DealIDs stored in the sector given by `SectorID`
**`Randomness`**: Randomness included before PreCommit. Used to validate proof of replication.
**`InteractiveRandomness`**: Randomness included after PreCommit. Used to validate proof of replication.
**`Proof`**: A Proof of Replication that validates the sealing process has been performed correctly.
**`SealedCID`**: The root hash of the Sealed Sector
**`UnsealedCID`**: The root hash of the Unsealed Sector
## Exported Methods
#### 1. Constructor
```go=
func (a Actor) Constructor(rt Runtime, _ *adt.EmptyValue) *adt.EmptyValue
```
Initializes StoragePower actor state.
#### 2. CreateMiner
```go=
func (a Actor) CreateMiner(rt Runtime, params *CreateMinerParams) *CreateMinerReturn
```
Creates a new Miner actor via the Init actor.
* The new Miner's ID address is inserted into `st.Claims`, and `st.MinerCount` is incremented.
##### Parameters
```go=
type CreateMinerParams struct {
Owner addr.Address
Worker addr.Address
SealProofType abi.RegisteredSealProof
Peer abi.PeerID
Multiaddrs []abi.Multiaddrs
}
```
**`Owner`**: The new Miner's Owner address
* Requirements:
* See Miner actor Constructor for requirements.
**`Worker`**: The new Miner's Worker address
* Requirements:
* See Miner actor Constructor for requirements.
**`SealProofType`**: The proof type used for the Miner's sector commit proofs
* Requirements:
* See Miner actor Constructor for requirements.
**`Peer`**: The Libp2p identity used to connect with this Miner
* Requirements:
* See Miner actor Constructor for requirements.
**`Multiaddrs`**: Slice of Libp2p multi-addresses used to establish connections with this miner
* Requirements:
* See Miner actor Constructor for requirements.
##### Return
```go=
type CreateMinerReturn struct {
IDAddress addr.Address
RobustAddress addr.Address
}
```
**`IDAddress`**: The new Miner's ID address
**`RobustAddress`**: The new Miner's ACTOR address
##### Failure conditions
* Caller is not a Signable actor
* Init actor constructor or Miner actor constructor fails
* Init actor returns bad value, causing CBOR unmarshaling to fail
#### 3. UpdateClaimedPower
```go=
func (a Actor) UpdateClaimedPower(rt Runtime, params *UpdateClaimedPowerParams) *adt.EmptyValue
```
Invoked by a Miner whenever their claimed power changes, which may result from any of the following exported methods:
* Miner.SubmitWindowedPoSt
* Miner.ExtendSectorExpiration
* Miner.TerminateSectors
* Miner.DeclareFaults
* Miner.OnDeferredCronEvent (proving period)
* Miner.ConfirmSectorProofsValid
This method:
* Updates the calling Miner's Claim to reflect the change in power
* Updates StoragePower state to reflect the change in overall power:
* `st.TotalBytesCommitted` and `st.TotalQABytesCommitted` are adjusted directly
* `st.MinerAboveMinPowerCount` is increased by 1 if the change to Miner power puts them above `ConsensusMinMinerPower`
* `st.MinerAboveMinPowerCount` is decreased by 1 if the change to Miner power puts them below `ConsensusMinMinerPower`
* `st.RawBytePower` and `st.TotalQualityAdjPower` are adjusted depending on the Miner's power in relation to `ConsensusMinMinerPower`
##### Parameters
UpdateClaimedPowerParams contains the amount a Miner's power has changed. Both amounts may be positive or negative, signalling an increase or decrease in Miner's power, respectively.
```go=
type UpdateClaimedPowerParams struct {
RawByteDelta abi.StoragePower
QualityAdjustedDelta abi.StoragePower
}
```
**`RawByteDelta`**: The change to the Miner's RawBytePower
**`QualityAdjustedDelta`**: The change to the Miner's QualityAdjPower
##### Failure conditions
* Caller is not a Miner actor
* Miner's Claim not found in `st.Claims`
* Change to Miner's Claim results in a negative value for either field (panic)
#### 4. EnrollCronEvent
```go=
func (a Actor) EnrollCronEvent(rt Runtime, params *EnrollCronEventParams) *adt.EmptyValue
```
This method is invoked by a Miner from any of the following exported methods:
* Miner.Constructor
* Miner.TerminateSectors
* Miner.OnDeferredCronEvent
`EnrollCronEvent` allows a Miner to schedule a CronEvent with the StoragePower actor, which will be processed at some future epoch as part of StoragePower.OnEpochTickEnd.
At the specified epoch (`EventEpoch`), OnEpochTickEnd invokes Miner.OnDeferredCronEvent, supplying a `Payload` that allows the Miner to determine how to handle the CronEvent. There are a few types of `Payload` (defined in `miner_actor.go`):
* **Proving Deadline**: Miners have recurring proving deadlines. At the end of each proving deadline, a scheduled CronEvent prompts the Miner to invoke `Miner.handleProvingDeadline`.
* Among other things, this method will schedule another CronEvent for the next proving deadline.
* **Early Sector Termination**: Sectors are occasionally terminated before their expiration. In this case, the Miner processes as many early terminations as possible, and schedules additional terminations for processing at a future epoch.
If an enrolled CronEvent has an `EventEpoch` before `st.FirstCronEpoch`, `st.FirstCronEpoch` is set to `EventEpoch`.
##### Parameters
```go=
type EnrollCronEventParams struct {
EventEpoch abi.ChainEpoch
Payload []byte
}
```
**`EventEpoch`**: The epoch at which the CronEvent will be processed.
* Requirements:
* `EventEpoch >= 0`
**`Payload`**: The payload that will be supplied to Miner.OnDeferredCronEvent.
##### Failure conditions
* Caller is not a Miner actor
* `params.EventEpoch < 0`
#### 5. OnEpochTickEnd
```go=
func (a Actor) OnEpochTickEnd(rt Runtime, _ *adt.EmptyValue) *adt.EmptyValue
```
`OnEpochTickEnd` is a special method invoked by the Cron actor at the end of each tipset.
`OnEpochTickEnd` has 3 responsibilities:
* **Batch Verify PoReps**: If `st.ProofValidationBatch` contains proofs-of-replication (PoRep) submitted by Miners, these are verified in bulk via `rt.Syscalls().BatchVerifySeals`. For each Miner with successfully-proven Sectors, Miner.ConfirmSectorProofsValid is invoked and provided the successfully-proven SectorNumbers.
* After processing the PoReps in `st.ProofValidationBatch`, `st.ProofValidationBatch` is set to `nil`
* Miners that do not have valid Claims will have proof verification skipped.
* See SubmitPoRepForBulkVerify for more info.
* **Process Deferred CronEvents**: Iterates over `st.CronEventQueue` for each epoch from `st.FirstCronEpoch` to `rt.CurrEpoch()`. Each CronEvent is processed by invoking the specified Miner's OnDeferredCronEvent method.
* If a Miner's CronEvent fails, their Claim is zeroed out and deleted as a penalty.
* This method does not process deferred cron events for Miners without valid Claims (it skips them).
* Once CronEvents are processed, `st.FirstCronEpoch` is set to `rt.CurrEpoch() + 1`.
* See EnrollCronEvent for more info.
* **Update Network KPI**: As the last action taken, StoragePower updates its current epoch values for pledge collateral, quality-adjusted power, smoothed quality-adjusted power, and raw byte power. This last value, `st.ThisEpochRawBytePower`, is passed to Reward.UpdateNetworkKPI.
##### Failure conditions
* Caller is not the Cron actor
* Invocation of Reward.UpdateNetworkKPI fails
#### 6. UpdatePledgeTotal
```go=
func (a Actor) UpdatePledgeTotal(rt Runtime, pledgeDelta *abi.TokenAmount) *adt.EmptyValue
```
Each time a Miner's active Sectors change, their pledge total is updated and this method is invoked.
`pledgeDelta` may be a positive or negative value, signifying a gain or loss respectively.
##### Failure conditions
* Caller is not a Miner actor
* Caller does not have a valid claim in `st.Claims`
* Change causes `st.TotalPledgeCollateral` to be negative
#### 7. Deprecated1
This method was deprecated. See [this PR](https://github.com/filecoin-project/specs-actors/pull/1095).
#### 8. SubmitPoRepForBulkVerify
```go=
func (a Actor) SubmitPoRepForBulkVerify(rt Runtime, sealInfo *abi.SealVerifyInfo) *adt.EmptyValue
```
This method is invoked by Miner.ProveCommitSector. When ProveCommitting a Sector, a Miner submits a proof-of-replication (PoRep) to the StoragePower actor via `SubmitPoRepForBulkVerify`.
`SubmitPoRepForBulkVerify` inserts the Miner's proof in `st.ProofValidationBatch`. At the end of the same epoch, StoragePower.OnEpochTickEnd will batch-verify all submitted PoReps.
##### Failure conditions
* Caller is not a Miner actor
* Caller does not have a valid claim in `st.Claims`
* Caller has submitted `MaxMinerProveCommitsPerEpoch` (8000) already
#### 9. CurrentTotalPower
```go=
func (a Actor) CurrentTotalPower(rt Runtime, _ *adt.EmptyValue) *CurrentTotalPowerReturn
```
This method is a simple getter which returns the total power and pledge collateral recorded by the StoragePower actor during the last cron tick. This method is a simple read of these state fields:
* `st.ThisEpochRawBytePower`: Sum of RawBytePower for consensus-eligible Miners
* `st.ThisEpochQualityAdjPower`: Sum of QualityAdjPower for consensus-eligible Miners
* `st.ThisEpochPledgeCollateral`: Sum of pledge collateral across all Miners
* `st.ThisEpochQAPowerSmoothed`: TODO