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

     1  package miner
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/filecoin-project/go-state-types/abi"
     7  	"github.com/filecoin-project/go-state-types/dline"
     8  	"golang.org/x/xerrors"
     9  
    10  	"github.com/filecoin-project/specs-actors/v4/actors/util/adt"
    11  )
    12  
    13  // Returns deadline-related calculations for a deadline in some proving period and the current epoch.
    14  func NewDeadlineInfo(periodStart abi.ChainEpoch, deadlineIdx uint64, currEpoch abi.ChainEpoch) *dline.Info {
    15  	return dline.NewInfo(periodStart, deadlineIdx, currEpoch, WPoStPeriodDeadlines, WPoStProvingPeriod, WPoStChallengeWindow, WPoStChallengeLookback, FaultDeclarationCutoff)
    16  }
    17  
    18  func QuantSpecForDeadline(di *dline.Info) QuantSpec {
    19  	return NewQuantSpec(WPoStProvingPeriod, di.Last())
    20  }
    21  
    22  // FindSector returns the deadline and partition index for a sector number.
    23  // It returns an error if the sector number is not tracked by deadlines.
    24  func FindSector(store adt.Store, deadlines *Deadlines, sectorNum abi.SectorNumber) (uint64, uint64, error) {
    25  	for dlIdx := range deadlines.Due {
    26  		dl, err := deadlines.LoadDeadline(store, uint64(dlIdx))
    27  		if err != nil {
    28  			return 0, 0, err
    29  		}
    30  
    31  		partitions, err := adt.AsArray(store, dl.Partitions, DeadlinePartitionsAmtBitwidth)
    32  		if err != nil {
    33  			return 0, 0, err
    34  		}
    35  		var partition Partition
    36  
    37  		partIdx := uint64(0)
    38  		stopErr := errors.New("stop")
    39  		err = partitions.ForEach(&partition, func(i int64) error {
    40  			found, err := partition.Sectors.IsSet(uint64(sectorNum))
    41  			if err != nil {
    42  				return err
    43  			}
    44  			if found {
    45  				partIdx = uint64(i)
    46  				return stopErr
    47  			}
    48  			return nil
    49  		})
    50  		if err == stopErr {
    51  			return uint64(dlIdx), partIdx, nil
    52  		} else if err != nil {
    53  			return 0, 0, err
    54  		}
    55  
    56  	}
    57  	return 0, 0, xerrors.Errorf("sector %d not due at any deadline", sectorNum)
    58  }
    59  
    60  // Returns true if the deadline at the given index is currently mutable. A
    61  // "mutable" deadline may have new sectors assigned to it.
    62  func deadlineIsMutable(provingPeriodStart abi.ChainEpoch, dlIdx uint64, currentEpoch abi.ChainEpoch) bool {
    63  	// Get the next non-elapsed deadline (i.e., the next time we care about
    64  	// mutations to the deadline).
    65  	dlInfo := NewDeadlineInfo(provingPeriodStart, dlIdx, currentEpoch).NextNotElapsed()
    66  	// Ensure that the current epoch is at least one challenge window before
    67  	// that deadline opens.
    68  	return currentEpoch < dlInfo.Open-WPoStChallengeWindow
    69  }
    70  
    71  // Returns true if optimistically accepted posts submitted to the given deadline
    72  // may be disputed. Specifically, this ensures that:
    73  //
    74  // 1. Optimistic PoSts may not be disputed while the challenge window is open.
    75  // 2. Optimistic PoSts may not be disputed after the miner could have compacted the deadline.
    76  func deadlineAvailableForOptimisticPoStDispute(provingPeriodStart abi.ChainEpoch, dlIdx uint64, currentEpoch abi.ChainEpoch) bool {
    77  	if provingPeriodStart > currentEpoch {
    78  		// We haven't started proving yet, there's nothing to dispute.
    79  		return false
    80  	}
    81  	dlInfo := NewDeadlineInfo(provingPeriodStart, dlIdx, currentEpoch).NextNotElapsed()
    82  
    83  	return !dlInfo.IsOpen() && currentEpoch < (dlInfo.Close-WPoStProvingPeriod)+WPoStDisputeWindow
    84  }
    85  
    86  // Returns true if the given deadline may compacted in the current epoch.
    87  // Deadlines may not be compacted when:
    88  //
    89  // 1. The deadline is currently being challenged.
    90  // 2. The deadline is to be challenged next.
    91  // 3. Optimistically accepted posts from the deadline's last challenge window
    92  //    can currently be disputed.
    93  func deadlineAvailableForCompaction(provingPeriodStart abi.ChainEpoch, dlIdx uint64, currentEpoch abi.ChainEpoch) bool {
    94  	return deadlineIsMutable(provingPeriodStart, dlIdx, currentEpoch) &&
    95  		!deadlineAvailableForOptimisticPoStDispute(provingPeriodStart, dlIdx, currentEpoch)
    96  }
    97  
    98  // Determine current period start and deadline index directly from current epoch and
    99  // the offset implied by the proving period. This works correctly even for the state
   100  // of a miner actor without an active deadline cron
   101  func NewDeadlineInfoFromOffsetAndEpoch(periodStartSeed abi.ChainEpoch, currEpoch abi.ChainEpoch) *dline.Info {
   102  	q := NewQuantSpec(WPoStProvingPeriod, periodStartSeed)
   103  	currentPeriodStart := q.QuantizeDown(currEpoch)
   104  	currentDeadlineIdx := uint64((currEpoch-currentPeriodStart)/WPoStChallengeWindow) % WPoStPeriodDeadlines
   105  	return NewDeadlineInfo(currentPeriodStart, currentDeadlineIdx, currEpoch)
   106  }