package sealing import ( "time" "github.com/ipfs/go-cid" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin/v9/miner" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) type mutator interface { apply(state *SectorInfo) } // globalMutator is an event which can apply in every state type globalMutator interface { // applyGlobal applies the event to the state. If if returns true, // event processing should be interrupted applyGlobal(state *SectorInfo) bool } type Ignorable interface { Ignore() } // Global events type SectorRestart struct{} func (evt SectorRestart) applyGlobal(*SectorInfo) bool { return false } type SectorFatalError struct{ error } func (evt SectorFatalError) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorFatalError) applyGlobal(state *SectorInfo) bool { log.Errorf("Fatal error on sector %d: %+v", state.SectorNumber, evt.error) // TODO: Do we want to mark the state as unrecoverable? // I feel like this should be a softer error, where the user would // be able to send a retry event of some kind return true } type SectorForceState struct { State SectorState } func (evt SectorForceState) applyGlobal(state *SectorInfo) bool { state.State = evt.State return true } // Normal path type SectorStart struct { ID abi.SectorNumber SectorType abi.RegisteredSealProof } func (evt SectorStart) apply(state *SectorInfo) { state.SectorNumber = evt.ID state.SectorType = evt.SectorType } type SectorStartCC struct { ID abi.SectorNumber SectorType abi.RegisteredSealProof } func (evt SectorStartCC) apply(state *SectorInfo) { state.SectorNumber = evt.ID state.SectorType = evt.SectorType } type SectorAddPiece struct{} func (evt SectorAddPiece) apply(state *SectorInfo) { if state.CreationTime == 0 { state.CreationTime = time.Now().Unix() } } type SectorPieceAdded struct { NewPieces []SafeSectorPiece } func (evt SectorPieceAdded) apply(state *SectorInfo) { state.Pieces = append(state.Pieces, evt.NewPieces...) } type SectorAddPieceFailed struct{ error } func (evt SectorAddPieceFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorAddPieceFailed) apply(si *SectorInfo) {} type SectorRetryWaitDeals struct{} func (evt SectorRetryWaitDeals) apply(si *SectorInfo) {} type SectorStartPacking struct{} func (evt SectorStartPacking) apply(*SectorInfo) {} func (evt SectorStartPacking) Ignore() {} type SectorPacked struct{ FillerPieces []abi.PieceInfo } func (evt SectorPacked) apply(state *SectorInfo) { for idx := range evt.FillerPieces { state.Pieces = append(state.Pieces, SafeSectorPiece{ real: api.SectorPiece{ Piece: evt.FillerPieces[idx], DealInfo: nil, // filler pieces don't have deals associated with them }, }) } } type SectorTicket struct { TicketValue abi.SealRandomness TicketEpoch abi.ChainEpoch } func (evt SectorTicket) apply(state *SectorInfo) { state.TicketEpoch = evt.TicketEpoch state.TicketValue = evt.TicketValue } type SectorOldTicket struct{} func (evt SectorOldTicket) apply(*SectorInfo) {} type SectorPreCommit1 struct { PreCommit1Out storiface.PreCommit1Out } func (evt SectorPreCommit1) apply(state *SectorInfo) { state.PreCommit1Out = evt.PreCommit1Out state.PreCommit2Fails = 0 } type SectorPreCommit2 struct { Sealed cid.Cid Unsealed cid.Cid } func (evt SectorPreCommit2) apply(state *SectorInfo) { commd := evt.Unsealed state.CommD = &commd commr := evt.Sealed state.CommR = &commr } type SectorPreCommitBatch struct{} func (evt SectorPreCommitBatch) apply(*SectorInfo) {} type SectorPreCommitBatchSent struct { Message cid.Cid } func (evt SectorPreCommitBatchSent) apply(state *SectorInfo) { state.PreCommitMessage = &evt.Message } type SectorPreCommitLanded struct { TipSet types.TipSetKey } func (evt SectorPreCommitLanded) apply(si *SectorInfo) { si.PreCommitTipSet = evt.TipSet } type SectorSealPreCommit1Failed struct{ error } func (evt SectorSealPreCommit1Failed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorSealPreCommit1Failed) apply(si *SectorInfo) { si.InvalidProofs = 0 // reset counter si.PreCommit2Fails = 0 si.PreCommit1Fails++ } type SectorSealPreCommit2Failed struct{ error } func (evt SectorSealPreCommit2Failed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorSealPreCommit2Failed) apply(si *SectorInfo) { si.InvalidProofs = 0 // reset counter si.PreCommit2Fails++ } type SectorChainPreCommitFailed struct{ error } func (evt SectorChainPreCommitFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorChainPreCommitFailed) apply(*SectorInfo) {} type SectorPreCommitted struct { Message cid.Cid PreCommitDeposit big.Int PreCommitInfo miner.SectorPreCommitInfo } func (evt SectorPreCommitted) apply(state *SectorInfo) { state.PreCommitMessage = &evt.Message state.PreCommitDeposit = evt.PreCommitDeposit } type SectorSeedReady struct { SeedValue abi.InteractiveSealRandomness SeedEpoch abi.ChainEpoch } func (evt SectorSeedReady) apply(state *SectorInfo) { state.SeedEpoch = evt.SeedEpoch state.SeedValue = evt.SeedValue } type SectorRemoteCommit1Failed struct{ error } func (evt SectorRemoteCommit1Failed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorRemoteCommit1Failed) apply(*SectorInfo) {} type SectorRemoteCommit2Failed struct{ error } func (evt SectorRemoteCommit2Failed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorRemoteCommit2Failed) apply(*SectorInfo) {} type SectorComputeProofFailed struct{ error } func (evt SectorComputeProofFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorComputeProofFailed) apply(*SectorInfo) {} type SectorCommitFailed struct{ error } func (evt SectorCommitFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorCommitFailed) apply(*SectorInfo) {} type SectorRetrySubmitCommit struct{} func (evt SectorRetrySubmitCommit) apply(*SectorInfo) {} type SectorDealsExpired struct{ error } func (evt SectorDealsExpired) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorDealsExpired) apply(*SectorInfo) {} type SectorTicketExpired struct{ error } func (evt SectorTicketExpired) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorTicketExpired) apply(*SectorInfo) {} type SectorCommitted struct { Proof []byte } func (evt SectorCommitted) apply(state *SectorInfo) { state.Proof = evt.Proof } // like SectorCommitted, but finalizes before sending the proof to the chain type SectorProofReady struct { Proof []byte } func (evt SectorProofReady) apply(state *SectorInfo) { state.Proof = evt.Proof } type SectorSubmitCommitAggregate struct{} func (evt SectorSubmitCommitAggregate) apply(*SectorInfo) {} type SectorCommitSubmitted struct { Message cid.Cid } func (evt SectorCommitSubmitted) apply(state *SectorInfo) { state.CommitMessage = &evt.Message } type SectorCommitAggregateSent struct { Message cid.Cid } func (evt SectorCommitAggregateSent) apply(state *SectorInfo) { state.CommitMessage = &evt.Message } type SectorProving struct{} func (evt SectorProving) apply(*SectorInfo) {} type SectorFinalized struct{} func (evt SectorFinalized) apply(*SectorInfo) {} type SectorFinalizedAvailable struct{} func (evt SectorFinalizedAvailable) apply(*SectorInfo) {} type SectorRetryFinalize struct{} func (evt SectorRetryFinalize) apply(*SectorInfo) {} type SectorFinalizeFailed struct{ error } func (evt SectorFinalizeFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorFinalizeFailed) apply(*SectorInfo) {} // Snap deals // CC update path type SectorMarkForUpdate struct{} func (evt SectorMarkForUpdate) apply(state *SectorInfo) {} type SectorStartCCUpdate struct{} func (evt SectorStartCCUpdate) apply(state *SectorInfo) { state.CCUpdate = true // Clear filler piece but remember in case of abort state.CCPieces = state.Pieces state.Pieces = nil // Clear CreationTime in case this sector was accepting piece data previously state.CreationTime = 0 } type SectorReplicaUpdate struct { Out storiface.ReplicaUpdateOut } func (evt SectorReplicaUpdate) apply(state *SectorInfo) { state.UpdateSealed = &evt.Out.NewSealed state.UpdateUnsealed = &evt.Out.NewUnsealed } type SectorProveReplicaUpdate struct { Proof storiface.ReplicaUpdateProof } func (evt SectorProveReplicaUpdate) apply(state *SectorInfo) { state.ReplicaUpdateProof = evt.Proof } type SectorReplicaUpdateSubmitted struct { Message cid.Cid } func (evt SectorReplicaUpdateSubmitted) apply(state *SectorInfo) { state.ReplicaUpdateMessage = &evt.Message } type SectorReplicaUpdateLanded struct{} func (evt SectorReplicaUpdateLanded) apply(state *SectorInfo) {} type SectorUpdateActive struct{} func (evt SectorUpdateActive) apply(state *SectorInfo) {} type SectorKeyReleased struct{} func (evt SectorKeyReleased) apply(state *SectorInfo) {} // Failed state recovery type SectorRetrySealPreCommit1 struct{} func (evt SectorRetrySealPreCommit1) apply(state *SectorInfo) {} type SectorRetrySealPreCommit2 struct{} func (evt SectorRetrySealPreCommit2) apply(state *SectorInfo) {} type SectorRetryPreCommit struct{} func (evt SectorRetryPreCommit) apply(state *SectorInfo) {} type SectorRetryWaitSeed struct{} func (evt SectorRetryWaitSeed) apply(state *SectorInfo) {} type SectorRetryPreCommitWait struct{} func (evt SectorRetryPreCommitWait) apply(state *SectorInfo) {} type SectorRetryComputeProof struct{} func (evt SectorRetryComputeProof) apply(state *SectorInfo) { state.InvalidProofs++ } type SectorRetryInvalidProof struct{} func (evt SectorRetryInvalidProof) apply(state *SectorInfo) { state.InvalidProofs++ } type SectorRetryCommitWait struct{} func (evt SectorRetryCommitWait) apply(state *SectorInfo) {} type SectorInvalidDealIDs struct { Return ReturnState } func (evt SectorInvalidDealIDs) apply(state *SectorInfo) { state.Return = evt.Return } type SectorUpdateDealIDs struct { Updates map[int]abi.DealID } func (evt SectorUpdateDealIDs) apply(state *SectorInfo) { for i, id := range evt.Updates { // NOTE: all update deals are builtin-market deals state.Pieces[i].real.DealInfo.DealID = id } } // Snap Deals failure and recovery type SectorRetryReplicaUpdate struct{} func (evt SectorRetryReplicaUpdate) apply(state *SectorInfo) {} type SectorRetryProveReplicaUpdate struct{} func (evt SectorRetryProveReplicaUpdate) apply(state *SectorInfo) {} type SectorUpdateReplicaFailed struct{ error } func (evt SectorUpdateReplicaFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorUpdateReplicaFailed) apply(state *SectorInfo) {} type SectorProveReplicaUpdateFailed struct{ error } func (evt SectorProveReplicaUpdateFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorProveReplicaUpdateFailed) apply(state *SectorInfo) {} type SectorAbortUpgrade struct{ error } func (evt SectorAbortUpgrade) apply(state *SectorInfo) {} func (evt SectorAbortUpgrade) FormatError(xerrors.Printer) (next error) { return evt.error } type SectorRevertUpgradeToProving struct{} func (evt SectorRevertUpgradeToProving) apply(state *SectorInfo) { // cleanup sector state so that it is back in proving state.CCUpdate = false state.UpdateSealed = nil state.UpdateUnsealed = nil state.ReplicaUpdateProof = nil state.ReplicaUpdateMessage = nil state.Pieces = state.CCPieces state.CCPieces = nil state.CreationTime = 0 } type SectorRetrySubmitReplicaUpdateWait struct{} func (evt SectorRetrySubmitReplicaUpdateWait) apply(state *SectorInfo) {} type SectorRetrySubmitReplicaUpdate struct{} func (evt SectorRetrySubmitReplicaUpdate) apply(state *SectorInfo) {} type SectorSubmitReplicaUpdateFailed struct{} func (evt SectorSubmitReplicaUpdateFailed) apply(state *SectorInfo) {} type SectorDeadlineImmutable struct{} func (evt SectorDeadlineImmutable) apply(state *SectorInfo) {} type SectorDeadlineMutable struct{} func (evt SectorDeadlineMutable) apply(state *SectorInfo) {} type SectorReleaseKeyFailed struct{ error } func (evt SectorReleaseKeyFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorReleaseKeyFailed) apply(state *SectorInfo) {} // Faults type SectorFaulty struct{} func (evt SectorFaulty) apply(state *SectorInfo) {} type SectorFaultReported struct{ reportMsg cid.Cid } func (evt SectorFaultReported) apply(state *SectorInfo) { state.FaultReportMsg = &evt.reportMsg } type SectorFaultedFinal struct{} // Terminating type SectorTerminate struct{} func (evt SectorTerminate) applyGlobal(state *SectorInfo) bool { state.State = Terminating return true } type SectorTerminating struct{ Message *cid.Cid } func (evt SectorTerminating) apply(state *SectorInfo) { state.TerminateMessage = evt.Message } type SectorTerminated struct{ TerminatedAt abi.ChainEpoch } func (evt SectorTerminated) apply(state *SectorInfo) { state.TerminatedAt = evt.TerminatedAt } type SectorTerminateFailed struct{ error } func (evt SectorTerminateFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorTerminateFailed) apply(*SectorInfo) {} // External events type SectorRemove struct{} func (evt SectorRemove) applyGlobal(state *SectorInfo) bool { // because this event is global we need to send the notification here instead through an fsm callback maybeNotifyRemoteDone(false, "Removing")(state) state.State = Removing return true } type SectorRemoved struct{} func (evt SectorRemoved) apply(state *SectorInfo) {} type SectorRemoveFailed struct{ error } func (evt SectorRemoveFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorRemoveFailed) apply(*SectorInfo) {} type SectorReceive struct { State SectorInfo } func (evt SectorReceive) apply(state *SectorInfo) { *state = evt.State } type SectorReceived struct{} func (evt SectorReceived) apply(state *SectorInfo) {}