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/peer"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/store"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
@ -122,7 +123,8 @@ type FullNode interface {
|
||||
PaychStatus(context.Context, address.Address) (*PaychStatus, error)
|
||||
PaychClose(context.Context, address.Address) (cid.Cid, 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
|
||||
PaychVoucherCheckSpendable(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error)
|
||||
PaychVoucherCreate(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, error)
|
||||
@ -229,7 +231,15 @@ type ChannelInfo struct {
|
||||
type PaymentInfo struct {
|
||||
Channel address.Address
|
||||
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 {
|
||||
|
@ -3,15 +3,15 @@ package api
|
||||
import (
|
||||
"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/peer"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/store"
|
||||
"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
|
||||
@ -86,19 +86,20 @@ type FullNodeStruct struct {
|
||||
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"`
|
||||
|
||||
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"`
|
||||
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
||||
PaychClose func(context.Context, address.Address) (cid.Cid, 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"`
|
||||
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
||||
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
|
||||
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, 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"`
|
||||
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"`
|
||||
PaychStatus func(context.Context, address.Address) (*PaychStatus, error) `perm:"read"`
|
||||
PaychClose func(context.Context, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||
PaychAllocateLane func(context.Context, address.Address) (uint64, error) `perm:"sign"`
|
||||
PaychNewPayment func(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error) `perm:"sign"`
|
||||
PaychLaneState func(ctx context.Context, ch address.Address, lane uint64) (actors.LaneState, error) `perm:"write"`
|
||||
PaychVoucherCheck func(context.Context, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckValid func(context.Context, address.Address, *types.SignedVoucher) error `perm:"read"`
|
||||
PaychVoucherCheckSpendable func(context.Context, address.Address, *types.SignedVoucher, []byte, []byte) (bool, error) `perm:"read"`
|
||||
PaychVoucherAdd func(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error) `perm:"write"`
|
||||
PaychVoucherCreate func(context.Context, address.Address, types.BigInt, uint64) (*types.SignedVoucher, 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)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychNewPayment(ctx context.Context, from, to address.Address, amount types.BigInt, extra *types.ModVerifyParams, tl uint64, minClose uint64) (*PaymentInfo, error) {
|
||||
return c.Internal.PaychNewPayment(ctx, from, to, amount, extra, tl, minClose)
|
||||
func (c *FullNodeStruct) PaychNewPayment(ctx context.Context, from, to address.Address, vouchers []VoucherSpec) (*PaymentInfo, error) {
|
||||
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) {
|
||||
|
@ -19,6 +19,11 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
|
||||
// Blocks
|
||||
const DealVoucherSkewLimit = 10
|
||||
|
||||
// Blocks
|
||||
const MinDealVoucherIncrement = ProvingPeriodDuration
|
||||
|
||||
const MaxVouchersPerDeal = 768 // roughly one voucher per 10h over a year
|
||||
|
||||
// /////
|
||||
// Consensus / Network
|
||||
|
||||
|
@ -3,16 +3,17 @@ package deals
|
||||
import (
|
||||
"bytes"
|
||||
"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"
|
||||
"github.com/ipfs/go-merkledag"
|
||||
unixfile "github.com/ipfs/go-unixfs/file"
|
||||
"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/address"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/filecoin-project/go-lotus/lib/sectorbuilder"
|
||||
"github.com/filecoin-project/go-lotus/storage/sectorblocks"
|
||||
@ -42,11 +43,25 @@ func (h *Handler) handle(ctx context.Context, deal MinerDeal, cb minerHandlerFun
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
maxClose := curHead.Height() + deal.Proposal.Duration + build.DealVoucherSkewLimit
|
||||
maxClose := curHead.Height() + (increments * uint64(i+1)) + build.DealVoucherSkewLimit
|
||||
if 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 {
|
||||
return xerrors.Errorf("validating payment voucher %d: didn't expect any merges", i)
|
||||
}
|
||||
|
||||
// TODO: make sure that current laneStatus.Amount == 0
|
||||
|
||||
if voucher.Amount.LessThan(deal.Proposal.TotalPrice) {
|
||||
return xerrors.Errorf("validating payment voucher %d: not enough funds in the voucher", i)
|
||||
if voucher.Amount.LessThan(vspec[i].Amount) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return xerrors.Errorf("validating payment voucher %d: minimum price: %s", i, minPrice)
|
||||
}
|
||||
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 {
|
||||
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
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
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 (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/filecoin-project/go-lotus/chain/actors"
|
||||
"github.com/filecoin-project/go-lotus/chain/types"
|
||||
"github.com/filecoin-project/go-lotus/chain/vm"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
|
@ -182,5 +182,4 @@ func (sm *StateManager) LoadActorState(ctx context.Context, a address.Address, o
|
||||
}
|
||||
|
||||
return act, nil
|
||||
|
||||
}
|
||||
|
@ -96,8 +96,9 @@ func (a *API) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.A
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@ -110,7 +111,7 @@ func (a *API) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.A
|
||||
PayChActor: payment.Channel,
|
||||
Payer: self,
|
||||
ChannelMessage: payment.ChannelMessage,
|
||||
Vouchers: []*types.SignedVoucher{payment.Voucher},
|
||||
Vouchers: payment.Vouchers,
|
||||
},
|
||||
MinerAddress: miner,
|
||||
ClientAddress: self,
|
||||
|
@ -42,8 +42,11 @@ func (a *PaychAPI) PaychAllocateLane(ctx context.Context, ch address.Address) (u
|
||||
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: validate voucher spec before locking funds
|
||||
ch, err := a.PaychGet(ctx, from, to, amount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -54,17 +57,24 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sv, err := a.paychVoucherCreate(ctx, ch.Channel, types.SignedVoucher{
|
||||
Amount: amount,
|
||||
Lane: lane,
|
||||
svs := make([]*types.SignedVoucher, len(vouchers))
|
||||
|
||||
Extra: extra,
|
||||
TimeLock: tl,
|
||||
MinCloseHeight: minClose,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for i, v := range vouchers {
|
||||
sv, err := a.paychVoucherCreate(ctx, ch.Channel, types.SignedVoucher{
|
||||
Amount: v.Amount,
|
||||
Lane: lane,
|
||||
|
||||
Extra: v.Extra,
|
||||
TimeLock: v.TimeLock,
|
||||
MinCloseHeight: v.MinClose,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
svs[i] = sv
|
||||
}
|
||||
|
||||
var pchCid *cid.Cid
|
||||
if ch.ChannelMessage != cid.Undef {
|
||||
pchCid = &ch.ChannelMessage
|
||||
@ -73,7 +83,7 @@ func (a *PaychAPI) PaychNewPayment(ctx context.Context, from, to address.Address
|
||||
return &api.PaymentInfo{
|
||||
Channel: ch.Channel,
|
||||
ChannelMessage: pchCid,
|
||||
Voucher: sv,
|
||||
Vouchers: svs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -126,6 +136,10 @@ func (a *PaychAPI) PaychClose(ctx context.Context, addr address.Address) (cid.Ci
|
||||
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 {
|
||||
return a.PaychMgr.CheckVoucherValid(ctx, ch, sv)
|
||||
}
|
||||
|
@ -221,16 +221,6 @@ func (pm *Manager) CheckVoucherSpendable(ctx context.Context, ch address.Address
|
||||
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) {
|
||||
ret, err := pm.sm.Call(ctx, &types.Message{
|
||||
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{
|
||||
Channel: cst.paych,
|
||||
ChannelMessage: nil,
|
||||
Voucher: sv,
|
||||
Vouchers: []*types.SignedVoucher{sv},
|
||||
}, nil
|
||||
}
|
||||
|
@ -122,8 +122,12 @@ func (hnd *handlerDeal) handleNext() (bool, error) {
|
||||
|
||||
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))
|
||||
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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user