on chain deals: Fix build

This commit is contained in:
Łukasz Magiera 2019-10-22 12:09:36 +02:00
parent 46a0333c9c
commit 99ef51a642
12 changed files with 66 additions and 266 deletions

View File

@ -134,7 +134,7 @@ type FullNode interface {
StateWaitMsg(context.Context, cid.Cid) (*MsgWait, error)
StateListMiners(context.Context, *types.TipSet) ([]address.Address, error)
StateListActors(context.Context, *types.TipSet) ([]address.Address, error)
StateMarketBalance(context.Context, address.Address) (actors.StorageParticipantBalance, error)
StateMarketBalance(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, error)
PaychGet(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error)
PaychList(context.Context) ([]address.Address, error)
@ -199,10 +199,9 @@ type Import struct {
type DealInfo struct {
ProposalCid cid.Cid
State DealState
Miner address.Address
Provider address.Address
PieceRef cid.Cid
CommP []byte
PieceRef []byte // cid bytes
Size uint64
TotalPrice types.BigInt

View File

@ -2,6 +2,7 @@ package api
import (
"context"
"github.com/filecoin-project/lotus/chain/actors"
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
"github.com/ipfs/go-cid"
@ -85,20 +86,21 @@ type FullNodeStruct struct {
ClientRetrieve func(ctx context.Context, order RetrievalOrder, path string) error `perm:"admin"`
ClientQueryAsk func(ctx context.Context, p peer.ID, miner address.Address) (*types.SignedStorageAsk, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"`
StateMinerProvingPeriodEnd func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, 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"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateMinerSectors func(context.Context, address.Address) ([]*SectorInfo, error) `perm:"read"`
StateMinerProvingSet func(context.Context, address.Address, *types.TipSet) ([]*SectorInfo, error) `perm:"read"`
StateMinerPower func(context.Context, address.Address, *types.TipSet) (MinerPower, error) `perm:"read"`
StateMinerWorker func(context.Context, address.Address, *types.TipSet) (address.Address, error) `perm:"read"`
StateMinerPeerID func(ctx context.Context, m address.Address, ts *types.TipSet) (peer.ID, error) `perm:"read"`
StateMinerProvingPeriodEnd func(ctx context.Context, actor address.Address, ts *types.TipSet) (uint64, error) `perm:"read"`
StateCall func(context.Context, *types.Message, *types.TipSet) (*types.MessageReceipt, error) `perm:"read"`
StateReplay func(context.Context, *types.TipSet, cid.Cid) (*ReplayResults, 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"`
StatePledgeCollateral func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
StateWaitMsg func(context.Context, cid.Cid) (*MsgWait, error) `perm:"read"`
StateListMiners func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateListActors func(context.Context, *types.TipSet) ([]address.Address, error) `perm:"read"`
StateMarketBalance func(context.Context, address.Address, *types.TipSet) (actors.StorageParticipantBalance, 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"`
@ -388,6 +390,10 @@ func (c *FullNodeStruct) StateListActors(ctx context.Context, ts *types.TipSet)
return c.Internal.StateListActors(ctx, ts)
}
func (c *FullNodeStruct) StateMarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (actors.StorageParticipantBalance, error) {
return c.Internal.StateMarketBalance(ctx, addr, ts)
}
func (c *FullNodeStruct) PaychGet(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*ChannelInfo, error) {
return c.Internal.PaychGet(ctx, from, to, ensureFunds)
}

View File

@ -9,11 +9,11 @@ import (
type DealState int
const (
DealUnknown = DealState(iota)
DealUnknown = DealState(iota)
DealRejected // Provider didn't like the proposal
DealAccepted // Proposal accepted, data moved
DealStaged // Data put into the sector
DealSealing // Data in process of being sealed
DealStaged // Data put into the sector
DealSealing // Data in process of being sealed
DealFailed

View File

@ -24,4 +24,5 @@ func SignWith(ctx context.Context, signer Signer, addr address.Address, signable
return err
}
}
return nil
}

View File

@ -143,7 +143,7 @@ func (sma StorageMarketActor) WithdrawBalance(act *types.Actor, vmctx types.VMCo
return nil, err
}
b, bnd, err := getMarketBalances(vmctx, self.Balances, []address.Address{vmctx.Message().From})
b, bnd, err := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, vmctx.Message().From)
if err != nil {
return nil, aerrors.Wrap(err, "could not get balance")
}
@ -185,7 +185,7 @@ func (sma StorageMarketActor) AddBalance(act *types.Actor, vmctx types.VMContext
return nil, err
}
b, bnd, err := getMarketBalances(vmctx, self.Balances, []address.Address{vmctx.Message().From})
b, bnd, err := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, vmctx.Message().From)
if err != nil {
return nil, aerrors.Wrap(err, "could not get balance")
}
@ -228,8 +228,8 @@ func setMarketBalances(vmctx types.VMContext, nd *hamt.Node, set map[address.Add
return c, nil
}
func getMarketBalances(vmctx types.VMContext, rcid cid.Cid, addrs []address.Address) ([]StorageParticipantBalance, *hamt.Node, ActorError) {
nd, err := hamt.LoadNode(vmctx.Context(), vmctx.Ipld(), rcid)
func GetMarketBalances(ctx context.Context, store *hamt.CborIpldStore, rcid cid.Cid, addrs ...address.Address) ([]StorageParticipantBalance, *hamt.Node, ActorError) {
nd, err := hamt.LoadNode(ctx, store, rcid)
if err != nil {
return nil, nil, aerrors.HandleExternalError(err, "failed to load miner set")
}
@ -238,7 +238,7 @@ func getMarketBalances(vmctx types.VMContext, rcid cid.Cid, addrs []address.Addr
for i, a := range addrs {
var balance StorageParticipantBalance
err = nd.Find(vmctx.Context(), string(a.Bytes()), &balance)
err = nd.Find(ctx, string(a.Bytes()), &balance)
switch err {
case hamt.ErrNotFound:
out[i] = StorageParticipantBalance{
@ -336,12 +336,6 @@ func (self *StorageMarketState) validateDeal(vmctx types.VMContext, deal Storage
if vmctx.BlockHeight() >= deal.Proposal.ProposalExpiration {
return aerrors.New(1, "deal proposal already expired")
}
if vmctx.BlockHeight() >= deal.Proposal.DealExpiration {
return aerrors.New(2, "deal proposal already expired")
}
if deal.Proposal.ProposalExpiration > deal.Proposal.DealExpiration {
return aerrors.New(3, "ProposalExpiration > DealExpiration")
}
var proposalBuf bytes.Buffer
err := deal.Proposal.MarshalCBOR(&proposalBuf)
@ -373,10 +367,7 @@ func (self *StorageMarketState) validateDeal(vmctx types.VMContext, deal Storage
// TODO: REVIEW: Do we want to check if provider exists in the power actor?
// TODO: do some caching (changes gas so needs to be in spec too)
b, bnd, aerr := getMarketBalances(vmctx, self.Balances, []address.Address{
deal.Proposal.Client,
deal.Proposal.Provider,
})
b, bnd, aerr := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, deal.Proposal.Client, deal.Proposal.Provider)
if aerr != nil {
return aerrors.Wrap(aerr, "getting client, and provider balances")
}
@ -518,17 +509,11 @@ func (sma StorageMarketActor) ProcessStorageDealsPayment(act *types.Actor, vmctx
return nil, nil
}
// TODO: clients probably want this to be fixed
dealDuration := dealInfo.Deal.Proposal.DealExpiration - dealInfo.ActivationEpoch
// todo: check math (written on a plane, also tired)
// TODO: division is hard, this more than likely has some off-by-one issue
toPay := types.BigDiv(types.BigMul(dealInfo.Deal.Proposal.StoragePrice, types.NewInt(build.ProvingPeriodDuration)), types.NewInt(dealDuration))
toPay := types.BigDiv(types.BigMul(dealInfo.Deal.Proposal.StoragePrice, types.NewInt(build.ProvingPeriodDuration)), types.NewInt(dealInfo.Deal.Proposal.Duration))
b, bnd, err := getMarketBalances(vmctx, self.Balances, []address.Address{
dealInfo.Deal.Proposal.Client,
dealInfo.Deal.Proposal.Provider,
})
b, bnd, err := GetMarketBalances(vmctx.Context(), vmctx.Ipld(), self.Balances, dealInfo.Deal.Proposal.Client, dealInfo.Deal.Proposal.Provider)
clientBal := b[0]
providerBal := b[1]

View File

@ -792,143 +792,6 @@ func (t *SubmitPoStParams) UnmarshalCBOR(r io.Reader) error {
return nil
}
func (t *PieceInclVoucherData) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{130}); err != nil {
return err
}
// t.t.CommP ([]uint8)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.CommP)))); err != nil {
return err
}
if _, err := w.Write(t.CommP); err != nil {
return err
}
// t.t.PieceSize (types.BigInt)
if err := t.PieceSize.MarshalCBOR(w); err != nil {
return err
}
return nil
}
func (t *PieceInclVoucherData) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 2 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.t.CommP ([]uint8)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.CommP: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.CommP = make([]byte, extra)
if _, err := io.ReadFull(br, t.CommP); err != nil {
return err
}
// t.t.PieceSize (types.BigInt)
{
if err := t.PieceSize.UnmarshalCBOR(br); err != nil {
return err
}
}
return nil
}
func (t *InclusionProof) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
return err
}
if _, err := w.Write([]byte{130}); err != nil {
return err
}
// t.t.Sector (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.Sector)); err != nil {
return err
}
// t.t.Proof ([]uint8)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Proof)))); err != nil {
return err
}
if _, err := w.Write(t.Proof); err != nil {
return err
}
return nil
}
func (t *InclusionProof) UnmarshalCBOR(r io.Reader) error {
br := cbg.GetPeeker(r)
maj, extra, err := cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajArray {
return fmt.Errorf("cbor input should be of type array")
}
if extra != 2 {
return fmt.Errorf("cbor input had wrong number of fields")
}
// t.t.Sector (uint64)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.Sector = extra
// t.t.Proof ([]uint8)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Proof: array too large (%d)", extra)
}
if maj != cbg.MajByteString {
return fmt.Errorf("expected byte array")
}
t.Proof = make([]byte, extra)
if _, err := io.ReadFull(br, t.Proof); err != nil {
return err
}
return nil
}
func (t *PaymentVerifyParams) MarshalCBOR(w io.Writer) error {
if t == nil {
_, err := w.Write(cbg.CborNull)
@ -3087,9 +2950,6 @@ func (t *StorageDealProposal) MarshalCBOR(w io.Writer) error {
}
// t.t.DealExpiration (uint64)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, t.DealExpiration)); err != nil {
return err
}
// t.t.StoragePrice (types.BigInt)
if err := t.StoragePrice.MarshalCBOR(w); err != nil {
@ -3187,7 +3047,6 @@ func (t *StorageDealProposal) UnmarshalCBOR(r io.Reader) error {
if maj != cbg.MajUnsignedInt {
return fmt.Errorf("wrong type for uint64 field")
}
t.DealExpiration = extra
// t.t.StoragePrice (types.BigInt)
{

View File

@ -46,7 +46,7 @@ type ClientDeal struct {
type Client struct {
sm *stmgr.StateManager
chain *store.ChainStore
chain *store.ChainStore
h host.Host
w *wallet.Wallet
dag dtypes.ClientDAG
@ -71,7 +71,7 @@ type clientDealUpdate struct {
func NewClient(sm *stmgr.StateManager, chain *store.ChainStore, h host.Host, w *wallet.Wallet, ds dtypes.MetadataDS, dag dtypes.ClientDAG, discovery *discovery.Local) *Client {
c := &Client{
sm: sm,
chain: chain,
chain: chain,
h: h,
w: w,
dag: dag,

View File

@ -78,7 +78,7 @@ func (p *Provider) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal)
// TODO: check StorageCollateral / StoragePrice
// check market funds
clientMarketBalance, err := p.full.StateMarketBalance(ctx, deal.Proposal.Client)
clientMarketBalance, err := p.full.StateMarketBalance(ctx, deal.Proposal.Client, nil)
if err != nil {
return nil, err
}
@ -89,7 +89,7 @@ func (p *Provider) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal)
return nil, xerrors.New("clientMarketBalance.Available too small")
}
providerMarketBalance, err := p.full.StateMarketBalance(ctx, deal.Proposal.Client)
providerMarketBalance, err := p.full.StateMarketBalance(ctx, deal.Proposal.Client, nil)
if err != nil {
return nil, err
}
@ -125,9 +125,9 @@ func (p *Provider) accept(ctx context.Context, deal MinerDeal) (func(*MinerDeal)
log.Info("fetching data for a deal")
err = p.sendSignedResponse(StorageDealResponse{
State: api.DealAccepted,
Message: "",
Proposal: deal.ProposalCid,
State: api.DealAccepted,
Message: "",
Proposal: deal.ProposalCid,
PublishMessage: smsg.Cid(),
})
if err != nil {
@ -206,8 +206,8 @@ func (p *Provider) waitSealed(ctx context.Context, deal MinerDeal) (sectorbuilde
func (p *Provider) sealing(ctx context.Context, deal MinerDeal) (func(*MinerDeal), error) {
err := p.sendSignedResponse(StorageDealResponse{
State: api.DealSealing,
Proposal: deal.ProposalCid,
State: api.DealSealing,
Proposal: deal.ProposalCid,
})
if err != nil {
log.Warnf("Sending deal response failed: %s", err)

View File

@ -33,7 +33,7 @@ type StorageDealResponse struct {
Proposal cid.Cid
// DealAccepted
StorageDeal actors.StorageDeal
StorageDeal actors.StorageDeal
PublishMessage cid.Cid
// DealComplete

View File

@ -1,31 +0,0 @@
package deals
import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/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
}

View File

@ -13,7 +13,6 @@ import (
chunker "github.com/ipfs/go-ipfs-chunker"
offline "github.com/ipfs/go-ipfs-exchange-offline"
files "github.com/ipfs/go-ipfs-files"
cbor "github.com/ipfs/go-ipld-cbor"
ipld "github.com/ipfs/go-ipld-format"
"github.com/ipfs/go-merkledag"
"github.com/ipfs/go-unixfs/importer/balanced"
@ -76,50 +75,19 @@ func (a *API) ClientStartDeal(ctx context.Context, data cid.Cid, miner address.A
return nil, err
}
vd, err := a.DealClient.VerifyParams(ctx, data)
if err != nil {
return nil, err
}
voucherData, err := cbor.DumpObject(vd)
if err != nil {
return nil, err
}
// setup payments
total := types.BigMul(price, types.NewInt(blocksDuration))
// TODO: at least ping the miner before creating paych / locking the money
extra := &types.ModVerifyParams{
Actor: miner,
Method: actors.MAMethods.PaymentVerifyInclusion,
Data: voucherData,
}
head := a.Chain.GetHeaviestTipSet()
vouchers := deals.VoucherSpec(blocksDuration, total, head.Height(), extra)
payment, err := a.PaychNewPayment(ctx, self, miner, vouchers)
if err != nil {
return nil, err
}
proposal := deals.ClientDealProposal{
Data: data,
TotalPrice: total,
Duration: blocksDuration,
Payment: actors.PaymentInfo{
PayChActor: payment.Channel,
Payer: self,
ChannelMessage: payment.ChannelMessage,
Vouchers: payment.Vouchers,
},
Data: data,
TotalPrice: total,
Duration: blocksDuration,
ProviderAddress: miner,
Client: self,
MinerID: pid,
}
c, err := a.DealClient.Start(ctx, proposal, vd)
c, err := a.DealClient.Start(ctx, proposal)
// TODO: send updated voucher with PaymentVerifySector for cheaper validation (validate the sector the miner sent us first!)
return &c, err
}
@ -135,13 +103,12 @@ func (a *API) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) {
out[k] = api.DealInfo{
ProposalCid: v.ProposalCid,
State: v.State,
Miner: v.Proposal.MinerAddress,
Provider: v.Proposal.Provider,
PieceRef: v.Proposal.PieceRef,
CommP: v.Proposal.CommP,
Size: v.Proposal.Size,
Size: v.Proposal.PieceSize,
TotalPrice: v.Proposal.TotalPrice,
TotalPrice: v.Proposal.StoragePrice,
Duration: v.Proposal.Duration,
}
}

View File

@ -226,3 +226,17 @@ func (a *StateAPI) StateListMiners(ctx context.Context, ts *types.TipSet) ([]add
func (a *StateAPI) StateListActors(ctx context.Context, ts *types.TipSet) ([]address.Address, error) {
return a.StateManager.ListAllActors(ctx, ts)
}
func (a *StateAPI) StateMarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (actors.StorageParticipantBalance, error) {
var state actors.StorageMarketState
if _, err := a.StateManager.LoadActorState(ctx, actors.StoragePowerAddress, &state, ts); err != nil {
return actors.StorageParticipantBalance{}, err
}
cst := hamt.CSTFromBstore(a.StateManager.ChainStore().Blockstore())
b, _, err := actors.GetMarketBalances(ctx, cst, state.Balances, addr)
if err != nil {
return actors.StorageParticipantBalance{}, err
}
return b[0], nil
}