Filecoin's consensus mechanism revolves around storage power. For any given epoch, your chance of being selected as a block producer depends on your storage power, which is publically recorded on-chain. Filecoin storage miners help maintain this system by performing two crucial actions:
Most of the Miner actor's implementation is designed to support these two operations.
This section provides background information helpful for understanding the material described in Adding more storage and Proving existing storage. It is recommended to start reading those sections first, as they will link to relevant background sections where needed.
Randomness is an important attribute that helps the network verify the integrity of Miners' stored data. Filecoin's block creation process includes two types of randomness:
Each block produced in Filecoin includes values pulled from these two sources of randomness.
When Miners submit proofs about their stored data, the proofs incorporate references to randomness added at specific epochs. Assuming these values were not able to be predicted ahead of time, this helps ensure that Miners generated proofs at a specific point in time.
There are two proof types. Each uses one of the two sources of randomness:
A Sector is the fundamental unit of storage used in Filecoin storage mining. Sectors are allocations of disk space a Miner dedicates to the Filecoin network. Before a Sector can be used, the Miner must seal the Sector: encode the data in the Sector to prepare it for the proving process.
Terms:
The sealing process takes an input of data from an Unsealed Sector, and produces an encrypted replica of that data: the Sealed Sector.
Filecoin's proving processes make a few assumptions about these replicas:
According to these assumptions, if a Miner is able to prove that they have this replica data, they must be allocating a certain amount of disk space to store it.
A Proof of Replication (PoRep) is a proof that a Miner has correctly generated a replica of some underlying data.
In practice, the underlying data is the raw data contained in an Unsealed Sector, and a PoRep is a SNARK proof that the sealing process was performed correctly to produce a Sealed Sector (See Sealing a Sector).
When Miners commit to storing data, they must first produce a valid Proof of Replication.
A Proof of Spacetime (aka PoSt) is a long-term assurance of a Miner's continuous storage of their Sectors' data. This is not a single proof, but a collection of proofs the Miner has submitted over time. Periodically, a Miner must add to these proofs by submitting a Windowed PoSt:
The historical and ongoing submission of Windowed PoSts creates some assurance that the Miner has been storing, and continues to store their Sectors' underlying data (See Sealing a Sector).
Miners:
A Miner's token balance MUST cover ALL of the following:
A Miner may accrue penalties for many reasons:
When a Miner accrues penalties, the amount penalized is tracked as "Fee Debt." If a Miner has Fee Debt, they are restricted from certain actions until the amount owed is paid off. Miners with Fee Debt may not:
Background:
A Miner adds more storage in the form of Sectors. Adding more storage is a two-step process:
This two-step process provides assurance that the Miner's PoRep actually proves that the Miner has replicated the Sector data and is generating proofs from it:
For each Sector successfully ProveCommitted, the Miner becomes responsible for continuously proving the existence of their Sectors' data (see Proving existing storage. In return, the Miner is awarded storage power!
NOTE: Other documentation refers to ProveCommitted Sectors either as "active sectors," "committed sectors," or "proven sectors." This documentation will try to use "ProveCommitted Sectors" to differentiate between PreCommitted Sectors, and Windowed PoSt submission for ProveCommitted Sectors.
Miners are granted storage power in exchange for the storage space they dedicate to Filecoin. Ideally, this storage space is used to store data on behalf of Clients, but there may not always be enough Clients to utilize all the space a Miner has to offer.
In order for a Miner to maximize storage power (and profit), they should take advantage of all available storage space immediately, even before they find enough Clients to use this space.
To facilitate this, there are two types of Sectors that may be sealed and ProveCommitted:
In practice, Miners will add as much storage as they can in the form of CC Sectors, because these can be added without needing to wait for Clients. CC Sectors empower Miners to immediately make use of existing disk space: earning storage power and a higher chance at producing a block. However, CC Sectors do not grant the Miner as much power as Regular Sectors.
To incentivize Miners to hoard storage space and dedicate it to Filecoin, CC Sectors have a unique capability: they can be "upgraded" to Regular Sectors (also called "replacing a CC Sector").
Miners upgrade their ProveCommitted CC Sectors by PreCommitting a Regular Sector, and specifying that it should replace an existing CC Sector. Once the Regular Sector is successfully ProveCommitted, it will replace the existing CC Sector, boosting the Miner's storage power!
Background:
Once a Miner successfully adds and ProveCommits a Sector, the Sector is assigned to a Deadline: a specific window of time during which PoSts must be submitted. The day is broken up into 48 individual Deadlines of 30 minutes each, and ProveCommitted Sectors are assigned to one of these 48 Deadlines.
A Sectors' PoSts must be submitted on time, or that Sector is marked "faulty." There are two types of faults:
Both types of faults come with penalties, but in general, the penalties for declared faults are lower than those for undeclared faults - incentivizing Miners to declare faults whenever possible.
Faults are implied to be "temporary" - that is, a Miner that temporarily loses internet connection may choose to declare some Sectors for their upcoming Deadline as faulty, because the Miner knows they will regain the ability to submit proofs for those Sectors eventually. This declaration allows the Miner to still submit a valid proof for their Deadline (minus the faulty Sectors). This is incredibly important for Miners, as missing a Deadline's PoSt entirely incurs a high penalty. (TODO specifics)
If a Miner loses access to their Sectors entirely, they may wish to terminate the Sectors.
TODO
func (a Actor) Constructor(rt Runtime, params *ConstructorParams) *adt.EmptyValue
The Miner's Constructor has three primary functions:
func (a Actor) ControlAddresses(rt Runtime, _ *adt.EmptyValue) *GetControlAddressesReturn
Simple getter. Returns the Miner's Owner and Worker addresses, as well as an array of other control addresses authorized to submit proofs.
type GetControlAddressesReturn struct {
Owner addr.Address
Worker addr.Address
ControlAddrs []addr.Address
}
Owner
: The Miner's Owner address
Worker
: The Miner's Worker address
ControlAddrs
: Other addresses the Miner has authorized to submit PoSts, PreCommit Sectors, and manage existing Sectors.
func (a Actor) ChangeWorkerAddress(rt Runtime, params *ChangeWorkerAddressParams) *adt.EmptyValue
Allows the Miner's Owner
to queue a change to their Worker
and ControlAddrs
addresses. A change to ControlAddrs
takes effect immediately, whereas a change to Worker
will be committed after WorkerKeyChangeDelay
epochs (900). In order to implement this, ChangeWorkerAddress
enrolls a cron event with the StoragePower actor, using EventType
CronEventWorkerKeyChange
.
Until the pending change is committed, the pending Worker
address is stored in st.PendingWorkerKey
along with its effective epoch.
type ChangeWorkerAddressParams struct {
NewWorker addr.Address
NewControlAddrs []addr.Address
}
NewWorker
: The Miner's new Worker
address, which will be committed after 900 epochs.
PubkeyAddress
method returns a valid BLS addressNewControlAddrs
: The Miner's new control addresses. This always overwrites the Miner's existing control addresses, even if it is empty.
Owner
addressparams.NewWorker
could not be resolved to an ID addressparams.NewWorker
does not have an Account actor code CIDparams.NewWorker
is not a BLS address, and a Send to its PubkeyAddress
method failed to return a valid BLS address.func (a Actor) ChangePeerID(rt Runtime, params *ChangePeerIDParams) *adt.EmptyValue
Allows the Miner's Worker
address to change the Miner's PeerId
. This change goes into effect immediately.
type ChangePeerIDParams struct {
NewID abi.PeerID
}
NewID
: The new Libp2p identity used to connect to the Miner
len(NewID) <= MaxPeerIDLength
(128)Owner
, Worker
, or one of the Miner's ControlAddrs
params.NewID
is larger than MaxPeerIDLength
(128)func (a Actor) SubmitWindowedPoSt(rt Runtime, params *SubmitWindowedPoStParams) *adt.EmptyValue
Related concepts:
Summary:
Each of a Miner's ProveCommitted Sectors are assigned to a Deadline
Rough process:
Interactions with other actors:
func (a Actor) PreCommitSector(rt Runtime, params *SectorPreCommitInfo) *adt.EmptyValue
Related concepts:
Summary:
PreCommitSector
is used by a Miner in order to do ONE of the following:
Regardless of which option a Miner is using, a successful PreCommit means that the Miner must now ProveCommit the Sector, or lose a deposit.
Rough process:
SectorPreCommitInfo
st.PreCommittedSectors
) and allocate the chosen sector number (st.AllocatedSectors
)st.PreCommittedSectorsExpiry
by its quantized expiryInteractions with other actors:
func (a Actor) ProveCommitSector(rt Runtime, params *ProveCommitSectorParams) *adt.EmptyValue
Related concepts:
Summary:
ProveCommitSector
is used by a Miner to submit a PoRep for a PreCommitted Sector.
StoragePower.OnEpochTickEnd
ConfirmSectorProofsValid
with a list of all the valid proofs submitted by this Miner.Rough process:
Interactions with other actors:
func (a Actor) ExtendSectorExpiration(rt Runtime, params *ExtendSectorExpirationParams) *adt.EmptyValue
TODO
func (a Actor) TerminateSectors(rt Runtime, params *TerminateSectorsParams) *TerminateSectorsReturn
TODO
func (a Actor) DeclareFaults(rt Runtime, params *DeclareFaultsParams) *adt.EmptyValue
Related concepts:
Summary:
DeclareFaults
is used by a Miner to declare a set of Sectors as "faulty," indicating that the next PoSt for those Sectors' Deadline will not contain a proof for those Sectors' existence.
Rough process:
Interactions with other actors:
func (a Actor) DeclareFaultsRecovered(rt Runtime, params *DeclareFaultsRecoveredParams) *adt.EmptyValue
Related concepts:
Summary:
DeclareFaultsRecovered
is used by a Miner to declare a set of faulty Sectors as "recovering," indicating that the next PoSt for those Sectors' Deadline will contain a proof for those Sectors' existence.
Rough process:
func (a Actor) OnDeferredCronEvent(rt Runtime, payload *CronEventPayload) *adt.EmptyValue
CronEventProvingDeadline
Related concepts:
TODO
Summary:
TODO
Rough process:
Interactions with other actors:
CronEventProcessEarlyTerminations
TODO
func (a Actor) CheckSectorProven(rt Runtime, params *CheckSectorProvenParams) *adt.EmptyValue
Simple getter. Allows anyone to query whether a Sector was successfully proven via ProveCommitSector
. Abortf
if the Sector in question was not proven yet. Returns nil
with ExitCode 0
if the Sector has been proven.
type CheckSectorProvenParams struct {
SectorNumber abi.SectorNumber
}
SectorNumber
: The number of the Sector that should exist in st.Sectors
SectorNumber
does not exist in st.Sectors
func (a Actor) ApplyRewards(rt Runtime, params *builtin.ApplyRewardParams) *adt.EmptyValue
Related concepts:
Summary:
ApplyRewards
is used by the Reward actor to award a block reward to a Miner.
params.Reward
is expected to be sent as value by the Reward actor along with invocation, and is added to the Miner's vesting table to vest at some future epoch.params.Penalty
is added to the Miner's fee debt.Finally, the Miner also attempts to repay as much of their fee debt as possible.
Rough process:
params.Reward
must be non-negative and must be unlocked within the Minerparams.Penalty
must be non-negativeparams.Reward
to the Miner's vesting tableparams.Penalty
to the Miner's fee debtInteractions with other actors:
amountToLock
- amount vested)func (a Actor) ReportConsensusFault(rt Runtime, params *ReportConsensusFaultParams) *adt.EmptyValue
TODO
func (a Actor) WithdrawBalance(rt Runtime, params *WithdrawBalanceParams) *adt.EmptyValue
Related concepts:
Summary:
WithdrawBalance
is used by the Miner's Owner to withdraw available funds earned from block rewards (among other sources). Before withdrawing, the Miner must not have pending early-terminated Sectors, and must be able to repay any existing FeeDebt.
Rough process:
params.AmountRequested
must be non-negativeparams.AmountRequested
to the Miner's OwnerInteractions with other actors:
func (a Actor) ConfirmSectorProofsValid(rt Runtime, params *builtin.ConfirmSectorProofsParams) *adt.EmptyValue
Related concepts:
Summary:
ConfirmSectorProofsValid
marks the final step in the process of adding more storage. It is invoked in StoragePower.OnEpochTickEnd
, passing in a list of each Sector correctly ProveCommitted by this Miner over the last epoch. Once Sectors reach this step:
SubmitWindowedPoSt
Rough process:
Interactions with other actors:
func (a Actor) ChangeMultiaddrs(rt Runtime, params *ChangeMultiaddrsParams) *adt.EmptyValue
Allows the Miner's Worker
address to change the stored Multiaddrs
used to establish a connection with the Miner. Changes take effect immediately.
type ChangeMultiaddrsParams struct {
NewMultiaddrs []abi.Multiaddrs
}
NewMultiaddrs
: The updated slice of libp2p multi-addresses that can be used to establish a connection with the Miner.
NewMultiaddrs
may be emptyNewMultiaddrs
may not be over MaxMultiaddrData
(1024)Owner
, Worker
, or one of the Miner's ControlAddrs
params.NewMultiaddrs
is emptyparams.NewMultiaddrs
exceeds MaxMultiaddrData
(1024)func (a Actor) CompactPartitions(rt Runtime, params *CompactPartitionsParams) *adt.EmptyValue
TODO
func (a Actor) CompactSectorNumbers(rt Runtime, params *CompactSectorNumbersParams) *adt.EmptyValue
Used by the Miner to compact allocated Sector numbers to reduce the size of the allocated Sector number bitfield.
The input bitfield is merged with the Miner's existing st.AllocatedSectors
bitfield. If done optimally, this can drastically reduce the number of "runs" in st.AllocatedSectors
, reducing the cost needed to PreCommit a new Sector.
params.MaskSectorNumbers
references Sector numbers out of the range of abi.MaxSectorNumber
Owner
or Worker
, and is not one of the Miner's ControlAddresses
func (a Actor) ConfirmUpdateWorkerKey(rt Runtime, params *adt.EmptyValue) *adt.EmptyValue
If a worker key change was requested (via ChangeWorkerAddress
) and its effective epoch has been reached, this method allows the Miner to confirm the change without waiting for Cron to pick it up (via OnDeferredCronEvent
).
Owner
func (a Actor) RepayDebt(rt Runtime, params *adt.EmptyValue) *adt.EmptyValue
Allows the Miner (as the Owner
, Worker
, or one of the ControlAddresses
) to repay any existing fee debt.
This method repays as much fee debt as possible, and may leave the Miner with remaining fee debt after execution (assuming existing funds were insufficient).