Incremental deal payments
This commit is contained in:
parent
0ed035d0ff
commit
caa767e081
14
api/api.go
14
api/api.go
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/store"
|
"github.com/filecoin-project/go-lotus/chain/store"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
@ -122,7 +123,8 @@ type FullNode interface {
|
|||||||
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
|
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
|
||||||
PaychClose(context.Context, address.Address) (cid.Cid, error)
|
PaychClose(context.Context, address.Address) (cid.Cid, error)
|
||||||
PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error)
|
PaychAllocateLane(ctx context.Context, ch address.Address) (uint64, error)
|
||||||
PaychNewPayment(ctx context.Context, from, to address.Address, amount types.BigInt, extra *types.ModVerifyParams, tl uint64, minClose uint64) (*PaymentInfo, error)
|
PaychLaneState(ctx context.Context, ch address.Address, lane uint64) (actors.LaneState, error)
|
||||||
|
PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error)
|
||||||
PaychVoucherCheckValid(context.Context, address.Address, *types.SignedVoucher) error
|
PaychVoucherCheckValid(context.Context, address.Address, *types.SignedVoucher) error
|
||||||
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
|
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
|
||||||
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
|
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
|
||||||
@ -229,7 +231,15 @@ type ChannelInfo struct {
|
|||||||
type PaymentInfo struct {
|
type PaymentInfo struct {
|
||||||
Channel address.Address
|
Channel address.Address
|
||||||
ChannelMessage *cid.Cid
|
ChannelMessage *cid.Cid
|
||||||
Voucher *types.SignedVoucher
|
Vouchers []*types.SignedVoucher
|
||||||
|
}
|
||||||
|
|
||||||
|
type VoucherSpec struct {
|
||||||
|
Amount types.BigInt
|
||||||
|
TimeLock uint64
|
||||||
|
MinClose uint64
|
||||||
|
|
||||||
|
Extra *types.ModVerifyParams
|
||||||
}
|
}
|
||||||
|
|
||||||
type MinerPower struct {
|
type MinerPower struct {
|
||||||
|
@ -3,15 +3,15 @@ package api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
"github.com/libp2p/go-libp2p-core/network"
|
"github.com/libp2p/go-libp2p-core/network"
|
||||||
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/store"
|
"github.com/filecoin-project/go-lotus/chain/store"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// All permissions are listed in permissioned.go
|
// All permissions are listed in permissioned.go
|
||||||
@ -86,19 +86,20 @@ type FullNodeStruct struct {
|
|||||||
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
|
StateGetActor func(context.Context, address.Address, *types.TipSet) (*types.Actor, error) `perm:"read"`
|
||||||
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
|
StateReadState func(context.Context, *types.Actor, *types.TipSet) (*ActorState, error) `perm:"read"`
|
||||||
|
|
||||||
PaychGet func(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error) `perm:"sign"`
|
PaychGet func(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error) `perm:"sign"`
|
||||||
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
|
PaychList func(context.Context) ([]address.Address, error) `perm:"read"`
|
||||||
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
||||||
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
|
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||||
PaychAllocateLane func(context.Context, address.Address) (uint64, error) `perm:"sign"`
|
PaychAllocateLane func(context.Context, address.Address) (uint64, error) `perm:"sign"`
|
||||||
PaychNewPayment func(ctx context.Context, from, to address.Address, amount types.BigInt, extra *types.ModVerifyParams, tl uint64, minClose uint64) (*PaymentInfo, error) `perm:"sign"`
|
PaychNewPayment func(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error) `perm:"sign"`
|
||||||
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
PaychLaneState func(ctx context.Context, ch address.Address, lane uint64) (actors.LaneState, error) `perm:"write"`
|
||||||
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
||||||
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
||||||
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
|
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
||||||
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
|
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
|
||||||
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
|
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error) `perm:"sign"`
|
||||||
PaychVoucherSubmit func(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error) `perm:"sign"`
|
PaychVoucherList func(context.Context, address.Address) ([]*types.SignedVoucher, error) `perm:"write"`
|
||||||
|
PaychVoucherSubmit func(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error) `perm:"sign"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,8 +364,12 @@ func (c *FullNodeStruct) PaychAllocateLane(ctx context.Context, ch address.Addre
|
|||||||
return c.Internal.PaychAllocateLane(ctx, ch)
|
return c.Internal.PaychAllocateLane(ctx, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) PaychNewPayment(ctx context.Context, from, to address.Address, amount types.BigInt, extra *types.ModVerifyParams, tl uint64, minClose uint64) (*PaymentInfo, error) {
|
func (c *FullNodeStruct) PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error) {
|
||||||
return c.Internal.PaychNewPayment(ctx, from, to, amount, extra, tl, minClose)
|
return c.Internal.PaychNewPayment(ctx, from, to, vouchers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) PaychLaneState(ctx context.Context, ch address.Address, lane uint64) (actors.LaneState, error) {
|
||||||
|
return c.Internal.PaychLaneState(ctx, ch, lane)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *types.SignedVoucher) (cid.Cid, error) {
|
func (c *FullNodeStruct) PaychVoucherSubmit(ctx context.Context, ch address.Address, sv *types.SignedVoucher) (cid.Cid, error) {
|
||||||
|
@ -19,6 +19,11 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
|
|||||||
// Blocks
|
// Blocks
|
||||||
const DealVoucherSkewLimit = 10
|
const DealVoucherSkewLimit = 10
|
||||||
|
|
||||||
|
// Blocks
|
||||||
|
const MinDealVoucherIncrement = ProvingPeriodDuration
|
||||||
|
|
||||||
|
const MaxVouchersPerDeal = 768 // roughly one voucher per 10h over a year
|
||||||
|
|
||||||
// /////
|
// /////
|
||||||
// Consensus / Network
|
// Consensus / Network
|
||||||
|
|
||||||
|
@ -3,16 +3,17 @@ package deals
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"github.com/filecoin-project/go-lotus/api"
|
|
||||||
"github.com/filecoin-project/go-lotus/build"
|
|
||||||
"github.com/filecoin-project/go-sectorbuilder/sealing_state"
|
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-sectorbuilder/sealing_state"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
"github.com/ipfs/go-merkledag"
|
"github.com/ipfs/go-merkledag"
|
||||||
unixfile "github.com/ipfs/go-unixfs/file"
|
unixfile "github.com/ipfs/go-unixfs/file"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/api"
|
||||||
|
"github.com/filecoin-project/go-lotus/build"
|
||||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
"github.com/filecoin-project/go-lotus/lib/sectorbuilder"
|
"github.com/filecoin-project/go-lotus/lib/sectorbuilder"
|
||||||
"github.com/filecoin-project/go-lotus/storage/sectorblocks"
|
"github.com/filecoin-project/go-lotus/storage/sectorblocks"
|
||||||
@ -42,11 +43,25 @@ func (h *Handler) handle(ctx context.Context, deal MinerDeal, cb minerHandlerFun
|
|||||||
|
|
||||||
// ACCEPTED
|
// ACCEPTED
|
||||||
|
|
||||||
func (h *Handler) validateVouchers(ctx context.Context, deal MinerDeal) error {
|
func (h *Handler) validateVouchers(ctx context.Context, deal MinerDeal, paych address.Address) error {
|
||||||
curHead, err := h.full.ChainHead(ctx)
|
curHead, err := h.full.ChainHead(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(deal.Proposal.Payment.Vouchers) == 0 {
|
||||||
|
return xerrors.Errorf("no payment vouchers for deal")
|
||||||
|
}
|
||||||
|
|
||||||
|
increments := deal.Proposal.Duration / uint64(len(deal.Proposal.Payment.Vouchers))
|
||||||
|
|
||||||
|
startH := deal.Proposal.Payment.Vouchers[0].TimeLock - (deal.Proposal.Duration / increments)
|
||||||
|
if startH > curHead.Height()+build.DealVoucherSkewLimit {
|
||||||
|
return xerrors.Errorf("deal starts too far into the future")
|
||||||
|
}
|
||||||
|
|
||||||
|
vspec := VoucherSpec(deal.Proposal.Duration, deal.Proposal.TotalPrice, startH, nil)
|
||||||
|
|
||||||
|
lane := deal.Proposal.Payment.Vouchers[0].Lane
|
||||||
|
|
||||||
for i, voucher := range deal.Proposal.Payment.Vouchers {
|
for i, voucher := range deal.Proposal.Payment.Vouchers {
|
||||||
err := h.full.PaychVoucherCheckValid(ctx, deal.Proposal.Payment.PayChActor, voucher)
|
err := h.full.PaychVoucherCheckValid(ctx, deal.Proposal.Payment.PayChActor, voucher)
|
||||||
@ -76,7 +91,7 @@ func (h *Handler) validateVouchers(ctx context.Context, deal MinerDeal) error {
|
|||||||
return xerrors.Errorf("validating payment voucher %d: paych challenge commP didn't match deal proposal", i)
|
return xerrors.Errorf("validating payment voucher %d: paych challenge commP didn't match deal proposal", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
maxClose := curHead.Height() + deal.Proposal.Duration + build.DealVoucherSkewLimit
|
maxClose := curHead.Height() + (increments * uint64(i+1)) + build.DealVoucherSkewLimit
|
||||||
if voucher.MinCloseHeight > maxClose {
|
if voucher.MinCloseHeight > maxClose {
|
||||||
return xerrors.Errorf("validating payment voucher %d: MinCloseHeight too high (%d), max expected: %d", i, voucher.MinCloseHeight, maxClose)
|
return xerrors.Errorf("validating payment voucher %d: MinCloseHeight too high (%d), max expected: %d", i, voucher.MinCloseHeight, maxClose)
|
||||||
}
|
}
|
||||||
@ -88,17 +103,33 @@ func (h *Handler) validateVouchers(ctx context.Context, deal MinerDeal) error {
|
|||||||
if len(voucher.Merges) > 0 {
|
if len(voucher.Merges) > 0 {
|
||||||
return xerrors.Errorf("validating payment voucher %d: didn't expect any merges", i)
|
return xerrors.Errorf("validating payment voucher %d: didn't expect any merges", i)
|
||||||
}
|
}
|
||||||
|
if voucher.Amount.LessThan(vspec[i].Amount) {
|
||||||
// TODO: make sure that current laneStatus.Amount == 0
|
return xerrors.Errorf("validating payment voucher %d: not enough funds in the voucher: %s < %s; vl=%d vsl=%d", i, voucher.Amount, vspec[i].Amount, len(deal.Proposal.Payment.Vouchers), len(vspec))
|
||||||
|
|
||||||
if voucher.Amount.LessThan(deal.Proposal.TotalPrice) {
|
|
||||||
return xerrors.Errorf("validating payment voucher %d: not enough funds in the voucher", i)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
minPrice := types.BigMul(types.BigMul(h.pricePerByteBlock, types.NewInt(deal.Proposal.Size)), types.NewInt(deal.Proposal.Duration))
|
minPrice := types.BigMul(types.BigMul(h.pricePerByteBlock, types.NewInt(deal.Proposal.Size)), types.NewInt(deal.Proposal.Duration))
|
||||||
if types.BigCmp(minPrice, deal.Proposal.TotalPrice) > 0 {
|
if types.BigCmp(minPrice, deal.Proposal.TotalPrice) > 0 {
|
||||||
return xerrors.Errorf("validating payment voucher %d: minimum price: %s", i, minPrice)
|
return xerrors.Errorf("minimum price: %s", minPrice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This is mildly racy, we need a way to check lane and submit voucher
|
||||||
|
// atomically
|
||||||
|
laneState, err := h.full.PaychLaneState(ctx, paych, lane)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("looking up payment channel lane: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if laneState.Closed {
|
||||||
|
return xerrors.New("lane closed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if laneState.Redeemed.GreaterThan(types.NewInt(0)) {
|
||||||
|
return xerrors.New("used lanes unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
if laneState.Nonce > 0 {
|
||||||
|
return xerrors.New("used lanes unsupported")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -120,7 +151,7 @@ func (h *Handler) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.validateVouchers(ctx, deal); err != nil {
|
if err := h.validateVouchers(ctx, deal, deal.Proposal.Payment.PayChActor); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
chain/deals/vouchers.go
Normal file
31
chain/deals/vouchers.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package deals
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/filecoin-project/go-lotus/api"
|
||||||
|
"github.com/filecoin-project/go-lotus/build"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func VoucherSpec(blocksDuration uint64, price types.BigInt, start uint64, extra *types.ModVerifyParams) []api.VoucherSpec {
|
||||||
|
nVouchers := blocksDuration / build.MinDealVoucherIncrement
|
||||||
|
if nVouchers < 1 {
|
||||||
|
nVouchers = 1
|
||||||
|
}
|
||||||
|
if nVouchers > build.MaxVouchersPerDeal {
|
||||||
|
nVouchers = build.MaxVouchersPerDeal
|
||||||
|
}
|
||||||
|
|
||||||
|
hIncrements := blocksDuration / nVouchers
|
||||||
|
vouchers := make([]api.VoucherSpec, nVouchers)
|
||||||
|
|
||||||
|
for i := uint64(0); i < nVouchers; i++ {
|
||||||
|
vouchers[i] = api.VoucherSpec{
|
||||||
|
Amount: types.BigDiv(types.BigMul(price, types.NewInt(i+1)), types.NewInt(nVouchers)),
|
||||||
|
TimeLock: start + (hIncrements * (i + 1)),
|
||||||
|
MinClose: start + (hIncrements * (i + 1)),
|
||||||
|
Extra: extra,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vouchers
|
||||||
|
}
|
@ -3,12 +3,11 @@ package stmgr
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
"github.com/filecoin-project/go-lotus/chain/vm"
|
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||||
|
|
||||||
cid "github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -182,5 +182,4 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
return act, nil
|
return act, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,9 @@ func (a *API) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.A
|
|||||||
}
|
}
|
||||||
|
|
||||||
head := a.Chain.GetHeaviestTipSet()
|
head := a.Chain.GetHeaviestTipSet()
|
||||||
|
vouchers := deals.VoucherSpec(blocksDuration, total, head.Height(), extra)
|
||||||
|
|
||||||
payment, err := a.PaychNewPayment(ctx, self, miner, total, extra, head.Height()+blocksDuration, head.Height()+blocksDuration)
|
payment, err := a.PaychNewPayment(ctx, self, miner, vouchers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -110,7 +111,7 @@ func (a *API) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.A
|
|||||||
PayChActor: payment.Channel,
|
PayChActor: payment.Channel,
|
||||||
Payer: self,
|
Payer: self,
|
||||||
ChannelMessage: payment.ChannelMessage,
|
ChannelMessage: payment.ChannelMessage,
|
||||||
Vouchers: []*types.SignedVoucher{payment.Voucher},
|
Vouchers: payment.Vouchers,
|
||||||
},
|
},
|
||||||
MinerAddress: miner,
|
MinerAddress: miner,
|
||||||
ClientAddress: self,
|
ClientAddress: self,
|
||||||
|
@ -42,8 +42,11 @@ func (a *PaychAPI) PaychAllocateLane(ctx context.Context, ch address.Address) (u
|
|||||||
return a.PaychMgr.AllocateLane(ch)
|
return a.PaychMgr.AllocateLane(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address, amount types.BigInt, extra *types.ModVerifyParams, tl uint64, minClose uint64) (*api.PaymentInfo, error) {
|
func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []api.VoucherSpec) (*api.PaymentInfo, error) {
|
||||||
|
amount := vouchers[len(vouchers)-1].Amount
|
||||||
|
|
||||||
// TODO: Fix free fund tracking in PaychGet
|
// TODO: Fix free fund tracking in PaychGet
|
||||||
|
// TODO: validate voucher spec before locking funds
|
||||||
ch, err := a.PaychGet(ctx, from, to, amount)
|
ch, err := a.PaychGet(ctx, from, to, amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -54,17 +57,24 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sv, err := a.paychVoucherCreate(ctx, ch.Channel, types.SignedVoucher{
|
svs := make([]*types.SignedVoucher, len(vouchers))
|
||||||
Amount: amount,
|
|
||||||
Lane: lane,
|
|
||||||
|
|
||||||
Extra: extra,
|
for i, v := range vouchers {
|
||||||
TimeLock: tl,
|
sv, err := a.paychVoucherCreate(ctx, ch.Channel, types.SignedVoucher{
|
||||||
MinCloseHeight: minClose,
|
Amount: v.Amount,
|
||||||
})
|
Lane: lane,
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
Extra: v.Extra,
|
||||||
|
TimeLock: v.TimeLock,
|
||||||
|
MinCloseHeight: v.MinClose,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
svs[i] = sv
|
||||||
}
|
}
|
||||||
|
|
||||||
var pchCid *cid.Cid
|
var pchCid *cid.Cid
|
||||||
if ch.ChannelMessage != cid.Undef {
|
if ch.ChannelMessage != cid.Undef {
|
||||||
pchCid = &ch.ChannelMessage
|
pchCid = &ch.ChannelMessage
|
||||||
@ -73,7 +83,7 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
|
|||||||
return &api.PaymentInfo{
|
return &api.PaymentInfo{
|
||||||
Channel: ch.Channel,
|
Channel: ch.Channel,
|
||||||
ChannelMessage: pchCid,
|
ChannelMessage: pchCid,
|
||||||
Voucher: sv,
|
Vouchers: svs,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +136,10 @@ func (a *PaychAPI) PaychClose(ctx context.Context, addr address.Address) (cid.Ci
|
|||||||
return smsg.Cid(), nil
|
return smsg.Cid(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *PaychAPI) PaychLaneState(ctx context.Context, ch address.Address, lane uint64) (actors.LaneState, error) {
|
||||||
|
return a.PaychMgr.LaneState(ctx, ch, lane)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *PaychAPI) PaychVoucherCheckValid(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
func (a *PaychAPI) PaychVoucherCheckValid(ctx context.Context, ch address.Address, sv *types.SignedVoucher) error {
|
||||||
return a.PaychMgr.CheckVoucherValid(ctx, ch, sv)
|
return a.PaychMgr.CheckVoucherValid(ctx, ch, sv)
|
||||||
}
|
}
|
||||||
|
@ -221,16 +221,6 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*types.Actor, *actors.PaymentChannelActorState, error) {
|
|
||||||
var pcast actors.PaymentChannelActorState
|
|
||||||
act, err := pm.sm.LoadActorState(ctx, ch, &pcast, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return act, &pcast, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) {
|
func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (address.Address, error) {
|
||||||
ret, err := pm.sm.Call(ctx, &types.Message{
|
ret, err := pm.sm.Call(ctx, &types.Message{
|
||||||
From: ch,
|
From: ch,
|
||||||
|
72
paych/state.go
Normal file
72
paych/state.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package paych
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
|
"github.com/filecoin-project/go-lotus/chain/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (pm *Manager) loadPaychState(ctx context.Context, ch address.Address) (*types.Actor, *actors.PaymentChannelActorState, error) {
|
||||||
|
var pcast actors.PaymentChannelActorState
|
||||||
|
act, err := pm.sm.LoadActorState(ctx, ch, &pcast, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return act, &pcast, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pm *Manager) LaneState(ctx context.Context, ch address.Address, lane uint64) (actors.LaneState, error) {
|
||||||
|
_, state, err := pm.loadPaychState(ctx, ch)
|
||||||
|
if err != nil {
|
||||||
|
return actors.LaneState{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: we probably want to call UpdateChannelState with all vouchers to be fully correct
|
||||||
|
// (but technically dont't need to)
|
||||||
|
// TODO: make sure this is correct
|
||||||
|
|
||||||
|
ls, ok := state.LaneStates[fmt.Sprintf("%d", lane)]
|
||||||
|
if !ok {
|
||||||
|
ls = &actors.LaneState{
|
||||||
|
Closed: false,
|
||||||
|
Redeemed: types.NewInt(0),
|
||||||
|
Nonce: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ls.Closed {
|
||||||
|
return actors.LaneState{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vouchers, err := pm.store.VouchersForPaych(ch)
|
||||||
|
if err != nil {
|
||||||
|
if err == ErrChannelNotTracked {
|
||||||
|
return *ls, nil
|
||||||
|
}
|
||||||
|
return actors.LaneState{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range vouchers {
|
||||||
|
for range v.Voucher.Merges {
|
||||||
|
panic("merges todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Voucher.Lane != lane {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Voucher.Nonce < ls.Nonce {
|
||||||
|
log.Warnf("Found outdated voucher: ch=%s, lane=%d, v.nonce=%d lane.nonce=%d", ch, lane, v.Voucher.Nonce, ls.Nonce)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ls.Nonce = v.Voucher.Nonce
|
||||||
|
ls.Redeemed = v.Voucher.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
return *ls, nil
|
||||||
|
}
|
@ -272,6 +272,6 @@ func (cst *clientStream) setupPayment(ctx context.Context, toSend types.BigInt)
|
|||||||
return api.PaymentInfo{
|
return api.PaymentInfo{
|
||||||
Channel: cst.paych,
|
Channel: cst.paych,
|
||||||
ChannelMessage: nil,
|
ChannelMessage: nil,
|
||||||
Voucher: sv,
|
Vouchers: []*types.SignedVoucher{sv},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -122,8 +122,12 @@ func (hnd *handlerDeal) handleNext() (bool, error) {
|
|||||||
|
|
||||||
unixfs0 := deal.Params.Unixfs0
|
unixfs0 := deal.Params.Unixfs0
|
||||||
|
|
||||||
|
if len(deal.Payment.Vouchers) != 1 {
|
||||||
|
return false, xerrors.Errorf("expected one signed voucher, got %d", len(deal.Payment.Vouchers))
|
||||||
|
}
|
||||||
|
|
||||||
expPayment := types.BigMul(hnd.m.pricePerByte, types.NewInt(deal.Params.Unixfs0.Size))
|
expPayment := types.BigMul(hnd.m.pricePerByte, types.NewInt(deal.Params.Unixfs0.Size))
|
||||||
if _, err := hnd.m.full.PaychVoucherAdd(context.TODO(), deal.Payment.Channel, deal.Payment.Voucher, nil, expPayment); err != nil {
|
if _, err := hnd.m.full.PaychVoucherAdd(context.TODO(), deal.Payment.Channel, deal.Payment.Vouchers[0], nil, expPayment); err != nil {
|
||||||
return false, xerrors.Errorf("processing retrieval payment: %w", err)
|
return false, xerrors.Errorf("processing retrieval payment: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user