103 lines
3.7 KiB
Go
103 lines
3.7 KiB
Go
package storageadapter
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
"github.com/filecoin-project/go-state-types/exitcode"
|
|
"github.com/filecoin-project/lotus/api"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
"github.com/ipfs/go-cid"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
type getCurrentDealInfoAPI interface {
|
|
StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error)
|
|
StateMarketStorageDeal(context.Context, abi.DealID, types.TipSetKey) (*api.MarketDeal, error)
|
|
StateSearchMsg(context.Context, cid.Cid) (*api.MsgLookup, error)
|
|
|
|
diffPreCommits(ctx context.Context, actor address.Address, pre, cur types.TipSetKey) (*miner.PreCommitChanges, error)
|
|
}
|
|
|
|
// GetCurrentDealInfo gets current information on a deal, and corrects the deal ID as needed
|
|
func GetCurrentDealInfo(ctx context.Context, ts *types.TipSet, api getCurrentDealInfoAPI, dealID abi.DealID, proposal market.DealProposal, publishCid *cid.Cid) (abi.DealID, *api.MarketDeal, types.TipSetKey, error) {
|
|
marketDeal, dealErr := api.StateMarketStorageDeal(ctx, dealID, ts.Key())
|
|
if dealErr == nil {
|
|
equal, err := checkDealEquality(ctx, ts, api, proposal, marketDeal.Proposal)
|
|
if err != nil {
|
|
return dealID, nil, types.EmptyTSK, err
|
|
}
|
|
if equal {
|
|
return dealID, marketDeal, types.EmptyTSK, nil
|
|
}
|
|
dealErr = xerrors.Errorf("Deal proposals did not match")
|
|
}
|
|
if publishCid == nil {
|
|
return dealID, nil, types.EmptyTSK, dealErr
|
|
}
|
|
// attempt deal id correction
|
|
lookup, err := api.StateSearchMsg(ctx, *publishCid)
|
|
if err != nil {
|
|
return dealID, nil, types.EmptyTSK, err
|
|
}
|
|
|
|
if lookup.Receipt.ExitCode != exitcode.Ok {
|
|
return dealID, nil, types.EmptyTSK, xerrors.Errorf("looking for publish deal message %s: non-ok exit code: %s", *publishCid, lookup.Receipt.ExitCode)
|
|
}
|
|
|
|
var retval market.PublishStorageDealsReturn
|
|
if err := retval.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
|
|
return dealID, nil, types.EmptyTSK, xerrors.Errorf("looking for publish deal message: unmarshaling message return: %w", err)
|
|
}
|
|
|
|
if len(retval.IDs) != 1 {
|
|
// market currently only ever sends messages with 1 deal
|
|
return dealID, nil, types.EmptyTSK, xerrors.Errorf("can't recover dealIDs from publish deal message with more than 1 deal")
|
|
}
|
|
|
|
if retval.IDs[0] == dealID {
|
|
// DealID did not change, so we are stuck with the original lookup error
|
|
return dealID, nil, lookup.TipSet, dealErr
|
|
}
|
|
|
|
dealID = retval.IDs[0]
|
|
marketDeal, err = api.StateMarketStorageDeal(ctx, dealID, ts.Key())
|
|
|
|
if err == nil {
|
|
equal, err := checkDealEquality(ctx, ts, api, proposal, marketDeal.Proposal)
|
|
if err != nil {
|
|
return dealID, nil, types.EmptyTSK, err
|
|
}
|
|
if !equal {
|
|
return dealID, nil, types.EmptyTSK, xerrors.Errorf("Deal proposals did not match")
|
|
}
|
|
}
|
|
return dealID, marketDeal, lookup.TipSet, err
|
|
}
|
|
|
|
func checkDealEquality(ctx context.Context, ts *types.TipSet, api getCurrentDealInfoAPI, p1, p2 market.DealProposal) (bool, error) {
|
|
p1ClientID, err := api.StateLookupID(ctx, p1.Client, ts.Key())
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
p2ClientID, err := api.StateLookupID(ctx, p2.Client, ts.Key())
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return p1.PieceCID.Equals(p2.PieceCID) &&
|
|
p1.PieceSize == p2.PieceSize &&
|
|
p1.VerifiedDeal == p2.VerifiedDeal &&
|
|
p1.Label == p2.Label &&
|
|
p1.StartEpoch == p2.StartEpoch &&
|
|
p1.EndEpoch == p2.EndEpoch &&
|
|
p1.StoragePricePerEpoch.Equals(p2.StoragePricePerEpoch) &&
|
|
p1.ProviderCollateral.Equals(p2.ProviderCollateral) &&
|
|
p1.ClientCollateral.Equals(p2.ClientCollateral) &&
|
|
p1.Provider == p2.Provider &&
|
|
p1ClientID == p2ClientID, nil
|
|
}
|