Skip to content

Commit

Permalink
retrieval: skip payment channel creation if total price is zero (#480)
Browse files Browse the repository at this point in the history
* feat: skip payment channel creation if total price is zero

* fix: add missing event name
  • Loading branch information
dirkmc authored Feb 1, 2021
1 parent bd2b4d4 commit 0d6c6e4
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 7 deletions.
2 changes: 2 additions & 0 deletions docs/retrievalclient.mmd
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ stateDiagram-v2
4 --> 8 : ClientEventPaymentChannelErrored
5 --> 8 : ClientEventPaymentChannelErrored
6 --> 8 : ClientEventPaymentChannelErrored
6 --> 13 : ClientEventPaymentChannelSkip
6 --> 4 : ClientEventPaymentChannelCreateInitiated
6 --> 24 : ClientEventPaymentChannelAddingFunds
22 --> 5 : ClientEventPaymentChannelAddingFunds
Expand Down Expand Up @@ -101,6 +102,7 @@ stateDiagram-v2
11 --> 13 : ClientEventPaymentSent
12 --> 19 : ClientEventPaymentSent
13 --> 21 : ClientEventComplete
18 --> 21 : ClientEventComplete
19 --> 15 : ClientEventComplete
21 --> 15 : ClientEventCompleteVerified
21 --> 17 : ClientEventEarlyTermination
Expand Down
Binary file modified docs/retrievalclient.mmd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/retrievalclient.mmd.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions retrievalmarket/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ const (
// the client that all blocks were sent for the deal, and the client is
// waiting for the last blocks to arrive
ClientEventWaitForLastBlocks

// ClientEventPaymentChannelSkip is fired when the total deal price is zero
// so there's no need to set up a payment channel
ClientEventPaymentChannelSkip
)

// ClientEvents is a human readable map of client event name -> event description
Expand Down Expand Up @@ -158,6 +162,7 @@ var ClientEvents = map[ClientEvent]string{
ClientEventRecheckFunds: "ClientEventRecheckFunds",
ClientEventCancel: "ClientEventCancel",
ClientEventWaitForLastBlocks: "ClientEventWaitForLastBlocks",
ClientEventPaymentChannelSkip: "ClientEventPaymentChannelSkip",
}

// ProviderEvent is an event that occurs in a deal lifecycle on the provider
Expand Down
9 changes: 9 additions & 0 deletions retrievalmarket/impl/clientstates/client_fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,18 @@ var ClientEvents = fsm.Events{
deal.Message = xerrors.Errorf("error from payment channel: %w", err).Error()
return nil
}),

// Price of deal is zero so skip creating a payment channel
fsm.Event(rm.ClientEventPaymentChannelSkip).
From(rm.DealStatusAccepted).To(rm.DealStatusOngoing),

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.DealStatusPaymentChannelAllocatingLane).
FromMany(rm.DealStatusCheckFunds).To(rm.DealStatusPaymentChannelAddingFunds).
Expand All @@ -98,6 +104,7 @@ var ClientEvents = fsm.Events{
}
return nil
}),

fsm.Event(rm.ClientEventPaymentChannelReady).
From(rm.DealStatusPaymentChannelCreating).To(rm.DealStatusPaymentChannelAllocatingLane).
From(rm.DealStatusPaymentChannelAddingFunds).To(rm.DealStatusOngoing).
Expand All @@ -113,6 +120,7 @@ var ClientEvents = fsm.Events{
deal.Message = ""
return nil
}),

fsm.Event(rm.ClientEventAllocateLaneErrored).
FromMany(rm.DealStatusPaymentChannelAllocatingLane).
To(rm.DealStatusFailing).
Expand Down Expand Up @@ -253,6 +261,7 @@ var ClientEvents = fsm.Events{
// completing deals
fsm.Event(rm.ClientEventComplete).
From(rm.DealStatusOngoing).To(rm.DealStatusCheckComplete).
From(rm.DealStatusBlocksComplete).To(rm.DealStatusCheckComplete).
From(rm.DealStatusFinalizing).To(rm.DealStatusCompleted),
fsm.Event(rm.ClientEventCompleteVerified).
From(rm.DealStatusCheckComplete).To(rm.DealStatusCompleted),
Expand Down
4 changes: 4 additions & 0 deletions retrievalmarket/impl/clientstates/client_states.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func ProposeDeal(ctx fsm.Context, environment ClientDealEnvironment, deal rm.Cli

// SetupPaymentChannelStart initiates setting up a payment channel for a deal
func SetupPaymentChannelStart(ctx fsm.Context, environment ClientDealEnvironment, deal rm.ClientDealState) error {
// If the total funds required for the deal are zero, skip creating the payment channel
if deal.TotalFunds.IsZero() {
return ctx.Trigger(rm.ClientEventPaymentChannelSkip)
}

tok, _, err := environment.Node().GetChainHead(ctx.Context())
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions retrievalmarket/impl/clientstates/client_states_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ func TestSetupPaymentChannel(t *testing.T) {
require.Equal(t, dealState.Status, retrievalmarket.DealStatusFailing)
})

t.Run("payment channel skip if total funds is zero", func(t *testing.T) {
envParams := testnodes.TestRetrievalClientNodeParams{}
dealState := makeDealState(retrievalmarket.DealStatusAccepted)
dealState.TotalFunds = abi.NewTokenAmount(0)
runSetupPaymentChannel(t, envParams, dealState)
assert.Empty(t, dealState.Message)
assert.Equal(t, dealState.Status, retrievalmarket.DealStatusOngoing)
})
}

func TestWaitForPaymentReady(t *testing.T) {
Expand Down
9 changes: 5 additions & 4 deletions retrievalmarket/impl/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,11 +514,12 @@ CurrentInterval: %d
} else if testCase.cancelled {
assert.Equal(t, retrievalmarket.DealStatusCancelled, clientDealState.Status)
} else {
assert.Equal(t, clientDealState.PaymentInfo.Lane, expectedVoucher.Lane)
require.NotNil(t, createdChan)
require.Equal(t, expectedTotal, createdChan.amt)
require.Equal(t, clientPaymentChannel, *newLaneAddr)
if !testCase.zeroPricePerByte {
assert.Equal(t, clientDealState.PaymentInfo.Lane, expectedVoucher.Lane)
require.NotNil(t, createdChan)
require.Equal(t, expectedTotal, createdChan.amt)
require.Equal(t, clientPaymentChannel, *newLaneAddr)

// verify that the voucher was saved/seen by the client with correct values
require.NotNil(t, createdVoucher)
tut.TestVoucherEquality(t, createdVoucher, expectedVoucher)
Expand Down

0 comments on commit 0d6c6e4

Please sign in to comment.