Skip to content

Commit

Permalink
Feat/no block chain ops (#190)
Browse files Browse the repository at this point in the history
* tests for adding funds and wait for payment channel creation, some cleanup
* allocate lane failure test, add state to from list in allocate lane errored
  • Loading branch information
shannonwells authored Apr 15, 2020
1 parent e232e40 commit 4378bd4
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 101 deletions.
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

0 comments on commit 4378bd4

Please sign in to comment.