providerstates

package
v1.26.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 26, 2023 License: Apache-2.0, MIT Imports: 23 Imported by: 0

Documentation

Overview

Package providerstates contains state machine logic relating to the `StorageProvider`.

provider_fsm.go is where the state transitions are defined, and the default handlers for each new state are defined.

provider_states.go contains state handler functions.

The following diagram illustrates the operation of the provider state machine. This diagram is auto-generated from current code and should remain up to date over time:

https://raw.githubusercontent.com/filecoin-project/go-fil-markets/master/docs/storageprovider.mmd.svg

Index

Constants

View Source
const DealMaxLabelSize = 256

TODO: These are copied from spec-actors master, use spec-actors exports when we update

Variables

View Source
var ProviderEvents = fsm.Events{
	fsm.Event(storagemarket.ProviderEventOpen).From(storagemarket.StorageDealUnknown).To(storagemarket.StorageDealValidating),
	fsm.Event(storagemarket.ProviderEventNodeErrored).FromAny().To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("error calling node: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealRejected).
		FromMany(storagemarket.StorageDealValidating, storagemarket.StorageDealVerifyData, storagemarket.StorageDealAcceptWait).To(storagemarket.StorageDealRejecting).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("deal rejected: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventRejectionSent).
		From(storagemarket.StorageDealRejecting).To(storagemarket.StorageDealFailing),
	fsm.Event(storagemarket.ProviderEventDealDeciding).
		From(storagemarket.StorageDealValidating).To(storagemarket.StorageDealAcceptWait),
	fsm.Event(storagemarket.ProviderEventDataRequested).
		From(storagemarket.StorageDealAcceptWait).To(storagemarket.StorageDealWaitingForData),

	fsm.Event(storagemarket.ProviderEventDataTransferFailed).
		FromMany(storagemarket.StorageDealTransferring, storagemarket.StorageDealProviderTransferAwaitRestart).
		To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("error transferring data: %w", err).Error()
			return nil
		}),

	fsm.Event(storagemarket.ProviderEventDataTransferInitiated).
		FromMany(storagemarket.StorageDealWaitingForData, storagemarket.StorageDealProviderTransferAwaitRestart).
		To(storagemarket.StorageDealTransferring).
		Action(func(deal *storagemarket.MinerDeal, channelId datatransfer.ChannelID) error {
			deal.TransferChannelId = &channelId
			return nil
		}),

	fsm.Event(storagemarket.ProviderEventDataTransferRestarted).
		FromMany(storagemarket.StorageDealWaitingForData, storagemarket.StorageDealProviderTransferAwaitRestart).
		To(storagemarket.StorageDealTransferring).
		From(storagemarket.StorageDealTransferring).ToJustRecord().
		Action(func(deal *storagemarket.MinerDeal, channelId datatransfer.ChannelID) error {
			deal.TransferChannelId = &channelId
			deal.Message = ""
			return nil
		}),

	fsm.Event(storagemarket.ProviderEventDataTransferStalled).
		FromMany(storagemarket.StorageDealTransferring, storagemarket.StorageDealProviderTransferAwaitRestart).
		ToJustRecord().
		Action(func(deal *storagemarket.MinerDeal) error {
			deal.Message = "data transfer appears to be stalled, awaiting reconnect from client"
			return nil
		}),

	fsm.Event(storagemarket.ProviderEventDataTransferCancelled).
		FromMany(
			storagemarket.StorageDealWaitingForData,
			storagemarket.StorageDealTransferring,
			storagemarket.StorageDealProviderTransferAwaitRestart,
		).
		To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal) error {
			deal.Message = "data transfer cancelled"
			return nil
		}),

	fsm.Event(storagemarket.ProviderEventDataTransferCompleted).
		FromMany(storagemarket.StorageDealTransferring, storagemarket.StorageDealProviderTransferAwaitRestart).
		To(storagemarket.StorageDealVerifyData),

	fsm.Event(storagemarket.ProviderEventDataVerificationFailed).
		From(storagemarket.StorageDealVerifyData).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error, path filestore.Path, metadataPath filestore.Path) error {
			deal.PiecePath = path
			deal.MetadataPath = metadataPath
			deal.Message = xerrors.Errorf("deal data verification failed: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventVerifiedData).
		FromMany(storagemarket.StorageDealVerifyData, storagemarket.StorageDealWaitingForData).To(storagemarket.StorageDealReserveProviderFunds).
		Action(func(deal *storagemarket.MinerDeal, path filestore.Path, metadataPath filestore.Path) error {
			deal.PiecePath = path
			deal.MetadataPath = metadataPath
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventFundingInitiated).
		From(storagemarket.StorageDealReserveProviderFunds).To(storagemarket.StorageDealProviderFunding).
		Action(func(deal *storagemarket.MinerDeal, mcid cid.Cid) error {
			deal.AddFundsCid = &mcid
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventFunded).
		FromMany(storagemarket.StorageDealProviderFunding, storagemarket.StorageDealReserveProviderFunds).To(storagemarket.StorageDealPublish),
	fsm.Event(storagemarket.ProviderEventDealPublishInitiated).
		From(storagemarket.StorageDealPublish).To(storagemarket.StorageDealPublishing).
		Action(func(deal *storagemarket.MinerDeal, finalCid cid.Cid) error {
			deal.PublishCid = &finalCid
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealPublishError).
		From(storagemarket.StorageDealPublishing).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("PublishStorageDeal error: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventSendResponseFailed).
		FromMany(storagemarket.StorageDealAcceptWait, storagemarket.StorageDealRejecting).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("sending response to deal: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealPublished).
		From(storagemarket.StorageDealPublishing).To(storagemarket.StorageDealStaged).
		Action(func(deal *storagemarket.MinerDeal, dealID abi.DealID, finalCid cid.Cid) error {
			deal.DealID = dealID
			deal.PublishCid = &finalCid
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventFileStoreErrored).
		FromMany(storagemarket.StorageDealStaged, storagemarket.StorageDealAwaitingPreCommit, storagemarket.StorageDealSealing, storagemarket.StorageDealActive).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("accessing file store: %w", err).Error()
			return nil
		}),

	fsm.Event(storagemarket.ProviderEventMultistoreErrored).
		FromMany(storagemarket.StorageDealStaged).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("operating on multistore: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealHandoffFailed).From(storagemarket.StorageDealStaged).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("handing off deal to node: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventPieceStoreErrored).
		From(storagemarket.StorageDealStaged).ToJustRecord().
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("recording piece for retrieval: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealHandedOff).
		From(storagemarket.StorageDealStaged).To(storagemarket.StorageDealAwaitingPreCommit).
		Action(func(deal *storagemarket.MinerDeal) error {
			deal.AvailableForRetrieval = true
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealPrecommitFailed).
		From(storagemarket.StorageDealAwaitingPreCommit).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("error awaiting deal pre-commit: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealPrecommitted).
		From(storagemarket.StorageDealAwaitingPreCommit).To(storagemarket.StorageDealSealing).
		Action(func(deal *storagemarket.MinerDeal, sectorNumber abi.SectorNumber) error {
			deal.SectorNumber = sectorNumber
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealActivationFailed).
		From(storagemarket.StorageDealSealing).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("error activating deal: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealActivated).
		FromMany(storagemarket.StorageDealAwaitingPreCommit, storagemarket.StorageDealSealing).
		To(storagemarket.StorageDealFinalizing),
	fsm.Event(storagemarket.ProviderEventFinalized).
		From(storagemarket.StorageDealFinalizing).To(storagemarket.StorageDealActive).
		Action(func(deal *storagemarket.MinerDeal) error {
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealSlashed).
		From(storagemarket.StorageDealActive).To(storagemarket.StorageDealSlashed).
		Action(func(deal *storagemarket.MinerDeal, slashEpoch abi.ChainEpoch) error {
			deal.SlashEpoch = slashEpoch
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventDealExpired).
		From(storagemarket.StorageDealActive).To(storagemarket.StorageDealExpired),
	fsm.Event(storagemarket.ProviderEventDealCompletionFailed).
		From(storagemarket.StorageDealActive).To(storagemarket.StorageDealError).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("error waiting for deal completion: %w", err).Error()
			return nil
		}),

	fsm.Event(storagemarket.ProviderEventFailed).From(storagemarket.StorageDealFailing).To(storagemarket.StorageDealError),

	fsm.Event(storagemarket.ProviderEventRestart).
		FromMany(storagemarket.StorageDealValidating, storagemarket.StorageDealAcceptWait, storagemarket.StorageDealRejecting).
		To(storagemarket.StorageDealError).
		From(storagemarket.StorageDealTransferring).
		To(storagemarket.StorageDealProviderTransferAwaitRestart).
		FromAny().ToNoChange(),

	fsm.Event(storagemarket.ProviderEventAwaitTransferRestartTimeout).
		From(storagemarket.StorageDealProviderTransferAwaitRestart).To(storagemarket.StorageDealFailing).
		FromAny().ToJustRecord().
		Action(func(deal *storagemarket.MinerDeal) error {
			if deal.State == storagemarket.StorageDealProviderTransferAwaitRestart {
				deal.Message = fmt.Sprintf("timed out waiting for client to restart transfer")
			}
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventTrackFundsFailed).
		From(storagemarket.StorageDealReserveProviderFunds).To(storagemarket.StorageDealFailing).
		Action(func(deal *storagemarket.MinerDeal, err error) error {
			deal.Message = xerrors.Errorf("error tracking deal funds: %w", err).Error()
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventFundsReserved).
		From(storagemarket.StorageDealReserveProviderFunds).ToJustRecord().
		Action(func(deal *storagemarket.MinerDeal, fundsReserved abi.TokenAmount) error {
			if deal.FundsReserved.Nil() {
				deal.FundsReserved = fundsReserved
			} else {
				deal.FundsReserved = big.Add(deal.FundsReserved, fundsReserved)
			}
			return nil
		}),
	fsm.Event(storagemarket.ProviderEventFundsReleased).
		FromMany(storagemarket.StorageDealPublishing, storagemarket.StorageDealFailing).ToJustRecord().
		Action(func(deal *storagemarket.MinerDeal, fundsReleased abi.TokenAmount) error {
			deal.FundsReserved = big.Subtract(deal.FundsReserved, fundsReleased)
			return nil
		}),
}

ProviderEvents are the events that can happen in a storage provider

ProviderFinalityStates are the states that terminate deal processing for a deal. When a provider restarts, it restarts only deals that are not in a finality state.

ProviderStateEntryFuncs are the handlers for different states in a storage client

StatesKnownBySealingSubsystem are the states on the happy path after hand-off to the sealing subsystem

Functions

func CleanupDeal

func CleanupDeal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

CleanupDeal clears the filestore once we know the mining component has read the data and it is in a sealed sector

func DecideOnProposal

func DecideOnProposal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

DecideOnProposal allows custom decision logic to run before accepting a deal, such as allowing a manual operator to decide whether or not to accept the deal

func FailDeal

func FailDeal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

FailDeal cleans up before terminating a deal

func HandoffDeal

func HandoffDeal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

HandoffDeal hands off a published deal for sealing and commitment in a sector

func PublishDeal

func PublishDeal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

PublishDeal sends a message to publish a deal on chain

func RejectDeal

func RejectDeal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

RejectDeal sends a failure response before terminating a deal

func ReserveProviderFunds

func ReserveProviderFunds(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

ReserveProviderFunds adds funds, as needed to the StorageMarketActor, so the miner has adequate collateral for the deal

func ValidateDealProposal

func ValidateDealProposal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

ValidateDealProposal validates a proposed deal against the provider criteria

func VerifyData

func VerifyData(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

VerifyData verifies that data received for a deal matches the pieceCID in the proposal

func VerifyDealActivated

func VerifyDealActivated(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

VerifyDealActivated verifies that a deal has been committed to a sector and activated

func VerifyDealPreCommitted

func VerifyDealPreCommitted(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

VerifyDealPreCommitted verifies that a deal has been pre-committed

func WaitForDealCompletion

func WaitForDealCompletion(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

WaitForDealCompletion waits for the deal to be slashed or to expire

func WaitForFunding

func WaitForFunding(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

WaitForFunding waits for a message posted to add funds to the StorageMarketActor to appear on chain

func WaitForPublish

func WaitForPublish(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

WaitForPublish waits for the publish message on chain and saves the deal id so it can be sent back to the client

func WaitForTransferRestart

func WaitForTransferRestart(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

WaitForTransferRestart fires a timeout after a set amount of time. If the restart hasn't started at this point, the transfer fails

Types

type ProviderDealEnvironment

type ProviderDealEnvironment interface {
	ReadCAR(path string) (*carv2.Reader, error)

	RegisterShard(ctx context.Context, pieceCid cid.Cid, path string, eagerInit bool) error
	AnnounceIndex(ctx context.Context, deal storagemarket.MinerDeal) (cid.Cid, error)
	RemoveIndex(ctx context.Context, proposalCid cid.Cid) error

	FinalizeBlockstore(proposalCid cid.Cid) error
	TerminateBlockstore(proposalCid cid.Cid, path string) error

	GeneratePieceCommitment(proposalCid cid.Cid, path string, dealSize abi.PaddedPieceSize) (cid.Cid, filestore.Path, error)

	Address() address.Address
	Node() storagemarket.StorageProviderNode
	Ask() storagemarket.StorageAsk
	SendSignedResponse(ctx context.Context, response *network.Response) error
	Disconnect(proposalCid cid.Cid) error
	FileStore() filestore.FileStore
	PieceStore() piecestore.PieceStore
	RunCustomDecisionLogic(context.Context, storagemarket.MinerDeal) (bool, string, error)
	AwaitRestartTimeout() <-chan time.Time
	network.PeerTagger
}

ProviderDealEnvironment are the dependencies needed for processing deals with a ProviderStateEntryFunc

type ProviderStateEntryFunc

type ProviderStateEntryFunc func(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error

ProviderStateEntryFunc is the signature for a StateEntryFunc in the provider FSM

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL