retrieval: payment validation
This commit is contained in:
parent
0a853ac0e7
commit
9fe198dc6f
@ -120,7 +120,7 @@ type FullNode interface {
|
||||
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)
|
||||
PaychVoucherAdd(context.Context, address.Address, *types.SignedVoucher, []byte) error
|
||||
PaychVoucherAdd(context.Context, address.Address, *types.SignedVoucher, []byte, types.BigInt) (types.BigInt, error)
|
||||
PaychVoucherList(context.Context, address.Address) ([]*types.SignedVoucher, error)
|
||||
PaychVoucherSubmit(context.Context, address.Address, *types.SignedVoucher) (cid.Cid, error)
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ type FullNodeStruct struct {
|
||||
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) error `perm:"write"`
|
||||
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"`
|
||||
@ -330,8 +330,8 @@ func (c *FullNodeStruct) PaychVoucherCheckSpendable(ctx context.Context, addr ad
|
||||
return c.Internal.PaychVoucherCheckSpendable(ctx, addr, sv, secret, proof)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, addr address.Address, sv *types.SignedVoucher, proof []byte) error {
|
||||
return c.Internal.PaychVoucherAdd(ctx, addr, sv, proof)
|
||||
func (c *FullNodeStruct) PaychVoucherAdd(ctx context.Context, addr address.Address, sv *types.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||
return c.Internal.PaychVoucherAdd(ctx, addr, sv, proof, minDelta)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) PaychVoucherCreate(ctx context.Context, pch address.Address, amt types.BigInt, lane uint64) (*types.SignedVoucher, error) {
|
||||
|
@ -32,6 +32,7 @@ func init() {
|
||||
cbor.RegisterCborType(types.ModVerifyParams{})
|
||||
cbor.RegisterCborType(types.Signature{})
|
||||
cbor.RegisterCborType(actors.PaymentInfo{})
|
||||
cbor.RegisterCborType(api.PaymentInfo{})
|
||||
cbor.RegisterCborType(actors.InclusionProof{})
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,8 @@ func (h *Handler) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal),
|
||||
}
|
||||
|
||||
for i, voucher := range deal.Proposal.Payment.Vouchers {
|
||||
if err := h.full.PaychVoucherAdd(ctx, deal.Proposal.Payment.PayChActor, voucher, nil); err != nil {
|
||||
// TODO: Set correct minAmount
|
||||
if _, err := h.full.PaychVoucherAdd(ctx, deal.Proposal.Payment.PayChActor, voucher, nil, types.NewInt(0)); err != nil {
|
||||
return nil, xerrors.Errorf("consuming payment voucher %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
@ -240,7 +241,8 @@ func (h *Handler) sealing(ctx context.Context, deal MinerDeal) (func(*MinerDeal)
|
||||
// store proofs for channels
|
||||
for i, v := range deal.Proposal.Payment.Vouchers {
|
||||
if v.Extra.Method == actors.MAMethods.PaymentVerifyInclusion {
|
||||
if err := h.full.PaychVoucherAdd(ctx, deal.Proposal.Payment.PayChActor, v, proofB); err != nil {
|
||||
// TODO: Set correct minAmount
|
||||
if _, err := h.full.PaychVoucherAdd(ctx, deal.Proposal.Payment.PayChActor, v, proofB, types.NewInt(0)); err != nil {
|
||||
return nil, xerrors.Errorf("storing payment voucher %d proof: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ var paychVoucherAddCmd = &cli.Command{
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
// TODO: allow passing proof bytes
|
||||
if err := api.PaychVoucherAdd(ctx, ch, sv, nil); err != nil {
|
||||
if _, err := api.PaychVoucherAdd(ctx, ch, sv, nil, types.NewInt(0)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ class Client extends React.Component {
|
||||
Root: deal.PieceRef,
|
||||
Size: deal.Size,
|
||||
// TODO: support offset
|
||||
Total: "900",
|
||||
Total: String(deal.Size * 2),
|
||||
|
||||
Client: client,
|
||||
Miner: deal.Miner
|
||||
|
@ -132,7 +132,7 @@ class FullNode extends React.Component {
|
||||
extra = <span>Verif: <<b><Address nobalance={true} client={this.props.client} addr={voucher.Extra.Actor} method={voucher.Extra.Method} mountWindow={this.props.mountWindow}/></b>></span>
|
||||
}
|
||||
|
||||
return <div key={voucher.Nonce} className="FullNode-voucher">
|
||||
return <div key={`${addr} ${voucher.Lane} ${voucher.Nonce}`} className="FullNode-voucher">
|
||||
Voucher Nonce:<b>{voucher.Nonce}</b> Lane:<b>{voucher.Lane}</b> Amt:<b>{voucher.Amount}</b> TL:<b>{voucher.TimeLock}</b> MinCl:<b>{voucher.MinCloseHeight}</b> {extra}
|
||||
</div>
|
||||
})
|
||||
|
@ -104,11 +104,11 @@ class StorageNode extends React.Component {
|
||||
<div>
|
||||
<Address client={this.props.fullConn} addr={this.state.actor} mountWindow={this.props.mountWindow}/>
|
||||
</div>
|
||||
<div>{this.state.statusCounts.map((c, i) => <span>{sealCodes[i]}: {c} | </span>)}</div>
|
||||
<div>{this.state.statusCounts.map((c, i) => <span key={i}>{sealCodes[i]}: {c} | </span>)}</div>
|
||||
<div>
|
||||
{this.state.staged ? this.state.staged.map(s => (
|
||||
<div>{s.SectorID} {sealCodes[s.SealStatusCode]}</div>
|
||||
)) : <div></div>}
|
||||
{this.state.staged ? this.state.staged.map((s, i) => (
|
||||
<div key={i}>{s.SectorID} {sealCodes[s.SealStatusCode]}</div>
|
||||
)) : <div/>}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -134,14 +134,14 @@ func (a *PaychAPI) PaychVoucherCheckSpendable(ctx context.Context, ch address.Ad
|
||||
return a.PaychMgr.CheckVoucherSpendable(ctx, ch, sv, secret, proof)
|
||||
}
|
||||
|
||||
func (a *PaychAPI) PaychVoucherAdd(ctx context.Context, ch address.Address, sv *types.SignedVoucher, proof []byte) error {
|
||||
func (a *PaychAPI) PaychVoucherAdd(ctx context.Context, ch address.Address, sv *types.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||
_ = a.PaychMgr.TrackInboundChannel(ctx, ch) // TODO: expose those calls
|
||||
|
||||
if err := a.PaychVoucherCheckValid(ctx, ch, sv); err != nil {
|
||||
return err
|
||||
return types.NewInt(0), err
|
||||
}
|
||||
|
||||
return a.PaychMgr.AddVoucher(ctx, ch, sv, proof)
|
||||
return a.PaychMgr.AddVoucher(ctx, ch, sv, proof, minDelta)
|
||||
}
|
||||
|
||||
// PaychVoucherCreate creates a new signed voucher on the given payment channel
|
||||
@ -179,7 +179,7 @@ func (a *PaychAPI) paychVoucherCreate(ctx context.Context, pch address.Address,
|
||||
|
||||
sv.Signature = sig
|
||||
|
||||
if err := a.PaychMgr.AddVoucher(ctx, pch, sv, nil); err != nil {
|
||||
if _, err := a.PaychMgr.AddVoucher(ctx, pch, sv, nil, types.NewInt(0)); err != nil {
|
||||
return nil, xerrors.Errorf("failed to persist voucher: %w", err)
|
||||
}
|
||||
|
||||
|
@ -248,12 +248,12 @@ func (pm *Manager) getPaychOwner(ctx context.Context, ch address.Address) (addre
|
||||
return address.NewFromBytes(ret.Return)
|
||||
}
|
||||
|
||||
func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *types.SignedVoucher, proof []byte) error {
|
||||
func (pm *Manager) AddVoucher(ctx context.Context, ch address.Address, sv *types.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||
if err := pm.CheckVoucherValid(ctx, ch, sv); err != nil {
|
||||
return err
|
||||
return types.NewInt(0), err
|
||||
}
|
||||
|
||||
return pm.store.AddVoucher(ch, sv, proof)
|
||||
return pm.store.AddVoucher(ch, sv, proof, minDelta)
|
||||
}
|
||||
|
||||
func (pm *Manager) AllocateLane(ch address.Address) (uint64, error) {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -181,17 +182,24 @@ func (ps *Store) findChan(filter func(*ChannelInfo) bool) (address.Address, erro
|
||||
return address.Undef, nil
|
||||
}
|
||||
|
||||
func (ps *Store) AddVoucher(ch address.Address, sv *types.SignedVoucher, proof []byte) error {
|
||||
func (ps *Store) AddVoucher(ch address.Address, sv *types.SignedVoucher, proof []byte, minDelta types.BigInt) (types.BigInt, error) {
|
||||
ps.lk.Lock()
|
||||
defer ps.lk.Unlock()
|
||||
|
||||
ci, err := ps.getChannelInfo(ch)
|
||||
if err != nil {
|
||||
return err
|
||||
return types.NewInt(0), err
|
||||
}
|
||||
|
||||
var bestAmount types.BigInt
|
||||
var bestNonce uint64 = math.MaxUint64
|
||||
|
||||
// look for duplicates
|
||||
for i, v := range ci.Vouchers {
|
||||
if v.Voucher.Lane == sv.Lane && v.Voucher.Nonce + 1 > bestNonce + 1 {
|
||||
bestNonce = v.Voucher.Nonce
|
||||
bestAmount = v.Voucher.Amount
|
||||
}
|
||||
if !sv.Equals(v.Voucher) {
|
||||
continue
|
||||
}
|
||||
@ -201,7 +209,7 @@ func (ps *Store) AddVoucher(ch address.Address, sv *types.SignedVoucher, proof [
|
||||
break
|
||||
}
|
||||
log.Warnf("AddVoucher: voucher re-added with matching proof")
|
||||
return nil
|
||||
return types.NewInt(0), nil
|
||||
}
|
||||
|
||||
log.Warnf("AddVoucher: adding proof to stored voucher")
|
||||
@ -210,7 +218,16 @@ func (ps *Store) AddVoucher(ch address.Address, sv *types.SignedVoucher, proof [
|
||||
Proof: proof,
|
||||
}
|
||||
|
||||
return ps.putChannelInfo(ci)
|
||||
return types.NewInt(0), ps.putChannelInfo(ci)
|
||||
}
|
||||
|
||||
if bestAmount == (types.BigInt{}) {
|
||||
bestAmount = types.NewInt(0)
|
||||
}
|
||||
|
||||
delta := types.BigSub(sv.Amount, bestAmount)
|
||||
if types.BigCmp(minDelta, delta) > 0 {
|
||||
return delta, xerrors.Errorf("addVoucher: supplied token amount too low; minD=%s, D=%s; bestAmt=%s; v.Amt=%s", minDelta, delta, bestAmount, sv.Amount)
|
||||
}
|
||||
|
||||
ci.Vouchers = append(ci.Vouchers, &VoucherInfo{
|
||||
@ -222,7 +239,7 @@ func (ps *Store) AddVoucher(ch address.Address, sv *types.SignedVoucher, proof [
|
||||
ci.NextLane = sv.Lane + 1
|
||||
}
|
||||
|
||||
return ps.putChannelInfo(ci)
|
||||
return delta, ps.putChannelInfo(ci)
|
||||
}
|
||||
|
||||
func (ps *Store) AllocateLane(ch address.Address) (uint64, error) {
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/network"
|
||||
"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/types"
|
||||
"github.com/filecoin-project/go-lotus/lib/cborrpc"
|
||||
@ -19,14 +20,17 @@ import (
|
||||
|
||||
type Miner struct {
|
||||
sectorBlocks *sectorblocks.SectorBlocks
|
||||
full api.FullNode
|
||||
|
||||
pricePerByte types.BigInt
|
||||
// TODO: Unseal price
|
||||
}
|
||||
|
||||
func NewMiner(sblks *sectorblocks.SectorBlocks) *Miner {
|
||||
func NewMiner(sblks *sectorblocks.SectorBlocks, full api.FullNode) *Miner {
|
||||
return &Miner{
|
||||
sectorBlocks: sblks,
|
||||
full: full,
|
||||
|
||||
pricePerByte: types.NewInt(2), // TODO: allow setting
|
||||
}
|
||||
}
|
||||
@ -118,8 +122,10 @@ func (hnd *handlerDeal) handleNext() (bool, error) {
|
||||
|
||||
unixfs0 := deal.Params.Unixfs0
|
||||
|
||||
// TODO: Verify payment, check how much we can send based on that
|
||||
// Or reject (possibly returning the payment to retain reputation with the client)
|
||||
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 {
|
||||
return false, xerrors.Errorf("processing retrieval payment: %w", err)
|
||||
}
|
||||
|
||||
// If the file isn't open (new deal stream), isn't the right file, or isn't
|
||||
// at the right offset, (re)open it
|
||||
|
Loading…
Reference in New Issue
Block a user