diff --git a/api/api.go b/api/api.go index f2b38f670..e14eed76c 100644 --- a/api/api.go +++ b/api/api.go @@ -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) } diff --git a/api/struct.go b/api/struct.go index 553586dc5..2dad2aecb 100644 --- a/api/struct.go +++ b/api/struct.go @@ -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) { diff --git a/chain/deals/client.go b/chain/deals/client.go index 42b454659..70fe26252 100644 --- a/chain/deals/client.go +++ b/chain/deals/client.go @@ -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{}) } diff --git a/chain/deals/handler_states.go b/chain/deals/handler_states.go index fc1b122c5..0b2314acc 100644 --- a/chain/deals/handler_states.go +++ b/chain/deals/handler_states.go @@ -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) } } diff --git a/cli/paych.go b/cli/paych.go index e79d14141..db5ab0b71 100644 --- a/cli/paych.go +++ b/cli/paych.go @@ -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 } diff --git a/lotuspond/front/src/Client.js b/lotuspond/front/src/Client.js index 698badada..8a4472ddd 100644 --- a/lotuspond/front/src/Client.js +++ b/lotuspond/front/src/Client.js @@ -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 diff --git a/lotuspond/front/src/FullNode.js b/lotuspond/front/src/FullNode.js index 59b23ff08..312e917db 100644 --- a/lotuspond/front/src/FullNode.js +++ b/lotuspond/front/src/FullNode.js @@ -132,7 +132,7 @@ class FullNode extends React.Component { extra = Verif: <
> } - return
+ return
Voucher Nonce:{voucher.Nonce} Lane:{voucher.Lane} Amt:{voucher.Amount} TL:{voucher.TimeLock} MinCl:{voucher.MinCloseHeight} {extra}
}) diff --git a/lotuspond/front/src/StorageNode.js b/lotuspond/front/src/StorageNode.js index a27295fb5..e2f2f86de 100644 --- a/lotuspond/front/src/StorageNode.js +++ b/lotuspond/front/src/StorageNode.js @@ -104,11 +104,11 @@ class StorageNode extends React.Component {
-
{this.state.statusCounts.map((c, i) => {sealCodes[i]}: {c} | )}
+
{this.state.statusCounts.map((c, i) => {sealCodes[i]}: {c} | )}
- {this.state.staged ? this.state.staged.map(s => ( -
{s.SectorID} {sealCodes[s.SealStatusCode]}
- )) :
} + {this.state.staged ? this.state.staged.map((s, i) => ( +
{s.SectorID} {sealCodes[s.SealStatusCode]}
+ )) :
}
diff --git a/node/impl/paych/paych.go b/node/impl/paych/paych.go index b3dd2fd4f..15c89befe 100644 --- a/node/impl/paych/paych.go +++ b/node/impl/paych/paych.go @@ -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) } diff --git a/paych/paych.go b/paych/paych.go index ed47357ee..d3b91b0e9 100644 --- a/paych/paych.go +++ b/paych/paych.go @@ -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) { diff --git a/paych/store.go b/paych/store.go index 9bd493dda..ad1286e72 100644 --- a/paych/store.go +++ b/paych/store.go @@ -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) { diff --git a/retrieval/miner.go b/retrieval/miner.go index 434ccfab3..ebbe1f093 100644 --- a/retrieval/miner.go +++ b/retrieval/miner.go @@ -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