2019-09-10 12:35:43 +00:00
|
|
|
package deals
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-10-16 07:07:16 +00:00
|
|
|
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
2019-10-21 18:12:11 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors"
|
2019-10-23 17:39:14 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
2019-09-10 12:35:43 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type clientHandlerFunc func(ctx context.Context, deal ClientDeal) error
|
|
|
|
|
2019-09-10 14:13:24 +00:00
|
|
|
func (c *Client) handle(ctx context.Context, deal ClientDeal, cb clientHandlerFunc, next api.DealState) {
|
2019-09-10 12:35:43 +00:00
|
|
|
go func() {
|
|
|
|
err := cb(ctx, deal)
|
2019-09-13 19:43:33 +00:00
|
|
|
if err != nil {
|
|
|
|
next = api.DealError
|
|
|
|
}
|
2019-09-10 12:35:43 +00:00
|
|
|
select {
|
|
|
|
case c.updated <- clientDealUpdate{
|
|
|
|
newState: next,
|
|
|
|
id: deal.ProposalCid,
|
|
|
|
err: err,
|
|
|
|
}:
|
|
|
|
case <-c.stop:
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) new(ctx context.Context, deal ClientDeal) error {
|
|
|
|
resp, err := c.readStorageDealResp(deal)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-09-10 14:13:24 +00:00
|
|
|
if resp.State != api.DealAccepted {
|
2019-09-10 12:35:43 +00:00
|
|
|
return xerrors.Errorf("deal wasn't accepted (State=%d)", resp.State)
|
|
|
|
}
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
// TODO: spec says it's optional
|
2019-10-23 12:59:57 +00:00
|
|
|
pubmsg, err := c.chain.GetMessage(*resp.PublishMessage)
|
2019-10-21 18:12:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("getting deal pubsish message: %w", err)
|
|
|
|
}
|
|
|
|
|
2019-10-23 17:39:14 +00:00
|
|
|
pw, err := stmgr.GetMinerWorker(ctx, c.sm, nil, deal.Proposal.Provider)
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("getting miner worker failed: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if pubmsg.From != pw {
|
|
|
|
return xerrors.Errorf("deal wasn't published by storage provider: from=%s, provider=%s", pubmsg.From, deal.Proposal.Provider)
|
2019-10-21 18:12:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if pubmsg.To != actors.StorageMarketAddress {
|
2019-10-23 17:39:14 +00:00
|
|
|
return xerrors.Errorf("deal publish message wasn't set to StorageMarket actor (to=%s)", pubmsg.To)
|
2019-10-21 18:12:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if pubmsg.Method != actors.SMAMethods.PublishStorageDeals {
|
2019-10-23 17:39:14 +00:00
|
|
|
return xerrors.Errorf("deal publish message called incorrect method (method=%s)", pubmsg.Method)
|
2019-10-21 18:12:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: timeout
|
2019-10-23 12:59:57 +00:00
|
|
|
_, ret, err := c.sm.WaitForMessage(ctx, *resp.PublishMessage)
|
2019-10-21 18:12:11 +00:00
|
|
|
if err != nil {
|
2019-10-23 17:39:14 +00:00
|
|
|
return xerrors.Errorf("waiting for deal publish message: %w", err)
|
2019-10-21 18:12:11 +00:00
|
|
|
}
|
|
|
|
if ret.ExitCode != 0 {
|
|
|
|
return xerrors.Errorf("deal publish failed: exit=%d", ret.ExitCode)
|
|
|
|
}
|
|
|
|
// TODO: persist dealId
|
|
|
|
|
2019-09-10 12:35:43 +00:00
|
|
|
log.Info("DEAL ACCEPTED!")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) accepted(ctx context.Context, deal ClientDeal) error {
|
|
|
|
/* data transfer happens */
|
|
|
|
|
|
|
|
resp, err := c.readStorageDealResp(deal)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-09-10 14:13:24 +00:00
|
|
|
if resp.State != api.DealStaged {
|
2019-09-10 12:35:43 +00:00
|
|
|
return xerrors.Errorf("deal wasn't staged (State=%d)", resp.State)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Info("DEAL STAGED!")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) staged(ctx context.Context, deal ClientDeal) error {
|
|
|
|
/* miner seals our data, hopefully */
|
|
|
|
|
|
|
|
resp, err := c.readStorageDealResp(deal)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-09-10 14:13:24 +00:00
|
|
|
if resp.State != api.DealSealing {
|
2019-09-10 12:35:43 +00:00
|
|
|
return xerrors.Errorf("deal wasn't sealed (State=%d)", resp.State)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Info("DEAL SEALED!")
|
|
|
|
|
2019-10-21 18:12:11 +00:00
|
|
|
// TODO: want?
|
2019-10-16 07:07:16 +00:00
|
|
|
/*ssize, err := stmgr.GetMinerSectorSize(ctx, c.sm, nil, deal.Proposal.MinerAddress)
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("failed to get miner sector size: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ok, err := sectorbuilder.VerifyPieceInclusionProof(ssize, deal.Proposal.Size, deal.Proposal.CommP, resp.CommD, resp.PieceInclusionProof.ProofElements)
|
2019-09-10 12:35:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("verifying piece inclusion proof in staged deal %s: %w", deal.ProposalCid, err)
|
|
|
|
}
|
|
|
|
if !ok {
|
|
|
|
return xerrors.Errorf("verifying piece inclusion proof in staged deal %s failed", deal.ProposalCid)
|
2019-10-21 18:12:11 +00:00
|
|
|
}*/
|
2019-09-10 12:35:43 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) sealing(ctx context.Context, deal ClientDeal) error {
|
|
|
|
resp, err := c.readStorageDealResp(deal)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-09-10 14:13:24 +00:00
|
|
|
if resp.State != api.DealComplete {
|
2019-09-10 12:35:43 +00:00
|
|
|
return xerrors.Errorf("deal wasn't complete (State=%d)", resp.State)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: look for the commit message on chain, negotiate better payment vouchers
|
|
|
|
|
|
|
|
log.Info("DEAL COMPLETE!!")
|
|
|
|
return nil
|
|
|
|
}
|