retrieval: payment validation

This commit is contained in:
Łukasz Magiera 2019-09-16 23:25:23 +02:00
parent 0a853ac0e7
commit 9fe198dc6f
12 changed files with 54 additions and 28 deletions

View File

@ -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)
}

View File

@ -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) {

View File

@ -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{})
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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

View File

@ -132,7 +132,7 @@ class FullNode extends React.Component {
extra = <span>Verif: &lt;<b><Address nobalance={true} client={this.props.client} addr={voucher.Extra.Actor} method={voucher.Extra.Method} mountWindow={this.props.mountWindow}/></b>&gt;</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>
})

View File

@ -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>

View File

@ -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)
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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