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 }