---
# System prepended metadata

title: 'Actor Spec: StoragePower'

---

# 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