github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/miner_state.go (about)

     1  package miner
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"sort"
     7  
     8  	addr "github.com/filecoin-project/go-address"
     9  	"github.com/filecoin-project/go-bitfield"
    10  	"github.com/filecoin-project/go-state-types/abi"
    11  	"github.com/filecoin-project/go-state-types/big"
    12  	"github.com/filecoin-project/go-state-types/dline"
    13  	xc "github.com/filecoin-project/go-state-types/exitcode"
    14  	cid "github.com/ipfs/go-cid"
    15  	errors "github.com/pkg/errors"
    16  	xerrors "golang.org/x/xerrors"
    17  
    18  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
    19  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    20  )
    21  
    22  // Balance of Miner Actor should be greater than or equal to
    23  // the sum of PreCommitDeposits and LockedFunds.
    24  // It is possible for balance to fall below the sum of
    25  // PCD, LF and InitialPledgeRequirements, and this is a bad
    26  // state (IP Debt) that limits a miner actor's behavior (i.e. no balance withdrawals)
    27  // Excess balance as computed by st.GetAvailableBalance will be
    28  // withdrawable or usable for pre-commit deposit or pledge lock-up.
    29  type State struct {
    30  	// Information not related to sectors.
    31  	Info cid.Cid
    32  
    33  	PreCommitDeposits abi.TokenAmount // Total funds locked as PreCommitDeposits
    34  	LockedFunds       abi.TokenAmount // Total rewards and added funds locked in vesting table
    35  
    36  	VestingFunds cid.Cid // VestingFunds (Vesting Funds schedule for the miner).
    37  
    38  	FeeDebt abi.TokenAmount // Absolute value of debt this miner owes from unpaid fees
    39  
    40  	InitialPledge abi.TokenAmount // Sum of initial pledge requirements of all active sectors
    41  
    42  	// Sectors that have been pre-committed but not yet proven.
    43  	PreCommittedSectors cid.Cid // Map, HAMT[SectorNumber]SectorPreCommitOnChainInfo
    44  
    45  	// PreCommittedSectorsExpiry maintains the state required to expire PreCommittedSectors.
    46  	PreCommittedSectorsExpiry cid.Cid // BitFieldQueue (AMT[Epoch]*BitField)
    47  
    48  	// Allocated sector IDs. Sector IDs can never be reused once allocated.
    49  	AllocatedSectors cid.Cid // BitField
    50  
    51  	// Information for all proven and not-yet-garbage-collected sectors.
    52  	//
    53  	// Sectors are removed from this AMT when the partition to which the
    54  	// sector belongs is compacted.
    55  	Sectors cid.Cid // Array, AMT[SectorNumber]SectorOnChainInfo (sparse)
    56  
    57  	// DEPRECATED. This field will change names and no longer be updated every proving period in a future upgrade
    58  	// The first epoch in this miner's current proving period. This is the first epoch in which a PoSt for a
    59  	// partition at the miner's first deadline may arrive. Alternatively, it is after the last epoch at which
    60  	// a PoSt for the previous window is valid.
    61  	// Always greater than zero, this may be greater than the current epoch for genesis miners in the first
    62  	// WPoStProvingPeriod epochs of the chain; the epochs before the first proving period starts are exempt from Window
    63  	// PoSt requirements.
    64  	// Updated at the end of every period by a cron callback.
    65  	ProvingPeriodStart abi.ChainEpoch
    66  
    67  	// DEPRECATED. This field will be removed from state in a future upgrade.
    68  	// Index of the deadline within the proving period beginning at ProvingPeriodStart that has not yet been
    69  	// finalized.
    70  	// Updated at the end of each deadline window by a cron callback.
    71  	CurrentDeadline uint64
    72  
    73  	// The sector numbers due for PoSt at each deadline in the current proving period, frozen at period start.
    74  	// New sectors are added and expired ones removed at proving period boundary.
    75  	// Faults are not subtracted from this in state, but on the fly.
    76  	Deadlines cid.Cid
    77  
    78  	// Deadlines with outstanding fees for early sector termination.
    79  	EarlyTerminations bitfield.BitField
    80  
    81  	// True when miner cron is active, false otherwise
    82  	DeadlineCronActive bool
    83  }
    84  
    85  // Bitwidth of AMTs determined empirically from mutation patterns and projections of mainnet data.
    86  const PrecommitExpiryAmtBitwidth = 6
    87  const SectorsAmtBitwidth = 5
    88  
    89  type MinerInfo struct {
    90  	// Account that owns this miner.
    91  	// - Income and returned collateral are paid to this address.
    92  	// - This address is also allowed to change the worker address for the miner.
    93  	Owner addr.Address // Must be an ID-address.
    94  
    95  	// Worker account for this miner.
    96  	// The associated pubkey-type address is used to sign blocks and messages on behalf of this miner.
    97  	Worker addr.Address // Must be an ID-address.
    98  
    99  	// Additional addresses that are permitted to submit messages controlling this actor (optional).
   100  	ControlAddresses []addr.Address // Must all be ID addresses.
   101  
   102  	PendingWorkerKey *WorkerKeyChange
   103  
   104  	// Byte array representing a Libp2p identity that should be used when connecting to this miner.
   105  	PeerId abi.PeerID
   106  
   107  	// Slice of byte arrays representing Libp2p multi-addresses used for establishing a connection with this miner.
   108  	Multiaddrs []abi.Multiaddrs
   109  
   110  	// The proof type used for Window PoSt for this miner.
   111  	// A miner may commit sectors with different seal proof types (but compatible sector size and
   112  	// corresponding PoSt proof types).
   113  	WindowPoStProofType abi.RegisteredPoStProof
   114  
   115  	// Amount of space in each sector committed by this miner.
   116  	// This is computed from the proof type and represented here redundantly.
   117  	SectorSize abi.SectorSize
   118  
   119  	// The number of sectors in each Window PoSt partition (proof).
   120  	// This is computed from the proof type and represented here redundantly.
   121  	WindowPoStPartitionSectors uint64
   122  
   123  	// The next epoch this miner is eligible for certain permissioned actor methods
   124  	// and winning block elections as a result of being reported for a consensus fault.
   125  	ConsensusFaultElapsed abi.ChainEpoch
   126  
   127  	// A proposed new owner account for this miner.
   128  	// Must be confirmed by a message from the pending address itself.
   129  	PendingOwnerAddress *addr.Address
   130  }
   131  
   132  type WorkerKeyChange struct {
   133  	NewWorker   addr.Address // Must be an ID address
   134  	EffectiveAt abi.ChainEpoch
   135  }
   136  
   137  // Information provided by a miner when pre-committing a sector.
   138  type SectorPreCommitInfo struct {
   139  	SealProof       abi.RegisteredSealProof
   140  	SectorNumber    abi.SectorNumber
   141  	SealedCID       cid.Cid `checked:"true"` // CommR
   142  	SealRandEpoch   abi.ChainEpoch
   143  	DealIDs         []abi.DealID
   144  	Expiration      abi.ChainEpoch
   145  	ReplaceCapacity bool // Whether to replace a "committed capacity" no-deal sector (requires non-empty DealIDs)
   146  	// The committed capacity sector to replace, and it's deadline/partition location
   147  	ReplaceSectorDeadline  uint64
   148  	ReplaceSectorPartition uint64
   149  	ReplaceSectorNumber    abi.SectorNumber
   150  }
   151  
   152  // Information stored on-chain for a pre-committed sector.
   153  type SectorPreCommitOnChainInfo struct {
   154  	Info               SectorPreCommitInfo
   155  	PreCommitDeposit   abi.TokenAmount
   156  	PreCommitEpoch     abi.ChainEpoch
   157  	DealWeight         abi.DealWeight // Integral of active deals over sector lifetime
   158  	VerifiedDealWeight abi.DealWeight // Integral of active verified deals over sector lifetime
   159  }
   160  
   161  // Information stored on-chain for a proven sector.
   162  type SectorOnChainInfo struct {
   163  	SectorNumber          abi.SectorNumber
   164  	SealProof             abi.RegisteredSealProof // The seal proof type implies the PoSt proof/s
   165  	SealedCID             cid.Cid                 // CommR
   166  	DealIDs               []abi.DealID
   167  	Activation            abi.ChainEpoch  // Epoch during which the sector proof was accepted
   168  	Expiration            abi.ChainEpoch  // Epoch during which the sector expires
   169  	DealWeight            abi.DealWeight  // Integral of active deals over sector lifetime
   170  	VerifiedDealWeight    abi.DealWeight  // Integral of active verified deals over sector lifetime
   171  	InitialPledge         abi.TokenAmount // Pledge collected to commit this sector
   172  	ExpectedDayReward     abi.TokenAmount // Expected one day projection of reward for sector computed at activation time
   173  	ExpectedStoragePledge abi.TokenAmount // Expected twenty day projection of reward for sector computed at activation time
   174  	ReplacedSectorAge     abi.ChainEpoch  // Age of sector this sector replaced or zero
   175  	ReplacedDayReward     abi.TokenAmount // Day reward of sector this sector replace or zero
   176  }
   177  
   178  func ConstructState(store adt.Store, infoCid cid.Cid, periodStart abi.ChainEpoch, deadlineIndex uint64) (*State, error) {
   179  	emptyPrecommitMapCid, err := adt.StoreEmptyMap(store, builtin.DefaultHamtBitwidth)
   180  	if err != nil {
   181  		return nil, xerrors.Errorf("failed to construct empty map: %w", err)
   182  	}
   183  	emptyPrecommitsExpiryArrayCid, err := adt.StoreEmptyArray(store, PrecommitExpiryAmtBitwidth)
   184  	if err != nil {
   185  		return nil, xerrors.Errorf("failed to construct empty precommits array: %w", err)
   186  	}
   187  	emptySectorsArrayCid, err := adt.StoreEmptyArray(store, SectorsAmtBitwidth)
   188  	if err != nil {
   189  		return nil, xerrors.Errorf("failed to construct empty sectors array: %w", err)
   190  	}
   191  
   192  	emptyBitfield := bitfield.NewFromSet(nil)
   193  	emptyBitfieldCid, err := store.Put(store.Context(), emptyBitfield)
   194  	if err != nil {
   195  		return nil, xerrors.Errorf("failed to construct empty bitfield: %w", err)
   196  	}
   197  	emptyDeadline, err := ConstructDeadline(store)
   198  	if err != nil {
   199  		return nil, xerrors.Errorf("failed to construct empty deadline: %w", err)
   200  	}
   201  	emptyDeadlineCid, err := store.Put(store.Context(), emptyDeadline)
   202  	if err != nil {
   203  		return nil, xerrors.Errorf("failed to construct empty deadline: %w", err)
   204  	}
   205  	emptyDeadlines := ConstructDeadlines(emptyDeadlineCid)
   206  	emptyDeadlinesCid, err := store.Put(store.Context(), emptyDeadlines)
   207  	if err != nil {
   208  		return nil, xerrors.Errorf("failed to construct empty deadlines: %w", err)
   209  	}
   210  	emptyVestingFundsCid, err := store.Put(store.Context(), ConstructVestingFunds())
   211  	if err != nil {
   212  		return nil, xerrors.Errorf("failed to construct empty vesting funds: %w", err)
   213  	}
   214  
   215  	return &State{
   216  		Info: infoCid,
   217  
   218  		PreCommitDeposits: abi.NewTokenAmount(0),
   219  		LockedFunds:       abi.NewTokenAmount(0),
   220  		FeeDebt:           abi.NewTokenAmount(0),
   221  
   222  		VestingFunds: emptyVestingFundsCid,
   223  
   224  		InitialPledge: abi.NewTokenAmount(0),
   225  
   226  		PreCommittedSectors:       emptyPrecommitMapCid,
   227  		PreCommittedSectorsExpiry: emptyPrecommitsExpiryArrayCid,
   228  		AllocatedSectors:          emptyBitfieldCid,
   229  		Sectors:                   emptySectorsArrayCid,
   230  		ProvingPeriodStart:        periodStart,
   231  		CurrentDeadline:           deadlineIndex,
   232  		Deadlines:                 emptyDeadlinesCid,
   233  		EarlyTerminations:         bitfield.New(),
   234  		DeadlineCronActive:        false,
   235  	}, nil
   236  }
   237  
   238  func ConstructMinerInfo(owner, worker addr.Address, controlAddrs []addr.Address, pid []byte, multiAddrs [][]byte,
   239  	windowPoStProofType abi.RegisteredPoStProof) (*MinerInfo, error) {
   240  	sectorSize, err := windowPoStProofType.SectorSize()
   241  	if err != nil {
   242  		return nil, xc.ErrIllegalArgument.Wrapf("invalid sector size: %w", err)
   243  	}
   244  
   245  	partitionSectors, err := builtin.PoStProofWindowPoStPartitionSectors(windowPoStProofType)
   246  	if err != nil {
   247  		return nil, xc.ErrIllegalArgument.Wrapf("invalid partition sectors: %w", err)
   248  	}
   249  
   250  	return &MinerInfo{
   251  		Owner:                      owner,
   252  		Worker:                     worker,
   253  		ControlAddresses:           controlAddrs,
   254  		PendingWorkerKey:           nil,
   255  		PeerId:                     pid,
   256  		Multiaddrs:                 multiAddrs,
   257  		WindowPoStProofType:        windowPoStProofType,
   258  		SectorSize:                 sectorSize,
   259  		WindowPoStPartitionSectors: partitionSectors,
   260  		ConsensusFaultElapsed:      abi.ChainEpoch(-1),
   261  		PendingOwnerAddress:        nil,
   262  	}, nil
   263  }
   264  
   265  func (st *State) GetInfo(store adt.Store) (*MinerInfo, error) {
   266  	var info MinerInfo
   267  	if err := store.Get(store.Context(), st.Info, &info); err != nil {
   268  		return nil, xerrors.Errorf("failed to get miner info %w", err)
   269  	}
   270  	return &info, nil
   271  }
   272  
   273  func (st *State) SaveInfo(store adt.Store, info *MinerInfo) error {
   274  	c, err := store.Put(store.Context(), info)
   275  	if err != nil {
   276  		return err
   277  	}
   278  	st.Info = c
   279  	return nil
   280  }
   281  
   282  // Returns deadline calculations for the current proving period, according to the current epoch and constant state offset
   283  func (st *State) DeadlineInfo(currEpoch abi.ChainEpoch) *dline.Info {
   284  	return NewDeadlineInfoFromOffsetAndEpoch(st.ProvingPeriodStart, currEpoch)
   285  }
   286  
   287  // Returns deadline calculations for the state recorded proving period and deadline. This is out of date if the a
   288  // miner does not have an active miner cron
   289  func (st *State) RecordedDeadlineInfo(currEpoch abi.ChainEpoch) *dline.Info {
   290  	return NewDeadlineInfo(st.ProvingPeriodStart, st.CurrentDeadline, currEpoch)
   291  }
   292  
   293  // Returns current proving period start for the current epoch according to the current epoch and constant state offset
   294  func (st *State) CurrentProvingPeriodStart(currEpoch abi.ChainEpoch) abi.ChainEpoch {
   295  	dlInfo := st.DeadlineInfo(currEpoch)
   296  	return dlInfo.PeriodStart
   297  }
   298  
   299  // Returns deadline calculations for the current (according to state) proving period
   300  func (st *State) QuantSpecForDeadline(dlIdx uint64) QuantSpec {
   301  	return QuantSpecForDeadline(NewDeadlineInfo(st.ProvingPeriodStart, dlIdx, 0))
   302  }
   303  
   304  func (st *State) AllocateSectorNumber(store adt.Store, sectorNo abi.SectorNumber) error {
   305  	// This will likely already have been checked, but this is a good place
   306  	// to catch any mistakes.
   307  	if sectorNo > abi.MaxSectorNumber {
   308  		return xc.ErrIllegalArgument.Wrapf("sector number out of range: %d", sectorNo)
   309  	}
   310  
   311  	var allocatedSectors bitfield.BitField
   312  	if err := store.Get(store.Context(), st.AllocatedSectors, &allocatedSectors); err != nil {
   313  		return xc.ErrIllegalState.Wrapf("failed to load allocated sectors bitfield: %w", err)
   314  	}
   315  	if allocated, err := allocatedSectors.IsSet(uint64(sectorNo)); err != nil {
   316  		return xc.ErrIllegalState.Wrapf("failed to lookup sector number in allocated sectors bitfield: %w", err)
   317  	} else if allocated {
   318  		return xc.ErrIllegalArgument.Wrapf("sector number %d has already been allocated", sectorNo)
   319  	}
   320  	allocatedSectors.Set(uint64(sectorNo))
   321  
   322  	if root, err := store.Put(store.Context(), allocatedSectors); err != nil {
   323  		return xc.ErrIllegalArgument.Wrapf("failed to store allocated sectors bitfield after adding sector %d: %w", sectorNo, err)
   324  	} else {
   325  		st.AllocatedSectors = root
   326  	}
   327  	return nil
   328  }
   329  
   330  func (st *State) MaskSectorNumbers(store adt.Store, sectorNos bitfield.BitField) error {
   331  	lastSectorNo, err := sectorNos.Last()
   332  	if err != nil {
   333  		return xc.ErrIllegalArgument.Wrapf("invalid mask bitfield: %w", err)
   334  	}
   335  
   336  	if lastSectorNo > abi.MaxSectorNumber {
   337  		return xc.ErrIllegalArgument.Wrapf("masked sector number %d exceeded max sector number", lastSectorNo)
   338  	}
   339  
   340  	var allocatedSectors bitfield.BitField
   341  	if err := store.Get(store.Context(), st.AllocatedSectors, &allocatedSectors); err != nil {
   342  		return xc.ErrIllegalState.Wrapf("failed to load allocated sectors bitfield: %w", err)
   343  	}
   344  
   345  	allocatedSectors, err = bitfield.MergeBitFields(allocatedSectors, sectorNos)
   346  	if err != nil {
   347  		return xc.ErrIllegalState.Wrapf("failed to merge allocated bitfield with mask: %w", err)
   348  	}
   349  
   350  	if root, err := store.Put(store.Context(), allocatedSectors); err != nil {
   351  		return xc.ErrIllegalArgument.Wrapf("failed to mask allocated sectors bitfield: %w", err)
   352  	} else {
   353  		st.AllocatedSectors = root
   354  	}
   355  	return nil
   356  }
   357  
   358  // Stores a pre-committed sector info, failing if the sector number is already present.
   359  func (st *State) PutPrecommittedSector(store adt.Store, info *SectorPreCommitOnChainInfo) error {
   360  	precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth)
   361  	if err != nil {
   362  		return err
   363  	}
   364  
   365  	if modified, err := precommitted.PutIfAbsent(SectorKey(info.Info.SectorNumber), info); err != nil {
   366  		return errors.Wrapf(err, "failed to store pre-commitment for %v", info)
   367  	} else if !modified {
   368  		return xerrors.Errorf("sector %v already pre-committed", info.Info.SectorNumber)
   369  	}
   370  	st.PreCommittedSectors, err = precommitted.Root()
   371  	return err
   372  }
   373  
   374  func (st *State) GetPrecommittedSector(store adt.Store, sectorNo abi.SectorNumber) (*SectorPreCommitOnChainInfo, bool, error) {
   375  	precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth)
   376  	if err != nil {
   377  		return nil, false, err
   378  	}
   379  
   380  	var info SectorPreCommitOnChainInfo
   381  	found, err := precommitted.Get(SectorKey(sectorNo), &info)
   382  	if err != nil {
   383  		return nil, false, errors.Wrapf(err, "failed to load precommitment for %v", sectorNo)
   384  	}
   385  	return &info, found, nil
   386  }
   387  
   388  // This method gets and returns the requested pre-committed sectors, skipping
   389  // missing sectors.
   390  func (st *State) FindPrecommittedSectors(store adt.Store, sectorNos ...abi.SectorNumber) ([]*SectorPreCommitOnChainInfo, error) {
   391  	precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth)
   392  	if err != nil {
   393  		return nil, err
   394  	}
   395  
   396  	result := make([]*SectorPreCommitOnChainInfo, 0, len(sectorNos))
   397  
   398  	for _, sectorNo := range sectorNos {
   399  		var info SectorPreCommitOnChainInfo
   400  		found, err := precommitted.Get(SectorKey(sectorNo), &info)
   401  		if err != nil {
   402  			return nil, errors.Wrapf(err, "failed to load precommitment for %v", sectorNo)
   403  		}
   404  		if !found {
   405  			// TODO #564 log: "failed to get precommitted sector on sector %d, dropping from prove commit set"
   406  			continue
   407  		}
   408  		result = append(result, &info)
   409  	}
   410  
   411  	return result, nil
   412  }
   413  
   414  func (st *State) DeletePrecommittedSectors(store adt.Store, sectorNos ...abi.SectorNumber) error {
   415  	precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth)
   416  	if err != nil {
   417  		return err
   418  	}
   419  
   420  	for _, sectorNo := range sectorNos {
   421  		err = precommitted.Delete(SectorKey(sectorNo))
   422  		if err != nil {
   423  			return xerrors.Errorf("failed to delete precommitment for %v: %w", sectorNo, err)
   424  		}
   425  	}
   426  	st.PreCommittedSectors, err = precommitted.Root()
   427  	return err
   428  }
   429  
   430  func (st *State) HasSectorNo(store adt.Store, sectorNo abi.SectorNumber) (bool, error) {
   431  	sectors, err := LoadSectors(store, st.Sectors)
   432  	if err != nil {
   433  		return false, err
   434  	}
   435  
   436  	_, found, err := sectors.Get(sectorNo)
   437  	if err != nil {
   438  		return false, xerrors.Errorf("failed to get sector %v: %w", sectorNo, err)
   439  	}
   440  	return found, nil
   441  }
   442  
   443  func (st *State) PutSectors(store adt.Store, newSectors ...*SectorOnChainInfo) error {
   444  	sectors, err := LoadSectors(store, st.Sectors)
   445  	if err != nil {
   446  		return xerrors.Errorf("failed to load sectors: %w", err)
   447  	}
   448  
   449  	err = sectors.Store(newSectors...)
   450  	if err != nil {
   451  		return err
   452  	}
   453  
   454  	st.Sectors, err = sectors.Root()
   455  	if err != nil {
   456  		return xerrors.Errorf("failed to persist sectors: %w", err)
   457  	}
   458  	return nil
   459  }
   460  
   461  func (st *State) GetSector(store adt.Store, sectorNo abi.SectorNumber) (*SectorOnChainInfo, bool, error) {
   462  	sectors, err := LoadSectors(store, st.Sectors)
   463  	if err != nil {
   464  		return nil, false, err
   465  	}
   466  
   467  	return sectors.Get(sectorNo)
   468  }
   469  
   470  func (st *State) DeleteSectors(store adt.Store, sectorNos bitfield.BitField) error {
   471  	sectors, err := LoadSectors(store, st.Sectors)
   472  	if err != nil {
   473  		return err
   474  	}
   475  	err = sectorNos.ForEach(func(sectorNo uint64) error {
   476  		if err = sectors.Delete(sectorNo); err != nil {
   477  			return xerrors.Errorf("failed to delete sector %v: %w", sectorNos, err)
   478  		}
   479  		return nil
   480  	})
   481  	if err != nil {
   482  		return err
   483  	}
   484  
   485  	st.Sectors, err = sectors.Root()
   486  	return err
   487  }
   488  
   489  // Iterates sectors.
   490  // The pointer provided to the callback is not safe for re-use. Copy the pointed-to value in full to hold a reference.
   491  func (st *State) ForEachSector(store adt.Store, f func(*SectorOnChainInfo)) error {
   492  	sectors, err := LoadSectors(store, st.Sectors)
   493  	if err != nil {
   494  		return err
   495  	}
   496  	var sector SectorOnChainInfo
   497  	return sectors.ForEach(&sector, func(idx int64) error {
   498  		f(&sector)
   499  		return nil
   500  	})
   501  }
   502  
   503  func (st *State) FindSector(store adt.Store, sno abi.SectorNumber) (uint64, uint64, error) {
   504  	deadlines, err := st.LoadDeadlines(store)
   505  	if err != nil {
   506  		return 0, 0, err
   507  	}
   508  	return FindSector(store, deadlines, sno)
   509  }
   510  
   511  // Schedules each sector to expire at its next deadline end. If it can't find
   512  // any given sector, it skips it.
   513  //
   514  // This method assumes that each sector's power has not changed, despite the rescheduling.
   515  //
   516  // Note: this method is used to "upgrade" sectors, rescheduling the now-replaced
   517  // sectors to expire at the end of the next deadline. Given the expense of
   518  // sealing a sector, this function skips missing/faulty/terminated "upgraded"
   519  // sectors instead of failing. That way, the new sectors can still be proved.
   520  func (st *State) RescheduleSectorExpirations(
   521  	store adt.Store, currEpoch abi.ChainEpoch, ssize abi.SectorSize,
   522  	deadlineSectors DeadlineSectorMap,
   523  ) ([]*SectorOnChainInfo, error) {
   524  	deadlines, err := st.LoadDeadlines(store)
   525  	if err != nil {
   526  		return nil, err
   527  	}
   528  	sectors, err := LoadSectors(store, st.Sectors)
   529  	if err != nil {
   530  		return nil, err
   531  	}
   532  
   533  	var allReplaced []*SectorOnChainInfo
   534  	if err = deadlineSectors.ForEach(func(dlIdx uint64, pm PartitionSectorMap) error {
   535  		dlInfo := NewDeadlineInfo(st.CurrentProvingPeriodStart(currEpoch), dlIdx, currEpoch).NextNotElapsed()
   536  		newExpiration := dlInfo.Last()
   537  
   538  		dl, err := deadlines.LoadDeadline(store, dlIdx)
   539  		if err != nil {
   540  			return err
   541  		}
   542  
   543  		replaced, err := dl.RescheduleSectorExpirations(store, sectors, newExpiration, pm, ssize, QuantSpecForDeadline(dlInfo))
   544  		if err != nil {
   545  			return err
   546  		}
   547  		allReplaced = append(allReplaced, replaced...)
   548  
   549  		if err := deadlines.UpdateDeadline(store, dlIdx, dl); err != nil {
   550  			return err
   551  		}
   552  
   553  		return nil
   554  	}); err != nil {
   555  		return nil, err
   556  	}
   557  	return allReplaced, st.SaveDeadlines(store, deadlines)
   558  }
   559  
   560  // Assign new sectors to deadlines.
   561  func (st *State) AssignSectorsToDeadlines(
   562  	store adt.Store, currentEpoch abi.ChainEpoch, sectors []*SectorOnChainInfo, partitionSize uint64, sectorSize abi.SectorSize,
   563  ) error {
   564  	deadlines, err := st.LoadDeadlines(store)
   565  	if err != nil {
   566  		return err
   567  	}
   568  
   569  	// Sort sectors by number to get better runs in partition bitfields.
   570  	sort.Slice(sectors, func(i, j int) bool {
   571  		return sectors[i].SectorNumber < sectors[j].SectorNumber
   572  	})
   573  
   574  	var deadlineArr [WPoStPeriodDeadlines]*Deadline
   575  	if err = deadlines.ForEach(store, func(idx uint64, dl *Deadline) error {
   576  		// Skip deadlines that aren't currently mutable.
   577  		if deadlineIsMutable(st.CurrentProvingPeriodStart(currentEpoch), idx, currentEpoch) {
   578  			deadlineArr[int(idx)] = dl
   579  		}
   580  		return nil
   581  	}); err != nil {
   582  		return err
   583  	}
   584  
   585  	deadlineToSectors, err := assignDeadlines(MaxPartitionsPerDeadline, partitionSize, &deadlineArr, sectors)
   586  	if err != nil {
   587  		return xerrors.Errorf("failed to assign sectors to deadlines: %w", err)
   588  	}
   589  
   590  	for dlIdx, deadlineSectors := range deadlineToSectors {
   591  		if len(deadlineSectors) == 0 {
   592  			continue
   593  		}
   594  
   595  		quant := st.QuantSpecForDeadline(uint64(dlIdx))
   596  		dl := deadlineArr[dlIdx]
   597  
   598  		// The power returned from AddSectors is ignored because it's not activated (proven) yet.
   599  		proven := false
   600  		if _, err := dl.AddSectors(store, partitionSize, proven, deadlineSectors, sectorSize, quant); err != nil {
   601  			return err
   602  		}
   603  
   604  		if err := deadlines.UpdateDeadline(store, uint64(dlIdx), dl); err != nil {
   605  			return err
   606  		}
   607  	}
   608  
   609  	if err := st.SaveDeadlines(store, deadlines); err != nil {
   610  		return err
   611  	}
   612  	return nil
   613  }
   614  
   615  // Pops up to max early terminated sectors from all deadlines.
   616  //
   617  // Returns hasMore if we still have more early terminations to process.
   618  func (st *State) PopEarlyTerminations(store adt.Store, maxPartitions, maxSectors uint64) (result TerminationResult, hasMore bool, err error) {
   619  	stopErr := errors.New("stop error")
   620  
   621  	// Anything to do? This lets us avoid loading the deadlines if there's nothing to do.
   622  	noEarlyTerminations, err := st.EarlyTerminations.IsEmpty()
   623  	if err != nil {
   624  		return TerminationResult{}, false, xerrors.Errorf("failed to count deadlines with early terminations: %w", err)
   625  	} else if noEarlyTerminations {
   626  		return TerminationResult{}, false, nil
   627  	}
   628  
   629  	// Load deadlines
   630  	deadlines, err := st.LoadDeadlines(store)
   631  	if err != nil {
   632  		return TerminationResult{}, false, xerrors.Errorf("failed to load deadlines: %w", err)
   633  	}
   634  
   635  	// Process early terminations.
   636  	if err = st.EarlyTerminations.ForEach(func(dlIdx uint64) error {
   637  		// Load deadline + partitions.
   638  		dl, err := deadlines.LoadDeadline(store, dlIdx)
   639  		if err != nil {
   640  			return xerrors.Errorf("failed to load deadline %d: %w", dlIdx, err)
   641  		}
   642  
   643  		deadlineResult, more, err := dl.PopEarlyTerminations(store, maxPartitions-result.PartitionsProcessed, maxSectors-result.SectorsProcessed)
   644  		if err != nil {
   645  			return xerrors.Errorf("failed to pop early terminations for deadline %d: %w", dlIdx, err)
   646  		}
   647  
   648  		err = result.Add(deadlineResult)
   649  		if err != nil {
   650  			return xerrors.Errorf("failed to merge result from popping early terminations from deadline: %w", err)
   651  		}
   652  
   653  		if !more {
   654  			// safe to do while iterating.
   655  			st.EarlyTerminations.Unset(dlIdx)
   656  		}
   657  
   658  		// Save the deadline
   659  		err = deadlines.UpdateDeadline(store, dlIdx, dl)
   660  		if err != nil {
   661  			return xerrors.Errorf("failed to store deadline %d: %w", dlIdx, err)
   662  		}
   663  
   664  		if result.BelowLimit(maxPartitions, maxSectors) {
   665  			return nil
   666  		}
   667  
   668  		return stopErr
   669  	}); err != nil && err != stopErr {
   670  		return TerminationResult{}, false, xerrors.Errorf("failed to walk early terminations bitfield for deadlines: %w", err)
   671  	}
   672  
   673  	// Save back the deadlines.
   674  	err = st.SaveDeadlines(store, deadlines)
   675  	if err != nil {
   676  		return TerminationResult{}, false, xerrors.Errorf("failed to save deadlines: %w", err)
   677  	}
   678  
   679  	// Ok, check to see if we've handled all early terminations.
   680  	noEarlyTerminations, err = st.EarlyTerminations.IsEmpty()
   681  	if err != nil {
   682  		return TerminationResult{}, false, xerrors.Errorf("failed to count remaining early terminations deadlines")
   683  	}
   684  
   685  	return result, !noEarlyTerminations, nil
   686  }
   687  
   688  // Returns an error if the target sector cannot be found and/or is faulty/terminated.
   689  func (st *State) CheckSectorHealth(store adt.Store, dlIdx, pIdx uint64, sector abi.SectorNumber) error {
   690  	dls, err := st.LoadDeadlines(store)
   691  	if err != nil {
   692  		return err
   693  	}
   694  
   695  	dl, err := dls.LoadDeadline(store, dlIdx)
   696  	if err != nil {
   697  		return err
   698  	}
   699  
   700  	partition, err := dl.LoadPartition(store, pIdx)
   701  	if err != nil {
   702  		return err
   703  	}
   704  
   705  	if exists, err := partition.Sectors.IsSet(uint64(sector)); err != nil {
   706  		return xc.ErrIllegalState.Wrapf("failed to decode sectors bitfield (deadline %d, partition %d): %w", dlIdx, pIdx, err)
   707  	} else if !exists {
   708  		return xc.ErrNotFound.Wrapf("sector %d not a member of partition %d, deadline %d", sector, pIdx, dlIdx)
   709  	}
   710  
   711  	if faulty, err := partition.Faults.IsSet(uint64(sector)); err != nil {
   712  		return xc.ErrIllegalState.Wrapf("failed to decode faults bitfield (deadline %d, partition %d): %w", dlIdx, pIdx, err)
   713  	} else if faulty {
   714  		return xc.ErrForbidden.Wrapf("sector %d of partition %d, deadline %d is faulty", sector, pIdx, dlIdx)
   715  	}
   716  
   717  	if terminated, err := partition.Terminated.IsSet(uint64(sector)); err != nil {
   718  		return xc.ErrIllegalState.Wrapf("failed to decode terminated bitfield (deadline %d, partition %d): %w", dlIdx, pIdx, err)
   719  	} else if terminated {
   720  		return xc.ErrNotFound.Wrapf("sector %d of partition %d, deadline %d is terminated", sector, pIdx, dlIdx)
   721  	}
   722  
   723  	return nil
   724  }
   725  
   726  // Loads sector info for a sequence of sectors.
   727  func (st *State) LoadSectorInfos(store adt.Store, sectors bitfield.BitField) ([]*SectorOnChainInfo, error) {
   728  	sectorsArr, err := LoadSectors(store, st.Sectors)
   729  	if err != nil {
   730  		return nil, err
   731  	}
   732  	return sectorsArr.Load(sectors)
   733  }
   734  
   735  func (st *State) LoadDeadlines(store adt.Store) (*Deadlines, error) {
   736  	var deadlines Deadlines
   737  	if err := store.Get(store.Context(), st.Deadlines, &deadlines); err != nil {
   738  		return nil, xc.ErrIllegalState.Wrapf("failed to load deadlines (%s): %w", st.Deadlines, err)
   739  	}
   740  
   741  	return &deadlines, nil
   742  }
   743  
   744  func (st *State) SaveDeadlines(store adt.Store, deadlines *Deadlines) error {
   745  	c, err := store.Put(store.Context(), deadlines)
   746  	if err != nil {
   747  		return err
   748  	}
   749  	st.Deadlines = c
   750  	return nil
   751  }
   752  
   753  // LoadVestingFunds loads the vesting funds table from the store
   754  func (st *State) LoadVestingFunds(store adt.Store) (*VestingFunds, error) {
   755  	var funds VestingFunds
   756  	if err := store.Get(store.Context(), st.VestingFunds, &funds); err != nil {
   757  		return nil, xerrors.Errorf("failed to load vesting funds (%s): %w", st.VestingFunds, err)
   758  	}
   759  
   760  	return &funds, nil
   761  }
   762  
   763  // SaveVestingFunds saves the vesting table to the store
   764  func (st *State) SaveVestingFunds(store adt.Store, funds *VestingFunds) error {
   765  	c, err := store.Put(store.Context(), funds)
   766  	if err != nil {
   767  		return err
   768  	}
   769  	st.VestingFunds = c
   770  	return nil
   771  }
   772  
   773  // Return true when the miner actor needs to continue scheduling deadline crons
   774  func (st *State) ContinueDeadlineCron() bool {
   775  	return !st.PreCommitDeposits.IsZero() ||
   776  		!st.InitialPledge.IsZero() ||
   777  		!st.LockedFunds.IsZero()
   778  }
   779  
   780  //
   781  // Funds and vesting
   782  //
   783  
   784  func (st *State) AddPreCommitDeposit(amount abi.TokenAmount) error {
   785  	newTotal := big.Add(st.PreCommitDeposits, amount)
   786  	if newTotal.LessThan(big.Zero()) {
   787  		return xerrors.Errorf("negative pre-commit deposit %v after adding %v to prior %v", newTotal, amount, st.PreCommitDeposits)
   788  	}
   789  	st.PreCommitDeposits = newTotal
   790  	return nil
   791  }
   792  
   793  func (st *State) AddInitialPledge(amount abi.TokenAmount) error {
   794  	newTotal := big.Add(st.InitialPledge, amount)
   795  	if newTotal.LessThan(big.Zero()) {
   796  		return xerrors.Errorf("negative initial pledge %v after adding %v to prior %v", newTotal, amount, st.InitialPledge)
   797  	}
   798  	st.InitialPledge = newTotal
   799  	return nil
   800  }
   801  
   802  // AddLockedFunds first vests and unlocks the vested funds AND then locks the given funds in the vesting table.
   803  func (st *State) AddLockedFunds(store adt.Store, currEpoch abi.ChainEpoch, vestingSum abi.TokenAmount, spec *VestSpec) (vested abi.TokenAmount, err error) {
   804  	if vestingSum.LessThan(big.Zero()) {
   805  		return big.Zero(), xerrors.Errorf("negative amount to lock %s", vestingSum)
   806  	}
   807  
   808  	vestingFunds, err := st.LoadVestingFunds(store)
   809  	if err != nil {
   810  		return big.Zero(), xerrors.Errorf("failed to load vesting funds: %w", err)
   811  	}
   812  
   813  	// unlock vested funds first
   814  	amountUnlocked := vestingFunds.unlockVestedFunds(currEpoch)
   815  	st.LockedFunds = big.Sub(st.LockedFunds, amountUnlocked)
   816  	if st.LockedFunds.LessThan(big.Zero()) {
   817  		return big.Zero(), xerrors.Errorf("negative locked funds %v after unlocking %v", st.LockedFunds, amountUnlocked)
   818  	}
   819  
   820  	// add locked funds now
   821  	vestingFunds.addLockedFunds(currEpoch, vestingSum, st.ProvingPeriodStart, spec)
   822  	st.LockedFunds = big.Add(st.LockedFunds, vestingSum)
   823  
   824  	// save the updated vesting table state
   825  	if err := st.SaveVestingFunds(store, vestingFunds); err != nil {
   826  		return big.Zero(), xerrors.Errorf("failed to save vesting funds: %w", err)
   827  	}
   828  
   829  	return amountUnlocked, nil
   830  }
   831  
   832  // ApplyPenalty adds the provided penalty to fee debt.
   833  func (st *State) ApplyPenalty(penalty abi.TokenAmount) error {
   834  	if penalty.LessThan(big.Zero()) {
   835  		return xerrors.Errorf("applying negative penalty %v not allowed", penalty)
   836  	}
   837  	st.FeeDebt = big.Add(st.FeeDebt, penalty)
   838  	return nil
   839  }
   840  
   841  // Draws from vesting table and unlocked funds to repay up to the fee debt.
   842  // Returns the amount unlocked from the vesting table and the amount taken from
   843  // current balance. If the fee debt exceeds the total amount available for repayment
   844  // the fee debt field is updated to track the remaining debt.  Otherwise it is set to zero.
   845  func (st *State) RepayPartialDebtInPriorityOrder(store adt.Store, currEpoch abi.ChainEpoch, currBalance abi.TokenAmount) (fromVesting abi.TokenAmount, fromBalance abi.TokenAmount, err error) {
   846  	unlockedBalance, err := st.GetUnlockedBalance(currBalance)
   847  	if err != nil {
   848  		return big.Zero(), big.Zero(), err
   849  	}
   850  
   851  	// Pay fee debt with locked funds first
   852  	fromVesting, err = st.UnlockUnvestedFunds(store, currEpoch, st.FeeDebt)
   853  	if err != nil {
   854  		return abi.NewTokenAmount(0), abi.NewTokenAmount(0), err
   855  	}
   856  
   857  	// We should never unlock more than the debt we need to repay
   858  	if fromVesting.GreaterThan(st.FeeDebt) {
   859  		return big.Zero(), big.Zero(), xerrors.Errorf("unlocked more vesting funds %v than required for debt %v", fromVesting, st.FeeDebt)
   860  	}
   861  	st.FeeDebt = big.Sub(st.FeeDebt, fromVesting)
   862  
   863  	fromBalance = big.Min(unlockedBalance, st.FeeDebt)
   864  	st.FeeDebt = big.Sub(st.FeeDebt, fromBalance)
   865  
   866  	return fromVesting, fromBalance, nil
   867  
   868  }
   869  
   870  // Repays the full miner actor fee debt.  Returns the amount that must be
   871  // burnt and an error if there are not sufficient funds to cover repayment.
   872  // Miner state repays from unlocked funds and fails if unlocked funds are insufficient to cover fee debt.
   873  // FeeDebt will be zero after a successful call.
   874  func (st *State) repayDebts(currBalance abi.TokenAmount) (abi.TokenAmount, error) {
   875  	unlockedBalance, err := st.GetUnlockedBalance(currBalance)
   876  	if err != nil {
   877  		return big.Zero(), err
   878  	}
   879  	if unlockedBalance.LessThan(st.FeeDebt) {
   880  		return big.Zero(), xc.ErrInsufficientFunds.Wrapf("unlocked balance can not repay fee debt (%v < %v)", unlockedBalance, st.FeeDebt)
   881  	}
   882  	debtToRepay := st.FeeDebt
   883  	st.FeeDebt = big.Zero()
   884  	return debtToRepay, nil
   885  }
   886  
   887  // Unlocks an amount of funds that have *not yet vested*, if possible.
   888  // The soonest-vesting entries are unlocked first.
   889  // Returns the amount actually unlocked.
   890  func (st *State) UnlockUnvestedFunds(store adt.Store, currEpoch abi.ChainEpoch, target abi.TokenAmount) (abi.TokenAmount, error) {
   891  	// Nothing to unlock, don't bother loading any state.
   892  	if target.IsZero() || st.LockedFunds.IsZero() {
   893  		return big.Zero(), nil
   894  	}
   895  
   896  	vestingFunds, err := st.LoadVestingFunds(store)
   897  	if err != nil {
   898  		return big.Zero(), xerrors.Errorf("failed tp load vesting funds: %w", err)
   899  	}
   900  
   901  	amountUnlocked := vestingFunds.unlockUnvestedFunds(currEpoch, target)
   902  
   903  	st.LockedFunds = big.Sub(st.LockedFunds, amountUnlocked)
   904  	if st.LockedFunds.LessThan(big.Zero()) {
   905  		return big.Zero(), xerrors.Errorf("negative locked funds %v after unlocking %v", st.LockedFunds, amountUnlocked)
   906  	}
   907  
   908  	if err := st.SaveVestingFunds(store, vestingFunds); err != nil {
   909  		return big.Zero(), xerrors.Errorf("failed to save vesting funds: %w", err)
   910  	}
   911  
   912  	return amountUnlocked, nil
   913  }
   914  
   915  // Unlocks all vesting funds that have vested before the provided epoch.
   916  // Returns the amount unlocked.
   917  func (st *State) UnlockVestedFunds(store adt.Store, currEpoch abi.ChainEpoch) (abi.TokenAmount, error) {
   918  	// Short-circuit to avoid loading vesting funds if we don't have any.
   919  	if st.LockedFunds.IsZero() {
   920  		return big.Zero(), nil
   921  	}
   922  
   923  	vestingFunds, err := st.LoadVestingFunds(store)
   924  	if err != nil {
   925  		return big.Zero(), xerrors.Errorf("failed to load vesting funds: %w", err)
   926  	}
   927  
   928  	amountUnlocked := vestingFunds.unlockVestedFunds(currEpoch)
   929  	st.LockedFunds = big.Sub(st.LockedFunds, amountUnlocked)
   930  	if st.LockedFunds.LessThan(big.Zero()) {
   931  		return big.Zero(), xerrors.Errorf("vesting cause locked funds negative %v", st.LockedFunds)
   932  	}
   933  
   934  	err = st.SaveVestingFunds(store, vestingFunds)
   935  	if err != nil {
   936  		return big.Zero(), xerrors.Errorf("failed to save vesing funds: %w", err)
   937  	}
   938  
   939  	return amountUnlocked, nil
   940  }
   941  
   942  // CheckVestedFunds returns the amount of vested funds that have vested before the provided epoch.
   943  func (st *State) CheckVestedFunds(store adt.Store, currEpoch abi.ChainEpoch) (abi.TokenAmount, error) {
   944  	vestingFunds, err := st.LoadVestingFunds(store)
   945  	if err != nil {
   946  		return big.Zero(), xerrors.Errorf("failed to load vesting funds: %w", err)
   947  	}
   948  
   949  	amountVested := abi.NewTokenAmount(0)
   950  
   951  	for i := range vestingFunds.Funds {
   952  		vf := vestingFunds.Funds[i]
   953  		epoch := vf.Epoch
   954  		amount := vf.Amount
   955  
   956  		if epoch >= currEpoch {
   957  			break
   958  		}
   959  
   960  		amountVested = big.Add(amountVested, amount)
   961  	}
   962  
   963  	return amountVested, nil
   964  }
   965  
   966  // Unclaimed funds that are not locked -- includes free funds and does not
   967  // account for fee debt.  Always greater than or equal to zero
   968  func (st *State) GetUnlockedBalance(actorBalance abi.TokenAmount) (abi.TokenAmount, error) {
   969  	unlockedBalance := big.Subtract(actorBalance, st.LockedFunds, st.PreCommitDeposits, st.InitialPledge)
   970  	if unlockedBalance.LessThan(big.Zero()) {
   971  		return big.Zero(), xerrors.Errorf("negative unlocked balance %v", unlockedBalance)
   972  	}
   973  	return unlockedBalance, nil
   974  }
   975  
   976  // Unclaimed funds.  Actor balance - (locked funds, precommit deposit, initial pledge, fee debt)
   977  // Can go negative if the miner is in IP debt
   978  func (st *State) GetAvailableBalance(actorBalance abi.TokenAmount) (abi.TokenAmount, error) {
   979  	unlockedBalance, err := st.GetUnlockedBalance(actorBalance)
   980  	if err != nil {
   981  		return big.Zero(), err
   982  	}
   983  	return big.Subtract(unlockedBalance, st.FeeDebt), nil
   984  }
   985  
   986  func (st *State) CheckBalanceInvariants(balance abi.TokenAmount) error {
   987  	if st.PreCommitDeposits.LessThan(big.Zero()) {
   988  		return xerrors.Errorf("pre-commit deposit is negative: %v", st.PreCommitDeposits)
   989  	}
   990  	if st.LockedFunds.LessThan(big.Zero()) {
   991  		return xerrors.Errorf("locked funds is negative: %v", st.LockedFunds)
   992  	}
   993  	if st.InitialPledge.LessThan(big.Zero()) {
   994  		return xerrors.Errorf("initial pledge is negative: %v", st.InitialPledge)
   995  	}
   996  	if st.FeeDebt.LessThan(big.Zero()) {
   997  		return xerrors.Errorf("fee debt is negative: %v", st.InitialPledge)
   998  	}
   999  	minBalance := big.Sum(st.PreCommitDeposits, st.LockedFunds, st.InitialPledge)
  1000  	if balance.LessThan(minBalance) {
  1001  		return xerrors.Errorf("balance %v below required %v", balance, minBalance)
  1002  	}
  1003  	return nil
  1004  }
  1005  
  1006  func (st *State) IsDebtFree() bool {
  1007  	return st.FeeDebt.LessThanEqual(big.Zero())
  1008  }
  1009  
  1010  // pre-commit expiry
  1011  func (st *State) QuantSpecEveryDeadline() QuantSpec {
  1012  	return NewQuantSpec(WPoStChallengeWindow, st.ProvingPeriodStart)
  1013  }
  1014  
  1015  func (st *State) AddPreCommitExpiry(store adt.Store, expireEpoch abi.ChainEpoch, sectorNum abi.SectorNumber) error {
  1016  	// Load BitField Queue for sector expiry
  1017  	quant := st.QuantSpecEveryDeadline()
  1018  	queue, err := LoadBitfieldQueue(store, st.PreCommittedSectorsExpiry, quant, PrecommitExpiryAmtBitwidth)
  1019  	if err != nil {
  1020  		return xerrors.Errorf("failed to load pre-commit expiry queue: %w", err)
  1021  	}
  1022  
  1023  	// add entry for this sector to the queue
  1024  	if err := queue.AddToQueueValues(expireEpoch, uint64(sectorNum)); err != nil {
  1025  		return xerrors.Errorf("failed to add pre-commit sector expiry to queue: %w", err)
  1026  	}
  1027  
  1028  	st.PreCommittedSectorsExpiry, err = queue.Root()
  1029  	if err != nil {
  1030  		return xerrors.Errorf("failed to save pre-commit sector queue: %w", err)
  1031  	}
  1032  
  1033  	return nil
  1034  }
  1035  
  1036  func (st *State) ExpirePreCommits(store adt.Store, currEpoch abi.ChainEpoch) (depositToBurn abi.TokenAmount, err error) {
  1037  	depositToBurn = abi.NewTokenAmount(0)
  1038  
  1039  	// expire pre-committed sectors
  1040  	expiryQ, err := LoadBitfieldQueue(store, st.PreCommittedSectorsExpiry, st.QuantSpecEveryDeadline(), PrecommitExpiryAmtBitwidth)
  1041  	if err != nil {
  1042  		return depositToBurn, xerrors.Errorf("failed to load sector expiry queue: %w", err)
  1043  	}
  1044  
  1045  	sectors, modified, err := expiryQ.PopUntil(currEpoch)
  1046  	if err != nil {
  1047  		return depositToBurn, xerrors.Errorf("failed to pop expired sectors: %w", err)
  1048  	}
  1049  
  1050  	if modified {
  1051  		st.PreCommittedSectorsExpiry, err = expiryQ.Root()
  1052  		if err != nil {
  1053  			return depositToBurn, xerrors.Errorf("failed to save expiry queue: %w", err)
  1054  		}
  1055  	}
  1056  
  1057  	var precommitsToDelete []abi.SectorNumber
  1058  	if err = sectors.ForEach(func(i uint64) error {
  1059  		sectorNo := abi.SectorNumber(i)
  1060  		sector, found, err := st.GetPrecommittedSector(store, sectorNo)
  1061  		if err != nil {
  1062  			return err
  1063  		}
  1064  		if !found {
  1065  			// already committed/deleted
  1066  			return nil
  1067  		}
  1068  
  1069  		// mark it for deletion
  1070  		precommitsToDelete = append(precommitsToDelete, sectorNo)
  1071  
  1072  		// increment deposit to burn
  1073  		depositToBurn = big.Add(depositToBurn, sector.PreCommitDeposit)
  1074  		return nil
  1075  	}); err != nil {
  1076  		return big.Zero(), xerrors.Errorf("failed to check pre-commit expiries: %w", err)
  1077  	}
  1078  
  1079  	// Actually delete it.
  1080  	if len(precommitsToDelete) > 0 {
  1081  		if err := st.DeletePrecommittedSectors(store, precommitsToDelete...); err != nil {
  1082  			return big.Zero(), fmt.Errorf("failed to delete pre-commits: %w", err)
  1083  		}
  1084  	}
  1085  
  1086  	st.PreCommitDeposits = big.Sub(st.PreCommitDeposits, depositToBurn)
  1087  	if st.PreCommitDeposits.LessThan(big.Zero()) {
  1088  		return big.Zero(), xerrors.Errorf("pre-commit expiry caused negative deposits: %v", st.PreCommitDeposits)
  1089  	}
  1090  
  1091  	// This deposit was locked separately to pledge collateral so there's no pledge change here.
  1092  	return depositToBurn, nil
  1093  }
  1094  
  1095  type AdvanceDeadlineResult struct {
  1096  	PledgeDelta           abi.TokenAmount
  1097  	PowerDelta            PowerPair
  1098  	PreviouslyFaultyPower PowerPair // Power that was faulty before this advance (including recovering)
  1099  	DetectedFaultyPower   PowerPair // Power of new faults and failed recoveries
  1100  	TotalFaultyPower      PowerPair // Total faulty power after detecting faults (before expiring sectors)
  1101  	// Note that failed recovery power is included in both PreviouslyFaultyPower and DetectedFaultyPower,
  1102  	// so TotalFaultyPower is not simply their sum.
  1103  }
  1104  
  1105  // AdvanceDeadline advances the deadline. It:
  1106  // - Processes expired sectors.
  1107  // - Handles missed proofs.
  1108  // - Returns the changes to power & pledge, and faulty power (both declared and undeclared).
  1109  func (st *State) AdvanceDeadline(store adt.Store, currEpoch abi.ChainEpoch) (*AdvanceDeadlineResult, error) {
  1110  	pledgeDelta := abi.NewTokenAmount(0)
  1111  	powerDelta := NewPowerPairZero()
  1112  
  1113  	var totalFaultyPower PowerPair
  1114  	detectedFaultyPower := NewPowerPairZero()
  1115  
  1116  	// Note: Use dlInfo.Last() rather than rt.CurrEpoch unless certain
  1117  	// of the desired semantics. In the past, this method would sometimes be
  1118  	// invoked late due to skipped blocks. This is no longer the case, but
  1119  	// we still use dlInfo.Last().
  1120  	dlInfo := st.DeadlineInfo(currEpoch)
  1121  
  1122  	// Return early if the proving period hasn't started. While actors v2
  1123  	// sets the proving period start into the past so this case can never
  1124  	// happen, v1:
  1125  	//
  1126  	// 1. Sets the proving period in the future.
  1127  	// 2. Schedules the first cron event one epoch _before_ the proving
  1128  	//    period start.
  1129  	//
  1130  	// At this point, no proofs have been submitted so we can't check them.
  1131  	if !dlInfo.PeriodStarted() {
  1132  		return &AdvanceDeadlineResult{
  1133  			pledgeDelta,
  1134  			powerDelta,
  1135  			NewPowerPairZero(),
  1136  			NewPowerPairZero(),
  1137  			NewPowerPairZero(),
  1138  		}, nil
  1139  	}
  1140  
  1141  	// Advance to the next deadline (in case we short-circuit below).
  1142  	// Maintaining this state info is a legacy operation no longer required for code correctness
  1143  	st.CurrentDeadline = (dlInfo.Index + 1) % WPoStPeriodDeadlines
  1144  	if st.CurrentDeadline == 0 {
  1145  		st.ProvingPeriodStart = dlInfo.PeriodStart + WPoStProvingPeriod
  1146  	}
  1147  
  1148  	deadlines, err := st.LoadDeadlines(store)
  1149  	if err != nil {
  1150  		return nil, xerrors.Errorf("failed to load deadlines: %w", err)
  1151  	}
  1152  	deadline, err := deadlines.LoadDeadline(store, dlInfo.Index)
  1153  	if err != nil {
  1154  		return nil, xerrors.Errorf("failed to load deadline %d: %w", dlInfo.Index, err)
  1155  	}
  1156  
  1157  	previouslyFaultyPower := deadline.FaultyPower
  1158  
  1159  	// No live sectors in this deadline, nothing to do.
  1160  	if live, err := deadline.IsLive(); err != nil {
  1161  		return nil, xerrors.Errorf("failed to determine if miner is live: %w", err)
  1162  	} else if !live {
  1163  		return &AdvanceDeadlineResult{
  1164  			pledgeDelta,
  1165  			powerDelta,
  1166  			previouslyFaultyPower,
  1167  			detectedFaultyPower,
  1168  			deadline.FaultyPower,
  1169  		}, nil
  1170  	}
  1171  
  1172  	quant := QuantSpecForDeadline(dlInfo)
  1173  	{
  1174  		// Detect and penalize missing proofs.
  1175  		faultExpiration := dlInfo.Last() + FaultMaxAge
  1176  
  1177  		// detectedFaultyPower is new faults and failed recoveries
  1178  		powerDelta, detectedFaultyPower, err = deadline.ProcessDeadlineEnd(store, quant, faultExpiration)
  1179  		if err != nil {
  1180  			return nil, xerrors.Errorf("failed to process end of deadline %d: %w", dlInfo.Index, err)
  1181  		}
  1182  
  1183  		// Capture deadline's faulty power after new faults have been detected, but before it is
  1184  		// dropped along with faulty sectors expiring this round.
  1185  		totalFaultyPower = deadline.FaultyPower
  1186  	}
  1187  	{
  1188  		// Expire sectors that are due, either for on-time expiration or "early" faulty-for-too-long.
  1189  		expired, err := deadline.PopExpiredSectors(store, dlInfo.Last(), quant)
  1190  		if err != nil {
  1191  			return nil, xerrors.Errorf("failed to load expired sectors: %w", err)
  1192  		}
  1193  
  1194  		// Release pledge requirements for the sectors expiring on-time.
  1195  		// Pledge for the sectors expiring early is retained to support the termination fee that will be assessed
  1196  		// when the early termination is processed.
  1197  		pledgeDelta = big.Sub(pledgeDelta, expired.OnTimePledge)
  1198  		if err = st.AddInitialPledge(expired.OnTimePledge.Neg()); err != nil {
  1199  			return nil, xerrors.Errorf("failed to reduce %v initial pledge for expiring sectors: %w", expired.OnTimePledge, err)
  1200  		}
  1201  
  1202  		// Record reduction in power of the amount of expiring active power.
  1203  		// Faulty power has already been lost, so the amount expiring can be excluded from the delta.
  1204  		powerDelta = powerDelta.Sub(expired.ActivePower)
  1205  
  1206  		// Record deadlines with early terminations. While this
  1207  		// bitfield is non-empty, the miner is locked until they
  1208  		// pay the fee.
  1209  		noEarlyTerminations, err := expired.EarlySectors.IsEmpty()
  1210  		if err != nil {
  1211  			return nil, xerrors.Errorf("failed to count early terminations: %w", err)
  1212  		}
  1213  		if !noEarlyTerminations {
  1214  			st.EarlyTerminations.Set(dlInfo.Index)
  1215  		}
  1216  	}
  1217  
  1218  	// Save new deadline state.
  1219  	err = deadlines.UpdateDeadline(store, dlInfo.Index, deadline)
  1220  	if err != nil {
  1221  		return nil, xerrors.Errorf("failed to update deadline %d: %w", dlInfo.Index, err)
  1222  	}
  1223  
  1224  	err = st.SaveDeadlines(store, deadlines)
  1225  	if err != nil {
  1226  		return nil, xerrors.Errorf("failed to save deadlines: %w", err)
  1227  	}
  1228  
  1229  	// Compute penalties all together.
  1230  	// Be very careful when changing these as any changes can affect rounding.
  1231  	return &AdvanceDeadlineResult{
  1232  		PledgeDelta:           pledgeDelta,
  1233  		PowerDelta:            powerDelta,
  1234  		PreviouslyFaultyPower: previouslyFaultyPower,
  1235  		DetectedFaultyPower:   detectedFaultyPower,
  1236  		TotalFaultyPower:      totalFaultyPower,
  1237  	}, nil
  1238  }
  1239  
  1240  //
  1241  // Misc helpers
  1242  //
  1243  
  1244  func SectorKey(e abi.SectorNumber) abi.Keyer {
  1245  	return abi.UIntKey(uint64(e))
  1246  }
  1247  
  1248  func init() {
  1249  	// Check that ChainEpoch is indeed an unsigned integer to confirm that SectorKey is making the right interpretation.
  1250  	var e abi.SectorNumber
  1251  	if reflect.TypeOf(e).Kind() != reflect.Uint64 {
  1252  		panic("incorrect sector number encoding")
  1253  	}
  1254  }