api: separate method for paych funding

This commit is contained in:
Łukasz Magiera 2022-02-14 19:56:02 +01:00
parent 10af768c60
commit f61eb23f8f
13 changed files with 98 additions and 25 deletions

View File

@ -690,14 +690,16 @@ type FullNode interface {
// The Paych methods are for interacting with and managing payment channels
// PaychGet gets or creates a payment channel between address pair
// - If opts.Reserve is false, the specified amount will be added to the channel through on-chain send for future use
// - If opts.Reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds
// The specified amount will be reserved for use. If there aren't enough non-reserved funds
// available, funds will be added through an on-chain message.
// - When opts.OffChain is true, this call will not cause any messages to be sent to the chain (no automatic
// channel creation/funds adding). If the operation can't be performed without sending a message an error will be
// returned. Note that even when this option is specified, this call can be blocked by previous operations on the
// channel waiting for on-chain operations.
PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts PaychGetOpts) (*ChannelInfo, error) //perm:sign
PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts PaychGetOpts) (*ChannelInfo, error) //perm:sign
// PaychFund gets or creates a payment channel between address pair.
// The specified amount will be added to the channel through on-chain send for future use
PaychFund(ctx context.Context, from, to address.Address, amt types.BigInt) (*ChannelInfo, error) //perm:sign
PaychGetWaitReady(context.Context, cid.Cid) (address.Address, error) //perm:sign
PaychAvailableFunds(ctx context.Context, ch address.Address) (*ChannelAvailableFunds, error) //perm:sign
PaychAvailableFundsByFromTo(ctx context.Context, from, to address.Address) (*ChannelAvailableFunds, error) //perm:sign
@ -837,7 +839,6 @@ const (
)
type PaychGetOpts struct {
Reserve bool
OffChain bool
}

View File

@ -1975,6 +1975,21 @@ func (mr *MockFullNodeMockRecorder) PaychCollect(arg0, arg1 interface{}) *gomock
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychCollect", reflect.TypeOf((*MockFullNode)(nil).PaychCollect), arg0, arg1)
}
// PaychFund mocks base method.
func (m *MockFullNode) PaychFund(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int) (*api.ChannelInfo, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PaychFund", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(*api.ChannelInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PaychFund indicates an expected call of PaychFund.
func (mr *MockFullNodeMockRecorder) PaychFund(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychFund", reflect.TypeOf((*MockFullNode)(nil).PaychFund), arg0, arg1, arg2, arg3)
}
// PaychGet mocks base method.
func (m *MockFullNode) PaychGet(arg0 context.Context, arg1, arg2 address.Address, arg3 big.Int, arg4 api.PaychGetOpts) (*api.ChannelInfo, error) {
m.ctrl.T.Helper()

View File

@ -306,6 +306,8 @@ type FullNodeStruct struct {
PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"`
PaychFund func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) `perm:"sign"`
PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) `perm:"sign"`
PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"`
@ -2185,6 +2187,17 @@ func (s *FullNodeStub) PaychCollect(p0 context.Context, p1 address.Address) (cid
return *new(cid.Cid), ErrNotSupported
}
func (s *FullNodeStruct) PaychFund(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) {
if s.Internal.PaychFund == nil {
return nil, ErrNotSupported
}
return s.Internal.PaychFund(p0, p1, p2, p3)
}
func (s *FullNodeStub) PaychFund(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) {
return nil, ErrNotSupported
}
func (s *FullNodeStruct) PaychGet(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) {
if s.Internal.PaychGet == nil {
return nil, ErrNotSupported

View File

@ -338,10 +338,7 @@ func (w *WrapperV1Full) clientRetrieve(ctx context.Context, order RetrievalOrder
}
func (w *WrapperV1Full) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) {
return w.FullNode.PaychGet(ctx, from, to, amt, api.PaychGetOpts{
Reserve: true, // v0 always reserves
OffChain: false,
})
return w.FullNode.PaychFund(ctx, from, to, amt)
}
var _ FullNode = &WrapperV1Full{}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -79,10 +79,14 @@ var paychAddFundsCmd = &cli.Command{
// Send a message to chain to create channel / add funds to existing
// channel
info, err := api.PaychGet(ctx, from, to, types.BigInt(amt), lapi.PaychGetOpts{
Reserve: cctx.Bool("reserve"),
OffChain: false,
})
var info *lapi.ChannelInfo
if cctx.Bool("reserve") {
info, err = api.PaychGet(ctx, from, to, types.BigInt(amt), lapi.PaychGetOpts{
OffChain: false,
})
} else {
info, err = api.PaychFund(ctx, from, to, types.BigInt(amt))
}
if err != nil {
return err
}

View File

@ -147,6 +147,7 @@
* [PaychAvailableFunds](#PaychAvailableFunds)
* [PaychAvailableFundsByFromTo](#PaychAvailableFundsByFromTo)
* [PaychCollect](#PaychCollect)
* [PaychFund](#PaychFund)
* [PaychGet](#PaychGet)
* [PaychGetWaitReady](#PaychGetWaitReady)
* [PaychList](#PaychList)
@ -4512,10 +4513,35 @@ Response:
}
```
### PaychFund
PaychFund gets or creates a payment channel between address pair.
The specified amount will be added to the channel through on-chain send for future use
Perms: sign
Inputs:
```json
[
"f01234",
"f01234",
"0"
]
```
Response:
```json
{
"Channel": "f01234",
"WaitSentinel": {
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
}
}
```
### PaychGet
PaychGet gets or creates a payment channel between address pair
- If opts.Reserve is false, the specified amount will be added to the channel through on-chain send for future use
- If opts.Reserve is true, the specified amount will be reserved for use. If there aren't enough non-reserved funds
The specified amount will be reserved for use. If there aren't enough non-reserved funds
available, funds will be added through an on-chain message.
- When opts.OffChain is true, this call will not cause any messages to be sent to the chain (no automatic
channel creation/funds adding). If the operation can't be performed without sending a message an error will be
@ -4532,7 +4558,6 @@ Inputs:
"f01234",
"0",
{
"Reserve": true,
"OffChain": true
}
]

View File

@ -66,7 +66,6 @@ func (rcn *retrievalClientNode) GetOrCreatePaymentChannel(ctx context.Context, c
// TODO: respect the provided TipSetToken (a serialized TipSetKey) when
// querying the chain
ci, err := rcn.payAPI.PaychGet(ctx, clientAddress, minerAddress, clientFundsAvailable, api.PaychGetOpts{
Reserve: true,
OffChain: rcn.forceOffChain,
})
if err != nil {

View File

@ -23,7 +23,19 @@ type PaychAPI struct {
}
func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt, opts api.PaychGetOpts) (*api.ChannelInfo, error) {
ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, opts)
ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, true, opts)
if err != nil {
return nil, err
}
return &api.ChannelInfo{
Channel: ch,
WaitSentinel: mcid,
}, nil
}
func (a *PaychAPI) PaychFund(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) {
ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt, false, api.PaychGetOpts{OffChain: false})
if err != nil {
return nil, err
}
@ -55,10 +67,7 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
// TODO: Fix free fund tracking in PaychGet
// TODO: validate voucher spec before locking funds
ch, err := a.PaychGet(ctx, from, to, amount, api.PaychGetOpts{
Reserve: true,
OffChain: false,
})
ch, err := a.PaychGet(ctx, from, to, amount, api.PaychGetOpts{OffChain: false})
if err != nil {
return nil, err
}

View File

@ -101,7 +101,17 @@ func (pm *Manager) Stop() error {
return nil
}
func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt, opts api.PaychGetOpts) (address.Address, cid.Cid, error) {
type getOpts struct {
Reserve bool
OffChain bool
}
func (pm *Manager) GetPaych(ctx context.Context, from, to address.Address, amt types.BigInt, reserve bool, o api.PaychGetOpts) (address.Address, cid.Cid, error) {
opts := getOpts{
Reserve: reserve,
OffChain: o.OffChain,
}
if !opts.Reserve && opts.OffChain {
return address.Undef, cid.Undef, xerrors.Errorf("can't fund payment channels without on-chain operations")
}

View File

@ -33,14 +33,14 @@ type fundsReq struct {
ctx context.Context
promise chan *paychFundsRes
amt types.BigInt
opts api.PaychGetOpts
opts getOpts
lk sync.Mutex
// merge parent, if this req is part of a merge
merge *mergedFundsReq
}
func newFundsReq(ctx context.Context, amt types.BigInt, opts api.PaychGetOpts) *fundsReq {
func newFundsReq(ctx context.Context, amt types.BigInt, opts getOpts) *fundsReq {
promise := make(chan *paychFundsRes, 1)
return &fundsReq{
ctx: ctx,
@ -251,7 +251,7 @@ func (m *mergedFundsReq) failOffChainNoChannel(from, to address.Address) (*paych
// address and the CID of the new add funds message.
// If an operation returns an error, subsequent waiting operations will still
// be attempted.
func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt, opts api.PaychGetOpts) (address.Address, cid.Cid, error) {
func (ca *channelAccessor) getPaych(ctx context.Context, amt types.BigInt, opts getOpts) (address.Address, cid.Cid, error) {
// Add the request to add funds to a queue and wait for the result
freq := newFundsReq(ctx, amt, opts)
ca.enqueue(ctx, freq)