Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/no block chain ops #190

Merged
merged 9 commits into from
Apr 15, 2020
71 changes: 48 additions & 23 deletions retrievalmarket/impl/clientstates/client_fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/filecoin-project/go-statemachine/fsm"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"

rm "github.com/filecoin-project/go-fil-markets/retrievalmarket"
Expand All @@ -28,26 +29,48 @@ var ClientEvents = fsm.Events{
fsm.Event(rm.ClientEventOpen).
From(rm.DealStatusNew).ToNoChange(),
fsm.Event(rm.ClientEventPaymentChannelErrored).
From(rm.DealStatusAccepted).To(rm.DealStatusFailed).
FromMany(rm.DealStatusAccepted, rm.DealStatusPaymentChannelCreating).To(rm.DealStatusFailed).
Action(func(deal *rm.ClientDealState, err error) error {
deal.Message = xerrors.Errorf("getting payment channel: %w", err).Error()
deal.Message = xerrors.Errorf("get or create payment channel: %w", err).Error()
return nil
}),
fsm.Event(rm.ClientEventAllocateLaneErrored).
From(rm.DealStatusAccepted).To(rm.DealStatusFailed).
Action(func(deal *rm.ClientDealState, err error) error {
deal.Message = xerrors.Errorf("allocating payment lane: %w", err).Error()
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.ClientEventPaymentChannelCreated).
From(rm.DealStatusAccepted).To(rm.DealStatusPaymentChannelCreated).
fsm.Event(rm.ClientEventPaymentChannelReady).
FromMany(rm.DealStatusPaymentChannelCreating, rm.DealStatusPaymentChannelAddingFunds).
To(rm.DealStatusPaymentChannelReady).
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.DealStatusFailed).
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.DealStatusFailed).
Action(func(deal *rm.ClientDealState, err error) error {
deal.Message = xerrors.Errorf("wait for add funds: %w", err).Error()
return nil
}),
fsm.Event(rm.ClientEventWriteDealProposalErrored).
FromAny().To(rm.DealStatusErrored).
Action(func(deal *rm.ClientDealState, err error) error {
Expand Down Expand Up @@ -123,50 +146,52 @@ var ClientEvents = fsm.Events{
return nil
}),
fsm.Event(rm.ClientEventConsumeBlockFailed).
FromMany(rm.DealStatusPaymentChannelCreated, rm.DealStatusOngoing).To(rm.DealStatusFailed).
FromMany(rm.DealStatusPaymentChannelReady, rm.DealStatusOngoing).To(rm.DealStatusFailed).
Action(func(deal *rm.ClientDealState, err error) error {
deal.Message = xerrors.Errorf("consuming block: %w", err).Error()
return nil
}),
fsm.Event(rm.ClientEventLastPaymentRequested).
FromMany(rm.DealStatusPaymentChannelCreated,
FromMany(rm.DealStatusPaymentChannelReady,
rm.DealStatusOngoing,
rm.DealStatusBlocksComplete).To(rm.DealStatusFundsNeededLastPayment).
Action(recordPaymentOwed),
fsm.Event(rm.ClientEventAllBlocksReceived).
FromMany(rm.DealStatusPaymentChannelCreated,
FromMany(rm.DealStatusPaymentChannelReady,
rm.DealStatusOngoing,
rm.DealStatusBlocksComplete).To(rm.DealStatusBlocksComplete).
Action(recordProcessed),
fsm.Event(rm.ClientEventComplete).
FromMany(rm.DealStatusPaymentChannelCreated,
FromMany(rm.DealStatusPaymentChannelReady,
rm.DealStatusOngoing,
rm.DealStatusBlocksComplete,
rm.DealStatusFinalizing).To(rm.DealStatusCompleted).
Action(recordProcessed),
fsm.Event(rm.ClientEventEarlyTermination).
FromMany(rm.DealStatusPaymentChannelCreated, rm.DealStatusOngoing).To(rm.DealStatusFailed).
FromMany(rm.DealStatusPaymentChannelReady, rm.DealStatusOngoing).To(rm.DealStatusFailed).
Action(func(deal *rm.ClientDealState) error {
deal.Message = "received complete status before all blocks received"
return nil
}),
fsm.Event(rm.ClientEventPaymentRequested).
FromMany(rm.DealStatusPaymentChannelCreated, rm.DealStatusOngoing).To(rm.DealStatusFundsNeeded).
FromMany(rm.DealStatusPaymentChannelReady, rm.DealStatusOngoing).To(rm.DealStatusFundsNeeded).
Action(recordPaymentOwed),
fsm.Event(rm.ClientEventBlocksReceived).
From(rm.DealStatusPaymentChannelCreated).To(rm.DealStatusOngoing).
From(rm.DealStatusPaymentChannelReady).To(rm.DealStatusOngoing).
From(rm.DealStatusOngoing).ToNoChange().
Action(recordProcessed),
}

// ClientStateEntryFuncs are the handlers for different states in a retrieval client
var ClientStateEntryFuncs = fsm.StateEntryFuncs{
rm.DealStatusNew: ProposeDeal,
rm.DealStatusAccepted: SetupPaymentChannel,
rm.DealStatusPaymentChannelCreated: ProcessNextResponse,
rm.DealStatusOngoing: ProcessNextResponse,
rm.DealStatusBlocksComplete: ProcessNextResponse,
rm.DealStatusFundsNeeded: ProcessPaymentRequested,
rm.DealStatusFundsNeededLastPayment: ProcessPaymentRequested,
rm.DealStatusFinalizing: Finalize,
rm.DealStatusNew: ProposeDeal,
rm.DealStatusAccepted: SetupPaymentChannelStart,
rm.DealStatusPaymentChannelCreating: WaitForPaymentChannelCreate,
rm.DealStatusPaymentChannelAddingFunds: WaitForPaymentChannelAddFunds,
rm.DealStatusPaymentChannelReady: ProcessNextResponse,
rm.DealStatusOngoing: ProcessNextResponse,
rm.DealStatusBlocksComplete: ProcessNextResponse,
rm.DealStatusFundsNeeded: ProcessPaymentRequested,
rm.DealStatusFundsNeededLastPayment: ProcessPaymentRequested,
rm.DealStatusFinalizing: Finalize,
}
39 changes: 35 additions & 4 deletions retrievalmarket/impl/clientstates/client_states.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package clientstates
import (
"context"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-statemachine/fsm"
"github.com/filecoin-project/specs-actors/actors/abi"
"github.com/filecoin-project/specs-actors/actors/abi/big"
Expand All @@ -18,22 +19,52 @@ type ClientDealEnvironment interface {
ConsumeBlock(context.Context, rm.DealID, rm.Block) (uint64, bool, error)
}

// SetupPaymentChannel sets up a payment channel for a deal
func SetupPaymentChannel(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error {
// SetupPaymentChannelStart initiates setting up a payment channel for a deal
func SetupPaymentChannelStart(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error {
tok, _, err := environment.Node().GetChainHead(ctx.Context())
if err != nil {
return ctx.Trigger(rm.ClientEventPaymentChannelErrored, err)
}

paych, err := environment.Node().GetOrCreatePaymentChannel(ctx.Context(), deal.ClientWallet, deal.MinerWallet, deal.TotalFunds, tok)
paych, msgCID, err := environment.Node().GetOrCreatePaymentChannel(ctx.Context(), deal.ClientWallet, deal.MinerWallet, deal.TotalFunds, tok)
if err != nil {
return ctx.Trigger(rm.ClientEventPaymentChannelErrored, err)
}

if paych == address.Undef {
return ctx.Trigger(rm.ClientEventPaymentChannelCreateInitiated, msgCID)
}

return ctx.Trigger(rm.ClientEventPaymentChannelAddingFunds, msgCID, paych)
}

// WaitForPaymentChannelCreate waits for payment channel creation to be posted on chain,
// allocates a lane for vouchers, then signals that the payment channel is ready
func WaitForPaymentChannelCreate(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error {
paych, err := environment.Node().WaitForPaymentChannelCreation(*deal.WaitMsgCID)
if err != nil {
return ctx.Trigger(rm.ClientEventPaymentChannelErrored, err)
}

lane, err := environment.Node().AllocateLane(paych)
if err != nil {
return ctx.Trigger(rm.ClientEventAllocateLaneErrored, err)
}
return ctx.Trigger(rm.ClientEventPaymentChannelCreated, paych, lane)
return ctx.Trigger(rm.ClientEventPaymentChannelReady, paych, lane)
}

// WaitForPaymentChannelAddFunds waits for funds to be added to an existing payment channel, then
// signals that payment channel is ready again
func WaitForPaymentChannelAddFunds(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error {
err := environment.Node().WaitForPaymentChannelAddFunds(*deal.WaitMsgCID)
if err != nil {
return ctx.Trigger(rm.ClientEventPaymentChannelAddFundsErrored, err)
}
lane, err := environment.Node().AllocateLane(deal.PaymentInfo.PayCh)
if err != nil {
return ctx.Trigger(rm.ClientEventAllocateLaneErrored, err)
}
return ctx.Trigger(rm.ClientEventPaymentChannelReady, deal.PaymentInfo.PayCh, lane)
}

// ProposeDeal sends the proposal to the other party
Expand Down
Loading