Documentation
¶
Overview ¶
Package clientstates contains state machine logic relating to the `RetrievalClient`.
client_fsm.go is where the state transitions are defined, and the default handlers for each new state are defined.
client_states.go contains state handler functions.
The following diagram illustrates the operation of the client state machine. This diagram is auto-generated from current code and should remain up to date over time:
Index ¶
- Variables
- func CancelDeal(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- func Ongoing(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- func ProcessPaymentRequested(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- func ProposeDeal(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- func SendFunds(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- func SetupPaymentChannelStart(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- func WaitForPaymentChannelAddFunds(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- func WaitForPaymentChannelCreate(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
- type ClientDealEnvironment
Constants ¶
This section is empty.
Variables ¶
var ClientEvents = fsm.Events{ fsm.Event(rm.ClientEventOpen). From(rm.DealStatusNew).ToNoChange(), fsm.Event(rm.ClientEventWriteDealProposalErrored). FromAny().To(rm.DealStatusErrored). Action(func(deal *rm.ClientDealState, err error) error { deal.Message = xerrors.Errorf("proposing deal: %w", err).Error() return nil }), fsm.Event(rm.ClientEventDealProposed). From(rm.DealStatusNew).To(rm.DealStatusWaitForAcceptance). Action(func(deal *rm.ClientDealState, channelID datatransfer.ChannelID) error { deal.ChannelID = channelID return nil }), fsm.Event(rm.ClientEventDealRejected). From(rm.DealStatusWaitForAcceptance).To(rm.DealStatusRejected). Action(func(deal *rm.ClientDealState, message string) error { deal.Message = fmt.Sprintf("deal rejected: %s", message) return nil }), fsm.Event(rm.ClientEventDealNotFound). From(rm.DealStatusWaitForAcceptance).To(rm.DealStatusDealNotFound). Action(func(deal *rm.ClientDealState, message string) error { deal.Message = fmt.Sprintf("deal not found: %s", message) return nil }), fsm.Event(rm.ClientEventDealAccepted). From(rm.DealStatusWaitForAcceptance).To(rm.DealStatusAccepted), fsm.Event(rm.ClientEventUnknownResponseReceived). FromAny().To(rm.DealStatusFailing). Action(func(deal *rm.ClientDealState, status rm.DealStatus) error { deal.Message = fmt.Sprintf("Unexpected deal response status: %s", rm.DealStatuses[status]) return nil }), fsm.Event(rm.ClientEventPaymentChannelErrored). FromMany(rm.DealStatusAccepted, rm.DealStatusPaymentChannelCreating).To(rm.DealStatusFailing). Action(func(deal *rm.ClientDealState, err error) error { deal.Message = xerrors.Errorf("get or create payment channel: %w", err).Error() return nil }), fsm.Event(rm.ClientEventPaymentChannelCreateInitiated). From(rm.DealStatusAccepted).To(rm.DealStatusPaymentChannelCreating). Action(func(deal *rm.ClientDealState, msgCID cid.Cid) error { deal.WaitMsgCID = &msgCID return nil }), fsm.Event(rm.ClientEventPaymentChannelAddingFunds). FromMany(rm.DealStatusAccepted).To(rm.DealStatusPaymentChannelAddingFunds). Action(func(deal *rm.ClientDealState, msgCID cid.Cid, payCh address.Address) error { deal.WaitMsgCID = &msgCID deal.PaymentInfo = &rm.PaymentInfo{ PayCh: payCh, } return nil }), fsm.Event(rm.ClientEventPaymentChannelReady). FromMany(rm.DealStatusPaymentChannelCreating, rm.DealStatusPaymentChannelAddingFunds). To(rm.DealStatusOngoing). Action(func(deal *rm.ClientDealState, payCh address.Address, lane uint64) error { deal.PaymentInfo = &rm.PaymentInfo{ PayCh: payCh, Lane: lane, } return nil }), fsm.Event(rm.ClientEventAllocateLaneErrored). FromMany(rm.DealStatusPaymentChannelCreating, rm.DealStatusPaymentChannelAddingFunds). To(rm.DealStatusFailing). Action(func(deal *rm.ClientDealState, err error) error { deal.Message = xerrors.Errorf("allocating payment lane: %w", err).Error() return nil }), fsm.Event(rm.ClientEventPaymentChannelAddFundsErrored). From(rm.DealStatusPaymentChannelAddingFunds).To(rm.DealStatusFailing). Action(func(deal *rm.ClientDealState, err error) error { deal.Message = xerrors.Errorf("wait for add funds: %w", err).Error() return nil }), fsm.Event(rm.ClientEventDataTransferError). FromAny().To(rm.DealStatusErrored). Action(func(deal *rm.ClientDealState, err error) error { deal.Message = fmt.Sprintf("error generated by data transfer: %s", err.Error()) return nil }), fsm.Event(rm.ClientEventLastPaymentRequested). FromMany( rm.DealStatusOngoing, rm.DealStatusFundsNeededLastPayment, rm.DealStatusFundsNeeded).To(rm.DealStatusFundsNeededLastPayment). From(rm.DealStatusBlocksComplete).To(rm.DealStatusSendFundsLastPayment). FromMany( paymentChannelCreationStates...).ToJustRecord(). Action(func(deal *rm.ClientDealState, paymentOwed abi.TokenAmount) error { deal.PaymentRequested = big.Add(deal.PaymentRequested, paymentOwed) deal.LastPaymentRequested = true return nil }), fsm.Event(rm.ClientEventPaymentRequested). FromMany( rm.DealStatusOngoing, rm.DealStatusBlocksComplete, rm.DealStatusFundsNeeded).To(rm.DealStatusFundsNeeded). FromMany( paymentChannelCreationStates...).ToJustRecord(). Action(func(deal *rm.ClientDealState, paymentOwed abi.TokenAmount) error { deal.PaymentRequested = big.Add(deal.PaymentRequested, paymentOwed) return nil }), fsm.Event(rm.ClientEventUnsealPaymentRequested). From(rm.DealStatusWaitForAcceptance).To(rm.DealStatusAccepted). Action(func(deal *rm.ClientDealState, paymentOwed abi.TokenAmount) error { deal.PaymentRequested = big.Add(deal.PaymentRequested, paymentOwed) return nil }), fsm.Event(rm.ClientEventAllBlocksReceived). FromMany( rm.DealStatusOngoing, rm.DealStatusBlocksComplete, ).To(rm.DealStatusBlocksComplete). FromMany(paymentChannelCreationStates...).ToJustRecord(). From(rm.DealStatusFundsNeededLastPayment).To(rm.DealStatusSendFundsLastPayment). Action(func(deal *rm.ClientDealState) error { deal.AllBlocksReceived = true return nil }), fsm.Event(rm.ClientEventBlocksReceived). FromMany(rm.DealStatusOngoing, rm.DealStatusFundsNeeded, rm.DealStatusFundsNeededLastPayment).ToNoChange(). FromMany(paymentChannelCreationStates...).ToJustRecord(). Action(recordReceived), fsm.Event(rm.ClientEventSendFunds). From(rm.DealStatusFundsNeeded).To(rm.DealStatusSendFunds). From(rm.DealStatusFundsNeededLastPayment).To(rm.DealStatusSendFundsLastPayment), fsm.Event(rm.ClientEventFundsExpended). FromMany(rm.DealStatusSendFunds, rm.DealStatusSendFundsLastPayment).To(rm.DealStatusFailing). Action(func(deal *rm.ClientDealState, expectedTotal string, actualTotal string) error { deal.Message = fmt.Sprintf("not enough funds left: expected amt = %s, actual amt = %s", expectedTotal, actualTotal) return nil }), fsm.Event(rm.ClientEventBadPaymentRequested). FromMany(rm.DealStatusSendFunds, rm.DealStatusSendFundsLastPayment).To(rm.DealStatusFailing). Action(func(deal *rm.ClientDealState, message string) error { deal.Message = message return nil }), fsm.Event(rm.ClientEventCreateVoucherFailed). FromMany(rm.DealStatusSendFunds, rm.DealStatusSendFundsLastPayment).To(rm.DealStatusFailing). Action(func(deal *rm.ClientDealState, err error) error { deal.Message = xerrors.Errorf("creating payment voucher: %w", err).Error() return nil }), fsm.Event(rm.ClientEventWriteDealPaymentErrored). FromAny().To(rm.DealStatusErrored). Action(func(deal *rm.ClientDealState, err error) error { deal.Message = xerrors.Errorf("writing deal payment: %w", err).Error() return nil }), fsm.Event(rm.ClientEventPaymentSent). From(rm.DealStatusSendFunds).To(rm.DealStatusOngoing). From(rm.DealStatusSendFundsLastPayment).To(rm.DealStatusFinalizing). Action(func(deal *rm.ClientDealState) error { deal.FundsSpent = big.Add(deal.FundsSpent, deal.PaymentRequested) paymentForUnsealing := big.Min(deal.PaymentRequested, big.Sub(deal.UnsealPrice, deal.UnsealFundsPaid)) bytesPaidFor := big.Div(big.Sub(deal.PaymentRequested, paymentForUnsealing), deal.PricePerByte).Uint64() if bytesPaidFor >= deal.CurrentInterval { deal.CurrentInterval += deal.DealProposal.PaymentIntervalIncrease } deal.BytesPaidFor += bytesPaidFor deal.UnsealFundsPaid = big.Add(deal.UnsealFundsPaid, paymentForUnsealing) deal.PaymentRequested = abi.NewTokenAmount(0) return nil }), fsm.Event(rm.ClientEventComplete). FromMany(rm.DealStatusFinalizing).To(rm.DealStatusCompleted), fsm.Event(rm.ClientEventCancelComplete). From(rm.DealStatusFailing).To(rm.DealStatusErrored), }
ClientEvents are the events that can happen in a retrieval client
var ClientFinalityStates = []fsm.StateKey{ rm.DealStatusErrored, rm.DealStatusCompleted, rm.DealStatusRejected, rm.DealStatusDealNotFound, }
ClientFinalityStates are terminal states after which no further events are received
var ClientStateEntryFuncs = fsm.StateEntryFuncs{ rm.DealStatusNew: ProposeDeal, rm.DealStatusAccepted: SetupPaymentChannelStart, rm.DealStatusPaymentChannelCreating: WaitForPaymentChannelCreate, rm.DealStatusPaymentChannelAddingFunds: WaitForPaymentChannelAddFunds, rm.DealStatusOngoing: Ongoing, rm.DealStatusFundsNeeded: ProcessPaymentRequested, rm.DealStatusFundsNeededLastPayment: ProcessPaymentRequested, rm.DealStatusSendFunds: SendFunds, rm.DealStatusSendFundsLastPayment: SendFunds, rm.DealStatusFailing: CancelDeal, }
ClientStateEntryFuncs are the handlers for different states in a retrieval client
Functions ¶
func CancelDeal ¶ added in v0.5.0
func CancelDeal(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
CancelDeal clears a deal that went wrong for an unknown reason
func Ongoing ¶ added in v0.5.0
func Ongoing(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
Ongoing just double checks that we may need to move out of the ongoing state cause a payment was previously requested
func ProcessPaymentRequested ¶
func ProcessPaymentRequested(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
ProcessPaymentRequested processes a request for payment from the provider
func ProposeDeal ¶
func ProposeDeal(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
ProposeDeal sends the proposal to the other party
func SendFunds ¶ added in v0.5.0
func SendFunds(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
SendFunds sends the next amount requested by the provider
func SetupPaymentChannelStart ¶
func SetupPaymentChannelStart(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
SetupPaymentChannelStart initiates setting up a payment channel for a deal
func WaitForPaymentChannelAddFunds ¶
func WaitForPaymentChannelAddFunds(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
WaitForPaymentChannelAddFunds waits for funds to be added to an existing payment channel, then signals that payment channel is ready again
func WaitForPaymentChannelCreate ¶
func WaitForPaymentChannelCreate(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error
WaitForPaymentChannelCreate waits for payment channel creation to be posted on chain,
allocates a lane for vouchers, then signals that the payment channel is ready
Types ¶
type ClientDealEnvironment ¶
type ClientDealEnvironment interface { // Node returns the node interface for this deal Node() rm.RetrievalClientNode OpenDataTransfer(ctx context.Context, to peer.ID, proposal *rm.DealProposal) (datatransfer.ChannelID, error) SendDataTransferVoucher(context.Context, datatransfer.ChannelID, *rm.DealPayment) error CloseDataTransfer(context.Context, datatransfer.ChannelID) error }
ClientDealEnvironment is a bridge to the environment a client deal is executing in. It provides access to relevant functionality on the retrieval client