2019-09-16 13:46:05 +00:00
|
|
|
package paych
|
2019-08-20 16:48:33 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2020-09-01 14:33:44 +00:00
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
2019-09-16 13:46:05 +00:00
|
|
|
"github.com/ipfs/go-cid"
|
|
|
|
"go.uber.org/fx"
|
|
|
|
|
2019-12-19 20:13:17 +00:00
|
|
|
"github.com/filecoin-project/go-address"
|
2020-08-12 17:06:08 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
|
|
full "github.com/filecoin-project/lotus/node/impl/full"
|
2020-02-13 00:28:23 +00:00
|
|
|
"github.com/filecoin-project/lotus/paychmgr"
|
2019-08-20 16:48:33 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type PaychAPI struct {
|
|
|
|
fx.In
|
|
|
|
|
2019-09-16 13:46:05 +00:00
|
|
|
full.MpoolAPI
|
|
|
|
full.WalletAPI
|
|
|
|
full.ChainAPI
|
2019-08-20 16:48:33 +00:00
|
|
|
|
2020-02-13 00:28:23 +00:00
|
|
|
PaychMgr *paychmgr.Manager
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 23:16:47 +00:00
|
|
|
func (a *PaychAPI) PaychGet(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) {
|
|
|
|
ch, mcid, err := a.PaychMgr.GetPaych(ctx, from, to, amt)
|
2019-08-20 16:48:33 +00:00
|
|
|
if err != nil {
|
2019-09-13 14:11:40 +00:00
|
|
|
return nil, err
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2019-09-13 14:11:40 +00:00
|
|
|
return &api.ChannelInfo{
|
2020-08-11 14:45:45 +00:00
|
|
|
Channel: ch,
|
2020-08-12 20:29:44 +00:00
|
|
|
WaitSentinel: mcid,
|
2019-09-13 14:11:40 +00:00
|
|
|
}, nil
|
2019-09-10 13:43:01 +00:00
|
|
|
}
|
|
|
|
|
2020-09-01 14:33:44 +00:00
|
|
|
func (a *PaychAPI) PaychAvailableFunds(from, to address.Address) (*api.ChannelAvailableFunds, error) {
|
|
|
|
return a.PaychMgr.AvailableFunds(from, to)
|
|
|
|
}
|
|
|
|
|
2020-08-12 20:29:44 +00:00
|
|
|
func (a *PaychAPI) PaychGetWaitReady(ctx context.Context, sentinel cid.Cid) (address.Address, error) {
|
|
|
|
return a.PaychMgr.GetPaychWaitReady(ctx, sentinel)
|
2020-07-28 23:16:47 +00:00
|
|
|
}
|
|
|
|
|
2020-02-21 17:26:44 +00:00
|
|
|
func (a *PaychAPI) PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error) {
|
2019-09-16 13:46:05 +00:00
|
|
|
return a.PaychMgr.AllocateLane(ch)
|
|
|
|
}
|
|
|
|
|
2019-09-24 21:13:47 +00:00
|
|
|
func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []api.VoucherSpec) (*api.PaymentInfo, error) {
|
|
|
|
amount := vouchers[len(vouchers)-1].Amount
|
|
|
|
|
2019-09-16 17:23:48 +00:00
|
|
|
// TODO: Fix free fund tracking in PaychGet
|
2019-09-24 21:13:47 +00:00
|
|
|
// TODO: validate voucher spec before locking funds
|
2019-09-16 17:23:48 +00:00
|
|
|
ch, err := a.PaychGet(ctx, from, to, amount)
|
2019-09-10 13:43:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-09-16 13:46:05 +00:00
|
|
|
lane, err := a.PaychMgr.AllocateLane(ch.Channel)
|
2019-09-10 13:43:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-02-25 21:09:22 +00:00
|
|
|
svs := make([]*paych.SignedVoucher, len(vouchers))
|
2019-09-10 13:43:01 +00:00
|
|
|
|
2019-09-24 21:13:47 +00:00
|
|
|
for i, v := range vouchers {
|
2020-09-01 14:33:44 +00:00
|
|
|
sv, err := a.PaychMgr.CreateVoucher(ctx, ch.Channel, paych.SignedVoucher{
|
2019-09-24 21:13:47 +00:00
|
|
|
Amount: v.Amount,
|
2020-07-28 23:16:47 +00:00
|
|
|
Lane: lane,
|
2019-09-24 21:13:47 +00:00
|
|
|
|
2020-02-13 03:50:37 +00:00
|
|
|
Extra: v.Extra,
|
2020-02-27 21:45:31 +00:00
|
|
|
TimeLockMin: v.TimeLockMin,
|
|
|
|
TimeLockMax: v.TimeLockMax,
|
2020-02-13 03:50:37 +00:00
|
|
|
MinSettleHeight: v.MinSettle,
|
2019-09-24 21:13:47 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-09-01 14:33:44 +00:00
|
|
|
if sv.Voucher == nil {
|
|
|
|
return nil, xerrors.Errorf("Could not create voucher - shortfall of %d", sv.Shortfall)
|
|
|
|
}
|
2019-09-24 21:13:47 +00:00
|
|
|
|
2020-09-01 14:33:44 +00:00
|
|
|
svs[i] = sv.Voucher
|
2019-09-10 13:43:01 +00:00
|
|
|
}
|
2019-09-24 21:13:47 +00:00
|
|
|
|
2019-09-10 13:43:01 +00:00
|
|
|
return &api.PaymentInfo{
|
2020-08-11 14:45:45 +00:00
|
|
|
Channel: ch.Channel,
|
|
|
|
WaitSentinel: ch.WaitSentinel,
|
|
|
|
Vouchers: svs,
|
2019-09-10 13:43:01 +00:00
|
|
|
}, nil
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *PaychAPI) PaychList(ctx context.Context) ([]address.Address, error) {
|
|
|
|
return a.PaychMgr.ListChannels()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *PaychAPI) PaychStatus(ctx context.Context, pch address.Address) (*api.PaychStatus, error) {
|
2019-09-06 22:39:47 +00:00
|
|
|
ci, err := a.PaychMgr.GetChannelInfo(pch)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &api.PaychStatus{
|
2019-09-10 13:43:01 +00:00
|
|
|
ControlAddr: ci.Control,
|
2019-09-06 22:39:47 +00:00
|
|
|
Direction: api.PCHDir(ci.Direction),
|
|
|
|
}, nil
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-07-18 03:07:02 +00:00
|
|
|
func (a *PaychAPI) PaychSettle(ctx context.Context, addr address.Address) (cid.Cid, error) {
|
2020-07-28 23:16:47 +00:00
|
|
|
return a.PaychMgr.Settle(ctx, addr)
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-07-18 03:07:02 +00:00
|
|
|
func (a *PaychAPI) PaychCollect(ctx context.Context, addr address.Address) (cid.Cid, error) {
|
2020-08-10 17:21:25 +00:00
|
|
|
return a.PaychMgr.Collect(ctx, addr)
|
2020-07-18 03:07:02 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 21:09:22 +00:00
|
|
|
func (a *PaychAPI) PaychVoucherCheckValid(ctx context.Context, ch address.Address, sv *paych.SignedVoucher) error {
|
2019-08-20 16:48:33 +00:00
|
|
|
return a.PaychMgr.CheckVoucherValid(ctx, ch, sv)
|
|
|
|
}
|
|
|
|
|
2020-09-03 03:49:51 +00:00
|
|
|
func (a *PaychAPI) PaychVoucherCheckSpendable(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte) (bool, error) {
|
|
|
|
return a.PaychMgr.CheckVoucherSpendable(ctx, ch, sv, secret)
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 21:09:22 +00:00
|
|
|
func (a *PaychAPI) PaychVoucherAdd(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
2020-08-17 15:13:13 +00:00
|
|
|
return a.PaychMgr.AddVoucherInbound(ctx, ch, sv, proof, minDelta)
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// PaychVoucherCreate creates a new signed voucher on the given payment channel
|
|
|
|
// with the given lane and amount. The value passed in is exactly the value
|
|
|
|
// that will be used to create the voucher, so if previous vouchers exist, the
|
|
|
|
// actual additional value of this voucher will only be the difference between
|
|
|
|
// the two.
|
2020-09-01 14:33:44 +00:00
|
|
|
// If there are insufficient funds in the channel to create the voucher,
|
|
|
|
// returns a nil voucher and the shortfall.
|
|
|
|
func (a *PaychAPI) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*api.VoucherCreateResult, error) {
|
|
|
|
return a.PaychMgr.CreateVoucher(ctx, pch, paych.SignedVoucher{Amount: amt, Lane: lane})
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 21:09:22 +00:00
|
|
|
func (a *PaychAPI) PaychVoucherList(ctx context.Context, pch address.Address) ([]*paych.SignedVoucher, error) {
|
2019-09-09 13:59:07 +00:00
|
|
|
vi, err := a.PaychMgr.ListVouchers(ctx, pch)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-02-25 21:09:22 +00:00
|
|
|
out := make([]*paych.SignedVoucher, len(vi))
|
2019-09-09 13:59:07 +00:00
|
|
|
for k, v := range vi {
|
|
|
|
out[k] = v.Voucher
|
|
|
|
}
|
|
|
|
|
|
|
|
return out, nil
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|
|
|
|
|
2020-09-03 03:49:51 +00:00
|
|
|
func (a *PaychAPI) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *paych.SignedVoucher, secret []byte) (cid.Cid, error) {
|
|
|
|
return a.PaychMgr.SubmitVoucher(ctx, ch, sv, secret)
|
2019-08-20 16:48:33 +00:00
|
|
|
}
|