feat(markets): check deal equality

in OnDealSectorCommitted, verify that deals looked up match the deal proposals which were made
This commit is contained in:
hannahhoward 2020-11-09 16:30:47 -08:00
parent 09a0d6e607
commit 7519bdde42
8 changed files with 94 additions and 23 deletions

2
go.mod
View File

@ -30,7 +30,7 @@ require (
github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03
github.com/filecoin-project/go-data-transfer v1.0.0
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f
github.com/filecoin-project/go-fil-markets v0.9.2-0.20201103030854-3d9aa08b3c2f
github.com/filecoin-project/go-fil-markets v0.9.2-0.20201109213926-58f0437275b7
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20201008195726-68c6a2704e49
github.com/filecoin-project/go-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20

4
go.sum
View File

@ -255,8 +255,8 @@ github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl
github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1:GxJzR3oRIMTPtpZ0b7QF8FKPK6/iPAc7trhlL5k/g+s=
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
github.com/filecoin-project/go-fil-markets v0.9.2-0.20201103030854-3d9aa08b3c2f h1:SAyL9YllpB/2gyclDE0AXQenEQc4O2g2IP+DDF7L0Vg=
github.com/filecoin-project/go-fil-markets v0.9.2-0.20201103030854-3d9aa08b3c2f/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM=
github.com/filecoin-project/go-fil-markets v0.9.2-0.20201109213926-58f0437275b7 h1:oxqnqKP9LCI+D4EoszxC7xUYCQovgLmyDa53RgFm6ts=
github.com/filecoin-project/go-fil-markets v0.9.2-0.20201109213926-58f0437275b7/go.mod h1:h+bJ/IUnYjnW5HMKyt9JQSnhslqetkpuzwwugc3K8vM=
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=

View File

@ -23,6 +23,7 @@ import (
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
marketactor "github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/events/state"
"github.com/filecoin-project/lotus/chain/market"
@ -212,8 +213,8 @@ func (c *ClientNodeAdapter) DealProviderCollateralBounds(ctx context.Context, si
return big.Mul(bounds.Min, big.NewInt(clientOverestimation)), bounds.Max, nil
}
func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealID abi.DealID, publishCid *cid.Cid, cb storagemarket.DealSectorCommittedCallback) error {
return OnDealSectorCommitted(ctx, c, c.ev, provider, dealID, publishCid, cb)
func (c *ClientNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealID abi.DealID, proposal market2.DealProposal, publishCid *cid.Cid, cb storagemarket.DealSectorCommittedCallback) error {
return OnDealSectorCommitted(ctx, c, c.ev, provider, dealID, marketactor.DealProposal(proposal), publishCid, cb)
}
func (c *ClientNodeAdapter) OnDealExpiredOrSlashed(ctx context.Context, dealID abi.DealID, onDealExpired storagemarket.DealExpiredCallback, onDealSlashed storagemarket.DealSlashedCallback) error {

View File

@ -19,11 +19,14 @@ type getCurrentDealInfoAPI interface {
}
// 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, publishCid *cid.Cid) (abi.DealID, *api.MarketDeal, error) {
func GetCurrentDealInfo(ctx context.Context, ts *types.TipSet, api getCurrentDealInfoAPI, dealID abi.DealID, proposal market.DealProposal, publishCid *cid.Cid) (abi.DealID, *api.MarketDeal, error) {
marketDeal, dealErr := api.StateMarketStorageDeal(ctx, dealID, ts.Key())
if dealErr == nil {
if marketDeal.Proposal == proposal {
return dealID, marketDeal, nil
}
dealErr = xerrors.Errorf("Deal proposals did not match")
}
if publishCid == nil {
return dealID, nil, dealErr
}
@ -55,5 +58,9 @@ func GetCurrentDealInfo(ctx context.Context, ts *types.TipSet, api getCurrentDea
dealID = retval.IDs[0]
marketDeal, err = api.StateMarketStorageDeal(ctx, dealID, ts.Key())
if err == nil && marketDeal.Proposal != proposal {
return dealID, nil, xerrors.Errorf("Deal proposals did not match")
}
return dealID, marketDeal, err
}

View File

@ -30,7 +30,25 @@ func TestGetCurrentDealInfo(t *testing.T) {
twoValuesReturn := makePublishDealsReturnBytes(t, []abi.DealID{abi.DealID(rand.Uint64()), abi.DealID(rand.Uint64())})
sameValueReturn := makePublishDealsReturnBytes(t, []abi.DealID{startDealID})
newValueReturn := makePublishDealsReturnBytes(t, []abi.DealID{newDealID})
proposal := market.DealProposal{
PieceCID: dummyCid,
PieceSize: abi.PaddedPieceSize(rand.Uint64()),
Label: "success",
}
otherProposal := market.DealProposal{
PieceCID: dummyCid,
PieceSize: abi.PaddedPieceSize(rand.Uint64()),
Label: "other",
}
successDeal := &api.MarketDeal{
Proposal: proposal,
State: market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: 2,
},
}
otherDeal := &api.MarketDeal{
Proposal: otherProposal,
State: market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: 2,
@ -56,6 +74,13 @@ func TestGetCurrentDealInfo(t *testing.T) {
expectedDealID: startDealID,
expectedError: errNotFound,
},
"publish CID = nil, other deal on lookup": {
marketDeals: map[abi.DealID]*api.MarketDeal{
startDealID: otherDeal,
},
expectedDealID: startDealID,
expectedError: xerrors.Errorf("Deal proposals did not match"),
},
"search message fails": {
publishCid: &dummyCid,
searchMessageErr: errors.New("something went wrong"),
@ -119,6 +144,21 @@ func TestGetCurrentDealInfo(t *testing.T) {
expectedDealID: newDealID,
expectedMarketDeal: successDeal,
},
"new deal id after other deal found": {
publishCid: &dummyCid,
searchMessageLookup: &api.MsgLookup{
Receipt: types.MessageReceipt{
ExitCode: exitcode.Ok,
Return: newValueReturn,
},
},
marketDeals: map[abi.DealID]*api.MarketDeal{
startDealID: otherDeal,
newDealID: successDeal,
},
expectedDealID: newDealID,
expectedMarketDeal: successDeal,
},
"new deal id failure": {
publishCid: &dummyCid,
searchMessageLookup: &api.MsgLookup{
@ -130,6 +170,20 @@ func TestGetCurrentDealInfo(t *testing.T) {
expectedDealID: newDealID,
expectedError: errNotFound,
},
"new deal id, failure due to other deal present": {
publishCid: &dummyCid,
searchMessageLookup: &api.MsgLookup{
Receipt: types.MessageReceipt{
ExitCode: exitcode.Ok,
Return: newValueReturn,
},
},
marketDeals: map[abi.DealID]*api.MarketDeal{
newDealID: otherDeal,
},
expectedDealID: newDealID,
expectedError: xerrors.Errorf("Deal proposals did not match"),
},
}
for testCase, data := range testCases {
t.Run(testCase, func(t *testing.T) {
@ -147,7 +201,7 @@ func TestGetCurrentDealInfo(t *testing.T) {
MarketDeals: marketDeals,
}
dealID, marketDeal, err := GetCurrentDealInfo(ctx, ts, api, startDealID, data.publishCid)
dealID, marketDeal, err := GetCurrentDealInfo(ctx, ts, api, startDealID, proposal, data.publishCid)
require.Equal(t, data.expectedDealID, dealID)
require.Equal(t, data.expectedMarketDeal, marketDeal)
if data.expectedError == nil {

View File

@ -8,6 +8,7 @@ import (
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/events"
"github.com/filecoin-project/lotus/chain/types"
@ -19,9 +20,9 @@ type sectorCommittedEventsAPI interface {
Called(check events.CheckFunc, msgHnd events.MsgHandler, rev events.RevertHandler, confidence int, timeout abi.ChainEpoch, mf events.MsgMatchFunc) error
}
func OnDealSectorCommitted(ctx context.Context, api getCurrentDealInfoAPI, eventsApi sectorCommittedEventsAPI, provider address.Address, dealID abi.DealID, publishCid *cid.Cid, cb storagemarket.DealSectorCommittedCallback) error {
func OnDealSectorCommitted(ctx context.Context, api getCurrentDealInfoAPI, eventsApi sectorCommittedEventsAPI, provider address.Address, dealID abi.DealID, proposal market.DealProposal, publishCid *cid.Cid, cb storagemarket.DealSectorCommittedCallback) error {
checkFunc := func(ts *types.TipSet) (done bool, more bool, err error) {
newDealID, sd, err := GetCurrentDealInfo(ctx, ts, api, dealID, publishCid)
newDealID, sd, err := GetCurrentDealInfo(ctx, ts, api, dealID, proposal, publishCid)
if err != nil {
// TODO: This may be fine for some errors
return false, false, xerrors.Errorf("failed to look up deal on chain: %w", err)
@ -47,16 +48,16 @@ func OnDealSectorCommitted(ctx context.Context, api getCurrentDealInfoAPI, event
}()
switch msg.Method {
case miner.Methods.PreCommitSector:
dealID, _, err = GetCurrentDealInfo(ctx, ts, api, dealID, publishCid)
if err != nil {
return false, err
}
var params miner.SectorPreCommitInfo
if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil {
return false, xerrors.Errorf("unmarshal pre commit: %w", err)
}
dealID, _, err = GetCurrentDealInfo(ctx, ts, api, dealID, proposal, publishCid)
if err != nil {
return false, err
}
for _, did := range params.DealIDs {
if did == dealID {
sectorNumber = params.SectorNumber
@ -71,7 +72,7 @@ func OnDealSectorCommitted(ctx context.Context, api getCurrentDealInfoAPI, event
return false, nil
}
_, sd, err := GetCurrentDealInfo(ctx, ts, api, dealID, publishCid)
_, sd, err := GetCurrentDealInfo(ctx, ts, api, dealID, proposal, publishCid)
if err != nil {
return false, xerrors.Errorf("failed to look up deal on chain: %w", err)
}
@ -105,15 +106,15 @@ func OnDealSectorCommitted(ctx context.Context, api getCurrentDealInfoAPI, event
case miner.Methods.PreCommitSector:
return !sectorFound, nil
case miner.Methods.ProveCommitSector:
if !sectorFound {
return false, nil
}
var params miner.ProveCommitSectorParams
if err := params.UnmarshalCBOR(bytes.NewReader(msg.Params)); err != nil {
return false, xerrors.Errorf("failed to unmarshal prove commit sector params: %w", err)
}
if !sectorFound {
return false, nil
}
if params.SectorNumber != sectorNumber {
return false, nil
}

View File

@ -29,17 +29,25 @@ func TestOnDealSectorCommitted(t *testing.T) {
ctx := context.Background()
publishCid := generateCids(1)[0]
sealedCid := generateCids(1)[0]
pieceCid := generateCids(1)[0]
startDealID := abi.DealID(rand.Uint64())
newDealID := abi.DealID(rand.Uint64())
newValueReturn := makePublishDealsReturnBytes(t, []abi.DealID{newDealID})
sectorNumber := abi.SectorNumber(rand.Uint64())
proposal := market.DealProposal{
PieceCID: pieceCid,
PieceSize: abi.PaddedPieceSize(rand.Uint64()),
Label: "success",
}
unfinishedDeal := &api.MarketDeal{
Proposal: proposal,
State: market.DealState{
SectorStartEpoch: -1,
LastUpdatedEpoch: 2,
},
}
successDeal := &api.MarketDeal{
Proposal: proposal,
State: market.DealState{
SectorStartEpoch: 1,
LastUpdatedEpoch: 2,
@ -263,7 +271,7 @@ func TestOnDealSectorCommitted(t *testing.T) {
cbCallCount++
cbError = err
}
err = OnDealSectorCommitted(ctx, api, eventsAPI, provider, startDealID, &publishCid, cb)
err = OnDealSectorCommitted(ctx, api, eventsAPI, provider, startDealID, proposal, &publishCid, cb)
if data.expectedError == nil {
require.NoError(t, err)
} else {

View File

@ -253,8 +253,8 @@ func (n *ProviderNodeAdapter) DealProviderCollateralBounds(ctx context.Context,
return bounds.Min, bounds.Max, nil
}
func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealID abi.DealID, publishCid *cid.Cid, cb storagemarket.DealSectorCommittedCallback) error {
return OnDealSectorCommitted(ctx, n, n.ev, provider, dealID, publishCid, cb)
func (n *ProviderNodeAdapter) OnDealSectorCommitted(ctx context.Context, provider address.Address, dealID abi.DealID, proposal market2.DealProposal, publishCid *cid.Cid, cb storagemarket.DealSectorCommittedCallback) error {
return OnDealSectorCommitted(ctx, n, n.ev, provider, dealID, market.DealProposal(proposal), publishCid, cb)
}
func (n *ProviderNodeAdapter) GetChainHead(ctx context.Context) (shared.TipSetToken, abi.ChainEpoch, error) {