lotus/paychmgr/paychget_test.go

1745 lines
53 KiB
Go
Raw Normal View History

2022-08-29 14:25:30 +00:00
// stm: #unit
2020-07-28 23:16:47 +00:00
package paychmgr
import (
"context"
"sync"
"testing"
"time"
2020-07-28 23:16:47 +00:00
"github.com/ipfs/go-cid"
ds "github.com/ipfs/go-datastore"
ds_sync "github.com/ipfs/go-datastore/sync"
"github.com/stretchr/testify/require"
2020-07-28 23:16:47 +00:00
"github.com/filecoin-project/go-address"
2022-06-14 15:00:51 +00:00
cborrpc "github.com/filecoin-project/go-cbor-util"
"github.com/filecoin-project/go-state-types/abi"
2020-09-07 03:49:10 +00:00
"github.com/filecoin-project/go-state-types/big"
2020-09-30 17:04:10 +00:00
"github.com/filecoin-project/specs-actors/v2/actors/builtin"
2020-10-05 20:27:34 +00:00
init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init"
2020-09-30 17:04:10 +00:00
tutils "github.com/filecoin-project/specs-actors/v2/support/testing"
2020-07-28 23:16:47 +00:00
2020-09-23 06:18:52 +00:00
lotusinit "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
paychmock "github.com/filecoin-project/lotus/chain/actors/builtin/paych/mock"
"github.com/filecoin-project/lotus/chain/types"
2020-07-28 23:16:47 +00:00
)
2022-02-14 19:16:30 +00:00
var onChainReserve = GetOpts{
2022-01-06 15:04:39 +00:00
Reserve: true,
OffChain: false,
}
2022-02-14 19:16:30 +00:00
var onChainNoReserve = GetOpts{
2022-01-06 15:04:39 +00:00
Reserve: false,
OffChain: false,
}
2022-02-14 19:16:30 +00:00
var offChainReserve = GetOpts{
2022-01-06 15:04:39 +00:00
Reserve: true,
OffChain: true,
}
2022-02-14 19:16:30 +00:00
var offChainNoReserve = GetOpts{
2022-01-06 15:04:39 +00:00
Reserve: false,
OffChain: true,
}
2020-07-28 23:16:47 +00:00
func testChannelResponse(t *testing.T, ch address.Address) types.MessageReceipt {
2020-10-05 20:27:34 +00:00
createChannelRet := init2.ExecReturn{
2020-07-28 23:16:47 +00:00
IDAddress: ch,
RobustAddress: ch,
}
createChannelRetBytes, err := cborrpc.Dump(&createChannelRet)
require.NoError(t, err)
createChannelResponse := types.MessageReceipt{
ExitCode: 0,
Return: createChannelRetBytes,
}
return createChannelResponse
}
// TestPaychGetCreateChannelMsg tests that GetPaych sends a message to create
// a new channel with the correct funds
func TestPaychGetCreateChannelMsg(t *testing.T) {
feat: Add additional test annotations (#8272) * Annotate api,proxy_util,blockstore_badger, policy tests * Annotate splitstore: bsbadger / markset * Annotate splitstore feature * Annotate union/timed blockstore tests * Annotate openrpc, diff_adt tests * Annotate error,drand,events tests * Annotate predicates_test * Fix annotations * Annotate tscache, gen tests * Annotate fundmanager test * Annotate repub and selection tests * Annotate statetree_test * Annotate forks_test * Annotate searchwait_test.go * Fix duplicated @@ symbols * Annotate chain stmgr/store tests * Annotate more (types) tests * More tests annotated * Annotate conformance chaos actor tests * Annotate more integration tests * Annotate journal system tests * Annotate more tests. * Annotate gas,head buffer behaviors * Fix markset annotations * doc: test annotations for the markets dagstore wrapper * Annotate miner_api test in dagstore * Annotate more test files * Remove bad annotations from fsrepo * Annotate wdpost system * Remove bad annotations * Renamce "conformance" to "chaos_actor" tests * doc: stm annotations for blockheader & election proof tests * Annotate remaining "A" tests * annotate: stm for error_test * memrepo_test.go * Annotate "b" file tests * message_test.go * doc: stm annotate for fsrepo_test * Annotate "c" file tests * Annotate "D" test files * message_test.go * doc: stm annotate for chain, node/config & client * docs: stm annotate node_test * Annotate u,v,wl tests * doc: stm annotations for various test files * Annotate "T" test files * doc: stm annotate for proxy_util_test & policy_test * doc: stm annotate for various tests * doc: final few stm annotations * Add mempool unit tests * Add two more memPool Add tests * Update submodules * Add check function tests * Add stm annotations, refactor test helper * Annotate api,proxy_util,blockstore_badger, policy tests * Annotate splitstore: bsbadger / markset solving merge conflicts * Annotate splitstore feature * Annotate union/timed blockstore tests * Annotate openrpc, diff_adt tests * Annotate error,drand,events tests * Annotate predicates_test * Fix annotations * Annotate tscache, gen tests * Annotate fundmanager test * Annotate statetree_test * Annotate forks_test * Annotate searchwait_test.go * Fix duplicated @@ symbols * Annotate chain stmgr/store tests * Annotate more (types) tests * More tests annotated * Annotate conformance chaos actor tests * Annotate more integration tests * Annotate journal system tests * Annotate more tests. * Annotate gas,head buffer behaviors solve merge conflict * Fix markset annotations * Annotate miner_api test in dagstore * Annotate more test files * doc: test annotations for the markets dagstore wrapper * Annotate wdpost system * Renamce "conformance" to "chaos_actor" tests * Annotate remaining "A" tests * doc: stm annotations for blockheader & election proof tests * annotate: stm for error_test * Annotate "b" file tests * memrepo_test.go * Annotate "c" file tests * message_test.go * Annotate "D" test files * doc: stm annotate for fsrepo_test * Annotate u,v,wl tests * message_test.go * doc: stm annotate for chain, node/config & client * docs: stm annotate node_test * Annotate "T" test files * doc: stm annotations for various test files * Add mempool unit tests solve merge conflict * doc: stm annotate for proxy_util_test & policy_test * doc: stm annotate for various tests * doc: final few stm annotations * Add two more memPool Add tests * Update submodules * Add check function tests solve conflict * Add stm annotations, refactor test helper solve merge conflict * Change CLI test kinds to "unit" * Fix double merged test * Fix ccupgrade_test merge * Fix lint issues * Add stm annotation to types_Test * Test vectors submodule * Add file annotation to burn_test Co-authored-by: Nikola Divic <divicnikola@gmail.com> Co-authored-by: TheMenko <themenkoprojects@gmail.com>
2022-03-16 17:37:34 +00:00
//stm: @TOKEN_PAYCH_CREATE_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
ch, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, address.Undef, ch)
pushedMsg := mock.pushedMessages(mcid)
2020-07-28 23:16:47 +00:00
require.Equal(t, from, pushedMsg.Message.From)
2020-09-23 06:18:52 +00:00
require.Equal(t, lotusinit.Address, pushedMsg.Message.To)
2020-07-28 23:16:47 +00:00
require.Equal(t, amt, pushedMsg.Message.Value)
}
2022-01-06 15:04:39 +00:00
func TestPaychGetOffchainNoReserveFails(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
mgr, err := newManager(store, mock)
require.NoError(t, err)
amt := big.NewInt(10)
_, _, err = mgr.GetPaych(ctx, from, to, amt, offChainNoReserve)
require.Error(t, err)
}
func TestPaychGetCreateOffchainReserveFails(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
mgr, err := newManager(store, mock)
require.NoError(t, err)
amt := big.NewInt(10)
_, _, err = mgr.GetPaych(ctx, from, to, amt, offChainReserve)
require.Error(t, err)
}
2020-07-28 23:16:47 +00:00
// TestPaychGetCreateChannelThenAddFunds tests creating a channel and then
// adding funds to it
func TestPaychGetCreateChannelThenAddFunds(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_LIST_CHANNELS_001, @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send create message for a channel with value 10
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Should have no channels yet (message sent but channel not created)
2021-12-14 17:01:45 +00:00
cis, err := mgr.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 0)
// 1. Set up create channel response (sent in response to WaitForMsg())
response := testChannelResponse(t, ch)
done := make(chan struct{})
go func() {
defer close(done)
// 2. Request add funds - should block until create channel has completed
amt2 := big.NewInt(5)
2022-01-06 15:04:39 +00:00
ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve)
2020-07-28 23:16:47 +00:00
// 4. This GetPaych should return after create channel from first
// GetPaych completes
require.NoError(t, err)
// Expect the channel to be the same
require.Equal(t, ch, ch2)
// Expect add funds message CID to be different to create message cid
require.NotEqual(t, createMsgCid, addFundsMsgCid)
// Should have one channel, whose address is the channel that was created
2021-12-14 17:01:45 +00:00
cis, err := mgr.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
// Amount should be amount sent to first GetPaych (to create
// channel).
// PendingAmount should be amount sent in second GetPaych
// (second GetPaych triggered add funds, which has not yet been confirmed)
2021-12-14 17:01:45 +00:00
ci, err := mgr.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.EqualValues(t, 10, ci.Amount.Int64())
require.EqualValues(t, 5, ci.PendingAmount.Int64())
require.Nil(t, ci.CreateMsg)
// Trigger add funds confirmation
mock.receiveMsgResponse(addFundsMsgCid, types.MessageReceipt{ExitCode: 0})
2020-07-28 23:16:47 +00:00
// Wait for add funds confirmation to be processed by manager
_, err = mgr.GetPaychWaitReady(ctx, addFundsMsgCid)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
// Should still have one channel
2021-12-14 17:01:45 +00:00
cis, err = mgr.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
// Channel amount should include last amount sent to GetPaych
2021-12-14 17:01:45 +00:00
ci, err = mgr.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.EqualValues(t, 15, ci.Amount.Int64())
require.EqualValues(t, 0, ci.PendingAmount.Int64())
require.Nil(t, ci.AddFundsMsg)
}()
// 3. Send create channel response
mock.receiveMsgResponse(createMsgCid, response)
2020-07-28 23:16:47 +00:00
<-done
}
2022-01-04 20:34:27 +00:00
func TestPaychGetCreatePrefundedChannelThenAddFunds(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-01-04 20:34:27 +00:00
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainNoReserve)
2022-01-04 20:34:27 +00:00
require.NoError(t, err)
// Should have no channels yet (message sent but channel not created)
cis, err := mgr.ListChannels(ctx)
require.NoError(t, err)
require.Len(t, cis, 0)
// 1. Set up create channel response (sent in response to WaitForMsg())
response := testChannelResponse(t, ch)
done := make(chan struct{})
go func() {
defer close(done)
// 2. Request add funds - shouldn't block
amt2 := big.NewInt(3)
2022-01-06 15:04:39 +00:00
ch2, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, offChainReserve)
2022-01-04 20:34:27 +00:00
// 4. This GetPaych should return after create channel from first
// GetPaych completes
require.NoError(t, err)
// Expect the channel to be the same
require.Equal(t, ch, ch2)
require.Equal(t, cid.Undef, addFundsMsgCid)
// Should have one channel, whose address is the channel that was created
cis, err := mgr.ListChannels(ctx)
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
// Amount should be amount sent to first GetPaych (to create
// channel).
// PendingAmount should be zero, AvailableAmount should be Amount minus what we requested
ci, err := mgr.GetChannelInfo(ctx, ch)
require.NoError(t, err)
require.EqualValues(t, 10, ci.Amount.Int64())
require.EqualValues(t, 0, ci.PendingAmount.Int64())
require.EqualValues(t, 7, ci.AvailableAmount.Int64())
require.Nil(t, ci.CreateMsg)
require.Nil(t, ci.AddFundsMsg)
}()
// 3. Send create channel response
mock.receiveMsgResponse(createMsgCid, response)
<-done
}
2020-07-28 23:16:47 +00:00
// TestPaychGetCreateChannelWithErrorThenCreateAgain tests that if an
// operation is queued up behind a create channel operation, and the create
// channel fails, then the waiting operation can succeed.
func TestPaychGetCreateChannelWithErrorThenCreateAgain(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_LIST_CHANNELS_001, @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send create message for a channel
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, mcid1, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// 1. Set up create channel response (sent in response to WaitForMsg())
// This response indicates an error.
errResponse := types.MessageReceipt{
ExitCode: 1, // error
Return: []byte{},
}
done := make(chan struct{})
go func() {
defer close(done)
// 2. Should block until create channel has completed.
// Because first channel create fails, this request
// should be for channel create again.
2020-07-28 23:16:47 +00:00
amt2 := big.NewInt(5)
2022-01-06 15:04:39 +00:00
ch2, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, address.Undef, ch2)
// 4. Send a success response
ch := tutils.NewIDAddr(t, 100)
successResponse := testChannelResponse(t, ch)
mock.receiveMsgResponse(mcid2, successResponse)
2020-07-28 23:16:47 +00:00
_, err = mgr.GetPaychWaitReady(ctx, mcid2)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
// Should have one channel, whose address is the channel that was created
2021-12-14 17:01:45 +00:00
cis, err := mgr.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
2021-12-14 17:01:45 +00:00
ci, err := mgr.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, amt2, ci.Amount)
}()
// 3. Send error response to first channel create
mock.receiveMsgResponse(mcid1, errResponse)
2020-07-28 23:16:47 +00:00
<-done
}
// TestPaychGetRecoverAfterError tests that after a create channel fails, the
// next attempt to create channel can succeed.
func TestPaychGetRecoverAfterError(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_LIST_CHANNELS_001, @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send create message for a channel
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send error create channel response
mock.receiveMsgResponse(mcid, types.MessageReceipt{
2020-07-28 23:16:47 +00:00
ExitCode: 1, // error
Return: []byte{},
})
// Send create message for a channel again
amt2 := big.NewInt(7)
2022-01-06 15:04:39 +00:00
_, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send success create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(mcid2, response)
2020-07-28 23:16:47 +00:00
_, err = mgr.GetPaychWaitReady(ctx, mcid2)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
// Should have one channel, whose address is the channel that was created
2021-12-14 17:01:45 +00:00
cis, err := mgr.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
2021-12-14 17:01:45 +00:00
ci, err := mgr.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, amt2, ci.Amount)
require.EqualValues(t, 0, ci.PendingAmount.Int64())
require.Nil(t, ci.CreateMsg)
}
// TestPaychGetRecoverAfterAddFundsError tests that after an add funds fails, the
// next attempt to add funds can succeed.
func TestPaychGetRecoverAfterAddFundsError(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_LIST_CHANNELS_001, @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send create message for a channel
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, mcid1, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send success create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(mcid1, response)
2020-07-28 23:16:47 +00:00
// Send add funds message for channel
amt2 := big.NewInt(5)
2022-01-06 15:04:39 +00:00
_, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send error add funds response
mock.receiveMsgResponse(mcid2, types.MessageReceipt{
2020-07-28 23:16:47 +00:00
ExitCode: 1, // error
Return: []byte{},
})
_, err = mgr.GetPaychWaitReady(ctx, mcid2)
require.Error(t, err)
2020-07-28 23:16:47 +00:00
// Should have one channel, whose address is the channel that was created
2021-12-14 17:01:45 +00:00
cis, err := mgr.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
2021-12-14 17:01:45 +00:00
ci, err := mgr.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, amt, ci.Amount)
require.EqualValues(t, 0, ci.PendingAmount.Int64())
require.Nil(t, ci.CreateMsg)
require.Nil(t, ci.AddFundsMsg)
// Send add funds message for channel again
amt3 := big.NewInt(2)
2022-01-06 15:04:39 +00:00
_, mcid3, err := mgr.GetPaych(ctx, from, to, amt3, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send success add funds response
mock.receiveMsgResponse(mcid3, types.MessageReceipt{
2020-07-28 23:16:47 +00:00
ExitCode: 0,
Return: []byte{},
})
_, err = mgr.GetPaychWaitReady(ctx, mcid3)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
// Should have one channel, whose address is the channel that was created
2021-12-14 17:01:45 +00:00
cis, err = mgr.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
// Amount should include amount for successful add funds msg
2021-12-14 17:01:45 +00:00
ci, err = mgr.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, amt.Int64()+amt3.Int64(), ci.Amount.Int64())
require.EqualValues(t, 0, ci.PendingAmount.Int64())
require.Nil(t, ci.CreateMsg)
require.Nil(t, ci.AddFundsMsg)
}
// TestPaychGetRestartAfterCreateChannelMsg tests that if the system stops
// right after the create channel message is sent, the channel will be
// created when the system restarts.
func TestPaychGetRestartAfterCreateChannelMsg(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_LIST_CHANNELS_001, @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
2022-06-15 10:09:11 +00:00
var createMsgCid cid.Cid
{
mock := newMockManagerAPI()
2020-07-28 23:16:47 +00:00
2022-06-15 10:09:11 +00:00
mgr, err := newManager(store, mock)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
2022-06-15 10:09:11 +00:00
// Send create message for a channel with value 10
amt := big.NewInt(10)
_, createMsgCid, err = mgr.GetPaych(ctx, from, to, amt, onChainReserve)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
2022-06-15 10:09:11 +00:00
// Simulate shutting down system
mock.close()
}
2020-07-28 23:16:47 +00:00
// Create a new manager with the same datastore
2022-06-15 10:09:11 +00:00
mock2 := newMockManagerAPI()
defer mock2.close()
2020-07-28 23:16:47 +00:00
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
2022-06-15 10:09:11 +00:00
mock2.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-06-15 10:09:11 +00:00
mgr2, err := newManager(store, mock2)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Should have no channels yet (message sent but channel not created)
2021-12-14 17:01:45 +00:00
cis, err := mgr2.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 0)
// 1. Set up create channel response (sent in response to WaitForMsg())
response := testChannelResponse(t, ch)
done := make(chan struct{})
go func() {
defer close(done)
// 2. Request add funds - should block until create channel has completed
amt2 := big.NewInt(5)
2022-01-06 15:04:39 +00:00
ch2, addFundsMsgCid, err := mgr2.GetPaych(ctx, from, to, amt2, onChainReserve)
2020-07-28 23:16:47 +00:00
// 4. This GetPaych should return after create channel from first
// GetPaych completes
require.NoError(t, err)
// Expect the channel to have been created
require.Equal(t, ch, ch2)
// Expect add funds message CID to be different to create message cid
require.NotEqual(t, createMsgCid, addFundsMsgCid)
// Should have one channel, whose address is the channel that was created
2021-12-14 17:01:45 +00:00
cis, err := mgr2.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
// Amount should be amount sent to first GetPaych (to create
// channel).
// PendingAmount should be amount sent in second GetPaych
// (second GetPaych triggered add funds, which has not yet been confirmed)
2021-12-14 17:01:45 +00:00
ci, err := mgr2.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.EqualValues(t, 10, ci.Amount.Int64())
require.EqualValues(t, 5, ci.PendingAmount.Int64())
require.Nil(t, ci.CreateMsg)
}()
// 3. Send create channel response
2022-06-15 10:09:11 +00:00
mock2.receiveMsgResponse(createMsgCid, response)
2020-07-28 23:16:47 +00:00
<-done
}
// TestPaychGetRestartAfterAddFundsMsg tests that if the system stops
// right after the add funds message is sent, the add funds will be
// processed when the system restarts.
func TestPaychGetRestartAfterAddFundsMsg(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_LIST_CHANNELS_001, @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
2020-07-28 23:16:47 +00:00
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send create message for a channel
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, mcid1, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send success create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(mcid1, response)
2020-07-28 23:16:47 +00:00
// Send add funds message for channel
amt2 := big.NewInt(5)
2022-01-06 15:04:39 +00:00
_, mcid2, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Simulate shutting down system
require.NoError(t, mgr.Stop())
2020-07-28 23:16:47 +00:00
// Create a new manager with the same datastore
2022-06-15 10:31:02 +00:00
mock2 := newMockManagerAPI()
defer mock2.close()
2020-07-28 23:16:47 +00:00
2022-06-15 10:31:02 +00:00
mock2.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-06-15 10:31:02 +00:00
mgr2, err := newManager(store, mock2)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// Send success add funds response
2022-06-15 10:31:02 +00:00
mock2.receiveMsgResponse(mcid2, types.MessageReceipt{
2020-07-28 23:16:47 +00:00
ExitCode: 0,
Return: []byte{},
})
_, err = mgr2.GetPaychWaitReady(ctx, mcid2)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
// Should have one channel, whose address is the channel that was created
2021-12-14 17:01:45 +00:00
cis, err := mgr2.ListChannels(ctx)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Len(t, cis, 1)
require.Equal(t, ch, cis[0])
// Amount should include amount for successful add funds msg
2021-12-14 17:01:45 +00:00
ci, err := mgr2.GetChannelInfo(ctx, ch)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, amt.Int64()+amt2.Int64(), ci.Amount.Int64())
require.EqualValues(t, 0, ci.PendingAmount.Int64())
require.Nil(t, ci.CreateMsg)
require.Nil(t, ci.AddFundsMsg)
}
// TestPaychGetWait tests that GetPaychWaitReady correctly waits for the
// channel to be created or funds to be added
func TestPaychGetWait(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
expch := tutils.NewIDAddr(t, 100)
2020-07-28 23:16:47 +00:00
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(expch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// 1. Get
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
go func() {
// 3. Send response
response := testChannelResponse(t, expch)
mock.receiveMsgResponse(createMsgCid, response)
2020-07-28 23:16:47 +00:00
}()
// 2. Wait till ready
ch, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
2020-07-28 23:16:47 +00:00
require.Equal(t, expch, ch)
// 4. Wait again - message has already been received so should
// return immediately
ch, err = mgr.GetPaychWaitReady(ctx, createMsgCid)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
require.Equal(t, expch, ch)
// Request add funds
amt2 := big.NewInt(15)
2022-01-06 15:04:39 +00:00
_, addFundsMsgCid, err := mgr.GetPaych(ctx, from, to, amt2, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
go func() {
// 6. Send add funds response
addFundsResponse := types.MessageReceipt{
ExitCode: 0,
Return: []byte{},
}
mock.receiveMsgResponse(addFundsMsgCid, addFundsResponse)
2020-07-28 23:16:47 +00:00
}()
// 5. Wait for add funds
ch, err = mgr.GetPaychWaitReady(ctx, addFundsMsgCid)
require.NoError(t, err)
require.Equal(t, expch, ch)
2020-07-28 23:16:47 +00:00
}
// TestPaychGetWaitErr tests that GetPaychWaitReady correctly handles errors
func TestPaychGetWaitErr(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// 1. Create channel
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
done := make(chan address.Address)
go func() {
defer close(done)
// 2. Wait for channel to be created
_, err := mgr.GetPaychWaitReady(ctx, mcid)
// 4. Channel creation should have failed
require.NotNil(t, err)
// 5. Call wait again with the same message CID
_, err = mgr.GetPaychWaitReady(ctx, mcid)
// 6. Should return immediately with the same error
require.NotNil(t, err)
}()
// 3. Send error response to create channel
response := types.MessageReceipt{
ExitCode: 1, // error
Return: []byte{},
}
mock.receiveMsgResponse(mcid, response)
2020-07-28 23:16:47 +00:00
<-done
}
// TestPaychGetWaitCtx tests that GetPaychWaitReady returns early if the context
// is cancelled
func TestPaychGetWaitCtx(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_WAIT_READY_001
2020-07-28 23:16:47 +00:00
ctx, cancel := context.WithCancel(context.Background())
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
2020-07-28 23:16:47 +00:00
mgr, err := newManager(store, mock)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
amt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, mcid, err := mgr.GetPaych(ctx, from, to, amt, onChainReserve)
2020-07-28 23:16:47 +00:00
require.NoError(t, err)
// When the context is cancelled, should unblock wait
go func() {
cancel()
}()
_, err = mgr.GetPaychWaitReady(ctx, mcid)
require.Error(t, ctx.Err(), err)
}
// TestPaychGetMergeAddFunds tests that if a create channel is in
// progress and two add funds are queued up behind it, the two add funds
// will be merged
func TestPaychGetMergeAddFunds(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_WAIT_READY_001
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve)
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
addFundsAmt1 := big.NewInt(5)
addFundsAmt2 := big.NewInt(3)
var addFundsCh1 address.Address
var addFundsCh2 address.Address
var addFundsMcid1 cid.Cid
var addFundsMcid2 cid.Cid
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
2020-10-26 10:09:56 +00:00
var err error
2022-01-06 15:04:39 +00:00
addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainReserve)
2022-01-04 20:34:27 +00:00
require.NoError(t, err)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
var err error
2022-01-06 15:04:39 +00:00
addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve)
2022-01-04 20:34:27 +00:00
require.NoError(t, err)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to be sent
addFundsSent.Wait()
// Expect add funds requests to have same channel as create channel and
// same message cid as each other (because they should have been merged)
require.Equal(t, ch, addFundsCh1)
require.Equal(t, ch, addFundsCh2)
require.Equal(t, addFundsMcid1, addFundsMcid2)
// Send success add funds response
mock.receiveMsgResponse(addFundsMcid1, types.MessageReceipt{
ExitCode: 0,
Return: []byte{},
})
// Wait for add funds response
addFundsCh, err := mgr.GetPaychWaitReady(ctx, addFundsMcid1)
require.NoError(t, err)
require.Equal(t, ch, addFundsCh)
// Make sure that one create channel message and one add funds message was
// sent
require.Equal(t, 2, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
// Check merged add funds amount is the sum of the individual
// amounts
addFundsMsg := mock.pushedMessages(addFundsMcid1)
require.Equal(t, from, addFundsMsg.Message.From)
require.Equal(t, ch, addFundsMsg.Message.To)
require.Equal(t, types.BigAdd(addFundsAmt1, addFundsAmt2), addFundsMsg.Message.Value)
}
func TestPaychGetMergePrefundAndReserve(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-01-04 20:34:27 +00:00
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve)
2022-01-04 20:34:27 +00:00
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
addFundsAmt1 := big.NewInt(5) // 1 prefunds
addFundsAmt2 := big.NewInt(3) // 2 reserves
var addFundsCh1 address.Address
var addFundsCh2 address.Address
var addFundsMcid1 cid.Cid
var addFundsMcid2 cid.Cid
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
var err error
2022-01-06 15:04:39 +00:00
addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainNoReserve)
require.NoError(t, err)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
2020-10-26 10:09:56 +00:00
var err error
2022-01-06 15:04:39 +00:00
addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve)
require.NoError(t, err)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to be sent
addFundsSent.Wait()
// Expect add funds requests to have same channel as create channel and
// same message cid as each other (because they should have been merged)
require.Equal(t, ch, addFundsCh1)
require.Equal(t, ch, addFundsCh2)
require.Equal(t, addFundsMcid1, addFundsMcid2)
// Send success add funds response
mock.receiveMsgResponse(addFundsMcid1, types.MessageReceipt{
ExitCode: 0,
Return: []byte{},
})
// Wait for add funds response
addFundsCh, err := mgr.GetPaychWaitReady(ctx, addFundsMcid1)
require.NoError(t, err)
require.Equal(t, ch, addFundsCh)
// Make sure that one create channel message and one add funds message was
// sent
require.Equal(t, 2, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
2020-09-23 06:18:52 +00:00
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
// Check merged add funds amount is the sum of the individual
// amounts
addFundsMsg := mock.pushedMessages(addFundsMcid1)
require.Equal(t, from, addFundsMsg.Message.From)
require.Equal(t, ch, addFundsMsg.Message.To)
require.Equal(t, types.BigAdd(addFundsAmt1, addFundsAmt2), addFundsMsg.Message.Value)
}
2022-01-04 20:34:27 +00:00
func TestPaychGetMergePrefundAndReservePrefunded(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-01-04 20:34:27 +00:00
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainNoReserve)
2022-01-04 20:34:27 +00:00
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
addFundsAmt1 := big.NewInt(5) // 1 prefunds
addFundsAmt2 := big.NewInt(3) // 2 reserves
var addFundsCh1 address.Address
var addFundsCh2 address.Address
var addFundsMcid1 cid.Cid
var addFundsMcid2 cid.Cid
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
var err error
2022-01-06 15:04:39 +00:00
addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainNoReserve)
2022-01-04 20:34:27 +00:00
require.NoError(t, err)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
var err error
2022-01-06 15:04:39 +00:00
addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve)
2022-01-04 20:34:27 +00:00
require.NoError(t, err)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to be sent
addFundsSent.Wait()
// Expect add funds requests to have same channel as create channel and
// same message cid as each other (because they should have been merged)
require.Equal(t, ch, addFundsCh1)
require.Equal(t, ch, addFundsCh2)
require.NotEqual(t, cid.Undef, addFundsMcid1)
require.Equal(t, cid.Undef, addFundsMcid2)
// Send success add funds response
mock.receiveMsgResponse(addFundsMcid1, types.MessageReceipt{
ExitCode: 0,
Return: []byte{},
})
// Wait for add funds response
addFundsCh, err := mgr.GetPaychWaitReady(ctx, addFundsMcid1)
require.NoError(t, err)
require.Equal(t, ch, addFundsCh)
// Make sure that one create channel message and one add funds message was
// sent
require.Equal(t, 2, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
// Check merged add funds amount is the sum of the individual
// amounts
addFundsMsg := mock.pushedMessages(addFundsMcid1)
require.Equal(t, from, addFundsMsg.Message.From)
require.Equal(t, ch, addFundsMsg.Message.To)
require.Equal(t, addFundsAmt1, addFundsMsg.Message.Value)
}
2022-01-06 15:04:39 +00:00
func TestPaychGetMergePrefundAndReservePrefundedOneOffchain(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-01-06 15:04:39 +00:00
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainNoReserve)
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
addFundsAmt1 := big.NewInt(5) // 1 reserves
addFundsAmt2 := big.NewInt(3) // 2 reserves
var addFundsCh1 address.Address
var addFundsCh2 address.Address
var addFundsMcid1 cid.Cid
var addFundsMcid2 cid.Cid
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
var err error
addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, offChainReserve)
require.NoError(t, err)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
var err error
addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve)
require.NoError(t, err)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to be sent
addFundsSent.Wait()
// Expect add funds requests to have same channel as create channel and
// same message cid as each other (because they should have been merged)
require.Equal(t, ch, addFundsCh1)
require.Equal(t, ch, addFundsCh2)
require.Equal(t, cid.Undef, addFundsMcid1)
require.Equal(t, cid.Undef, addFundsMcid2)
// Make sure that one create channel message was sent
require.Equal(t, 1, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
}
func TestPaychGetMergePrefundAndReservePrefundedBothOffchainOneFail(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-01-06 15:04:39 +00:00
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainNoReserve)
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
addFundsAmt1 := big.NewInt(5) // 1 reserves
addFundsAmt2 := big.NewInt(6) // 2 reserves too much
var addFundsCh1 address.Address
var addFundsCh2 address.Address
var addFundsMcid1 cid.Cid
var addFundsMcid2 cid.Cid
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
var err error
addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, offChainReserve)
require.NoError(t, err)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
var err error
addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, offChainReserve)
require.Error(t, err)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to be sent
addFundsSent.Wait()
// Expect add funds requests to have same channel as create channel and
// same message cid as each other (because they should have been merged)
require.Equal(t, ch, addFundsCh1)
require.Equal(t, ch, addFundsCh2)
require.Equal(t, cid.Undef, addFundsMcid1)
require.Equal(t, cid.Undef, addFundsMcid2)
// Make sure that one create channel message was sent
require.Equal(t, 1, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
}
func TestPaychGetMergePrefundAndReserveOneOffchainOneFail(t *testing.T) {
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2022-01-06 15:04:39 +00:00
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve)
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
addFundsAmt1 := big.NewInt(5) // 1 reserves
addFundsAmt2 := big.NewInt(6) // 2 reserves
var addFundsCh1 address.Address
var addFundsCh2 address.Address
var addFundsMcid1 cid.Cid
var addFundsMcid2 cid.Cid
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
var err error
addFundsCh1, addFundsMcid1, err = mgr.GetPaych(ctx, from, to, addFundsAmt1, onChainReserve)
require.NoError(t, err)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
var err error
addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, offChainReserve)
require.Error(t, err)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to be sent
addFundsSent.Wait()
// Expect add funds requests to have same channel as create channel and
// same message cid as each other (because they should have been merged)
require.Equal(t, ch, addFundsCh1)
require.Equal(t, ch, addFundsCh2)
require.NotEqual(t, cid.Undef, addFundsMcid1)
require.Equal(t, cid.Undef, addFundsMcid2)
// Make sure that one create channel message was sent
require.Equal(t, 2, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
// Check merged add funds amount is the sum of the individual
// amounts
addFundsMsg := mock.pushedMessages(addFundsMcid1)
require.Equal(t, from, addFundsMsg.Message.From)
require.Equal(t, ch, addFundsMsg.Message.To)
require.Equal(t, addFundsAmt1, addFundsMsg.Message.Value)
}
// TestPaychGetMergeAddFundsCtxCancelOne tests that when a queued add funds
// request is cancelled, its amount is removed from the total merged add funds
func TestPaychGetMergeAddFundsCtxCancelOne(t *testing.T) {
//stm: @TOKEN_PAYCH_WAIT_READY_001
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: types.NewInt(20),
}
mock.setPaychState(ch, act, paychmock.NewMockPayChState(from, to, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve)
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
addFundsAmt1 := big.NewInt(5)
addFundsAmt2 := big.NewInt(3)
var addFundsCh2 address.Address
var addFundsMcid2 cid.Cid
var addFundsErr1 error
addFundsCtx1, cancelAddFundsCtx1 := context.WithCancel(ctx)
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
2022-01-06 15:04:39 +00:00
_, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, addFundsAmt1, onChainReserve)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
2020-10-26 10:09:56 +00:00
var err error
2022-01-06 15:04:39 +00:00
addFundsCh2, addFundsMcid2, err = mgr.GetPaych(ctx, from, to, addFundsAmt2, onChainReserve)
require.NoError(t, err)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Cancel the first add funds request
cancelAddFundsCtx1()
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to be sent
addFundsSent.Wait()
// Expect first add funds request to have been cancelled
require.NotNil(t, addFundsErr1)
require.Equal(t, ch, addFundsCh2)
// Send success add funds response
mock.receiveMsgResponse(addFundsMcid2, types.MessageReceipt{
ExitCode: 0,
Return: []byte{},
})
// Wait for add funds response
addFundsCh, err := mgr.GetPaychWaitReady(ctx, addFundsMcid2)
require.NoError(t, err)
require.Equal(t, ch, addFundsCh)
// Make sure that one create channel message and one add funds message was
// sent
require.Equal(t, 2, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
2020-09-23 06:18:52 +00:00
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
// Check merged add funds amount only includes the second add funds amount
// (because first was cancelled)
addFundsMsg := mock.pushedMessages(addFundsMcid2)
require.Equal(t, from, addFundsMsg.Message.From)
require.Equal(t, ch, addFundsMsg.Message.To)
require.Equal(t, addFundsAmt2, addFundsMsg.Message.Value)
}
// TestPaychGetMergeAddFundsCtxCancelAll tests that when all queued add funds
// requests are cancelled, no add funds message is sent
func TestPaychGetMergeAddFundsCtxCancelAll(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_WAIT_READY_001
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewIDAddr(t, 101)
to := tutils.NewIDAddr(t, 102)
mock := newMockManagerAPI()
defer mock.close()
mgr, err := newManager(store, mock)
require.NoError(t, err)
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve)
require.NoError(t, err)
// Queue up two add funds requests behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(2)
var addFundsErr1 error
var addFundsErr2 error
addFundsCtx1, cancelAddFundsCtx1 := context.WithCancel(ctx)
addFundsCtx2, cancelAddFundsCtx2 := context.WithCancel(ctx)
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
2022-01-06 15:04:39 +00:00
_, _, addFundsErr1 = mgr.GetPaych(addFundsCtx1, from, to, big.NewInt(5), onChainReserve)
}()
go func() {
defer addFundsSent.Done()
// Request add funds again - should merge with waiting add funds request
2022-01-06 15:04:39 +00:00
_, _, addFundsErr2 = mgr.GetPaych(addFundsCtx2, from, to, big.NewInt(3), onChainReserve)
}()
// Wait for add funds requests to be queued up
waitForQueueSize(t, mgr, from, to, 2)
// Cancel all add funds requests
cancelAddFundsCtx1()
cancelAddFundsCtx2()
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, createMsgCid)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds requests to error out
addFundsSent.Wait()
require.NotNil(t, addFundsErr1)
require.NotNil(t, addFundsErr2)
// Make sure that just the create channel message was sent
require.Equal(t, 1, mock.pushedMessageCount())
// Check create message amount is correct
createMsg := mock.pushedMessages(createMsgCid)
require.Equal(t, from, createMsg.Message.From)
2020-09-23 06:18:52 +00:00
require.Equal(t, lotusinit.Address, createMsg.Message.To)
require.Equal(t, createAmt, createMsg.Message.Value)
}
2020-09-01 14:33:44 +00:00
// TestPaychAvailableFunds tests that PaychAvailableFunds returns the correct
// channel state
func TestPaychAvailableFunds(t *testing.T) {
2021-12-14 15:56:16 +00:00
//stm: @TOKEN_PAYCH_WAIT_READY_001, @TOKEN_PAYCH_AVAILABLE_FUNDS_001, @TOKEN_PAYCH_AVAILABLE_FUNDS_002, @TOKEN_PAYCH_AVAILABLE_FUNDS_003
2020-09-01 14:33:44 +00:00
ctx := context.Background()
store := NewStore(ds_sync.MutexWrap(ds.NewMapDatastore()))
fromKeyPrivate, fromKeyPublic := testGenerateKeyPair(t)
ch := tutils.NewIDAddr(t, 100)
from := tutils.NewSECP256K1Addr(t, string(fromKeyPublic))
to := tutils.NewIDAddr(t, 102)
fromAcct := tutils.NewActorAddr(t, "fromAct")
toAcct := tutils.NewActorAddr(t, "toAct")
mock := newMockManagerAPI()
defer mock.close()
mgr, err := newManager(store, mock)
require.NoError(t, err)
// No channel created yet so available funds should be all zeroes
2021-12-14 17:01:45 +00:00
av, err := mgr.AvailableFundsByFromTo(ctx, from, to)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
require.Nil(t, av.Channel)
require.Nil(t, av.PendingWaitSentinel)
require.EqualValues(t, 0, av.ConfirmedAmt.Int64())
require.EqualValues(t, 0, av.PendingAmt.Int64())
require.EqualValues(t, 0, av.QueuedAmt.Int64())
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
// Send create message for a channel with value 10
createAmt := big.NewInt(10)
2022-01-06 15:04:39 +00:00
_, createMsgCid, err := mgr.GetPaych(ctx, from, to, createAmt, onChainReserve)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
// Available funds should reflect create channel message sent
2021-12-14 17:01:45 +00:00
av, err = mgr.AvailableFundsByFromTo(ctx, from, to)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
require.Nil(t, av.Channel)
require.EqualValues(t, 0, av.ConfirmedAmt.Int64())
require.EqualValues(t, createAmt, av.PendingAmt)
require.EqualValues(t, 0, av.QueuedAmt.Int64())
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
// Should now have a pending wait sentinel
require.NotNil(t, av.PendingWaitSentinel)
// Queue up an add funds request behind create channel
var addFundsSent sync.WaitGroup
addFundsSent.Add(1)
addFundsAmt := big.NewInt(5)
var addFundsMcid cid.Cid
go func() {
defer addFundsSent.Done()
// Request add funds - should block until create channel has completed
2020-10-26 10:09:56 +00:00
var err error
2022-01-06 15:04:39 +00:00
_, addFundsMcid, err = mgr.GetPaych(ctx, from, to, addFundsAmt, onChainReserve)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
}()
// Wait for add funds request to be queued up
waitForQueueSize(t, mgr, from, to, 1)
// Available funds should now include queued funds
2021-12-14 17:01:45 +00:00
av, err = mgr.AvailableFundsByFromTo(ctx, from, to)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
require.Nil(t, av.Channel)
require.NotNil(t, av.PendingWaitSentinel)
require.EqualValues(t, 0, av.ConfirmedAmt.Int64())
// create amount is still pending
require.EqualValues(t, createAmt, av.PendingAmt)
// queued amount now includes add funds amount
require.EqualValues(t, addFundsAmt, av.QueuedAmt)
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
// Create channel in state
mock.setAccountAddress(fromAcct, from)
mock.setAccountAddress(toAcct, to)
2020-09-01 14:33:44 +00:00
act := &types.Actor{
Code: builtin.AccountActorCodeID,
Head: cid.Cid{},
Nonce: 0,
Balance: createAmt,
}
2020-09-14 08:11:11 +00:00
mock.setPaychState(ch, act, paychmock.NewMockPayChState(fromAcct, toAcct, abi.ChainEpoch(0), make(map[uint64]paych.LaneState)))
2020-09-01 14:33:44 +00:00
// Send create channel response
response := testChannelResponse(t, ch)
mock.receiveMsgResponse(createMsgCid, response)
// Wait for create channel response
chres, err := mgr.GetPaychWaitReady(ctx, *av.PendingWaitSentinel)
require.NoError(t, err)
require.Equal(t, ch, chres)
// Wait for add funds request to be sent
addFundsSent.Wait()
// Available funds should now include the channel and also a wait sentinel
// for the add funds message
2021-12-14 17:01:45 +00:00
av, err = mgr.AvailableFunds(ctx, ch)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
require.NotNil(t, av.Channel)
require.NotNil(t, av.PendingWaitSentinel)
// create amount is now confirmed
require.EqualValues(t, createAmt, av.ConfirmedAmt)
// add funds amount it now pending
require.EqualValues(t, addFundsAmt, av.PendingAmt)
require.EqualValues(t, 0, av.QueuedAmt.Int64())
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
// Send success add funds response
mock.receiveMsgResponse(addFundsMcid, types.MessageReceipt{
ExitCode: 0,
Return: []byte{},
})
// Wait for add funds response
_, err = mgr.GetPaychWaitReady(ctx, *av.PendingWaitSentinel)
require.NoError(t, err)
// Available funds should no longer have a wait sentinel
2021-12-14 17:01:45 +00:00
av, err = mgr.AvailableFunds(ctx, ch)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
require.NotNil(t, av.Channel)
require.Nil(t, av.PendingWaitSentinel)
// confirmed amount now includes create and add funds amounts
require.EqualValues(t, types.BigAdd(createAmt, addFundsAmt), av.ConfirmedAmt)
require.EqualValues(t, 0, av.PendingAmt.Int64())
require.EqualValues(t, 0, av.QueuedAmt.Int64())
require.EqualValues(t, 0, av.VoucherReedeemedAmt.Int64())
// Add some vouchers
voucherAmt1 := types.NewInt(3)
voucher := createTestVoucher(t, ch, 1, 1, voucherAmt1, fromKeyPrivate)
_, err = mgr.AddVoucherOutbound(ctx, ch, voucher, nil, types.NewInt(0))
require.NoError(t, err)
voucherAmt2 := types.NewInt(2)
voucher = createTestVoucher(t, ch, 2, 1, voucherAmt2, fromKeyPrivate)
_, err = mgr.AddVoucherOutbound(ctx, ch, voucher, nil, types.NewInt(0))
require.NoError(t, err)
2021-12-14 17:01:45 +00:00
av, err = mgr.AvailableFunds(ctx, ch)
2020-09-01 14:33:44 +00:00
require.NoError(t, err)
require.NotNil(t, av.Channel)
require.Nil(t, av.PendingWaitSentinel)
require.EqualValues(t, types.BigAdd(createAmt, addFundsAmt), av.ConfirmedAmt)
require.EqualValues(t, 0, av.PendingAmt.Int64())
require.EqualValues(t, 0, av.QueuedAmt.Int64())
// voucher redeemed amount now includes vouchers
require.EqualValues(t, types.BigAdd(voucherAmt1, voucherAmt2), av.VoucherReedeemedAmt)
}
// waitForQueueSize waits for the funds request queue to be of the given size
func waitForQueueSize(t *testing.T, mgr *Manager, from address.Address, to address.Address, size int) {
ca, err := mgr.accessorByFromTo(from, to)
require.NoError(t, err)
for {
if ca.queueSize() == size {
return
}
time.Sleep(time.Millisecond)
}
}