Skip to content

Commit

Permalink
Implement off-chain Window PoSt verification (filecoin-project#1327)
Browse files Browse the repository at this point in the history
This patch implements two changes:

1. New Window PoSts, except those that restore faulty sectors, are
   optimistically accepted, assumed correct, and recorded in the
   state-tree for one proving period.
2. Optimistically accepted window posts can be disputed until
   `WPoStProofDisputeWindow` epochs after the challenge window in which
   they were submitted closes. When a dispute successfully refutes an
   optimistically accepted Window PoSt, the miner is fined one IPF per
   active sector in the partition (at the moment when the proof was
   submitted) plus a flat fee of 20FIL, all incorrectly proved sectors
   are marked faulty, and the disputer (address that submitted the
   dispute) is rewarded a fixed `DipsuteReward`.
  • Loading branch information
Stebalien authored and bibibong committed Feb 20, 2021
1 parent b863afa commit d0e0bc9
Show file tree
Hide file tree
Showing 20 changed files with 1,484 additions and 200 deletions.
7 changes: 4 additions & 3 deletions actors/builtin/market/market_actor.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,9 @@ func (a Actor) PublishStorageDeals(rt Runtime, params *PublishStorageDealsParams
code := rt.Send(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &builtin.BatchPieceCIDParams{PieceCIDs: pids}, abi.NewTokenAmount(0), &builtin.Discard{})
builtin.RequireSuccess(rt, code, "failed to batch check expert data")

err := builtin.EnsureMinerNoPieces(rt, provider, pids)
builtin.RequireNoErr(rt, err, exitcode.ErrIllegalArgument, "failed to check miner pieces")
stored, err := builtin.CheckMinerStoredAnyPiece(rt, provider, pids)
builtin.RequireNoErr(rt, err, exitcode.ErrIllegalArgument, "failed to check miner stored pieces")
builtin.RequireState(rt, stored == false, "one or more files already stored")

/* resolvedAddrs := make(map[addr.Address]addr.Address, len(params.Deals))
baselinePower := requestCurrentBaselinePower(rt)
Expand Down Expand Up @@ -728,7 +729,7 @@ func genRandNextEpoch(currEpoch abi.ChainEpoch, deal *DealProposal, rbF func(cry
}

func genTerminateEpoch(currEpoch abi.ChainEpoch, dealID abi.DealID) (abi.ChainEpoch, error) {
offset := uint64(dealID) % uint64(DealUpdatesInterval)
offset := uint64(dealID) % uint64(DealTerminateLatency)
return currEpoch + DealTerminateLatency + abi.ChainEpoch(offset), nil
}

Expand Down
31 changes: 18 additions & 13 deletions actors/builtin/market/market_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ import (
"github.com/stretchr/testify/require"
)

var (
cbgFalse = cbg.CborBool(false)
cbgTrue = cbg.CborBool(true)
)

func mustCbor(o cbor.Marshaler) []byte {
buf := new(bytes.Buffer)
if err := o.MarshalCBOR(buf); err != nil {
Expand Down Expand Up @@ -490,7 +495,7 @@ func TestPublishStorageDeals(t *testing.T) {
expectGetControlAddresses(rt, providerResolved, mAddr.owner, mAddr.worker, mAddr.coinbase)
batchPids := builtin.BatchPieceCIDParams{PieceCIDs: []builtin.CheckedCID{{CID: deal.PieceCID}}}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids,big.Zero(), nil, exitcode.Ok)
rt.ExpectSend(providerResolved,builtin.MethodsMiner.EnsureNoPiece,&batchPids,big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(providerResolved, builtin.MethodsMiner.StoredAny, &batchPids, big.Zero(), &cbgFalse, exitcode.Ok)
// expectQueryNetworkInfo(rt, actor)
// create a client proposal with a valid signature
params := market.PublishStorageDealsParams{
Expand Down Expand Up @@ -868,7 +873,7 @@ func TestPublishStorageDealsFailures(t *testing.T) {

batchPids := builtin.BatchPieceCIDParams{PieceCIDs: []builtin.CheckedCID{{CID: dealProposal.PieceCID}}}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids,big.Zero(), nil, exitcode.Ok)
rt.ExpectSend( provider, builtin.MethodsMiner.EnsureNoPiece, &batchPids,big.Zero(), nil, exitcode.Ok, )
rt.ExpectSend( provider, builtin.MethodsMiner.StoredAny, &batchPids,big.Zero(), &cbgFalse, exitcode.Ok, )
/* expectQueryNetworkInfo(rt, actor) */
rt.SetCaller(worker, builtin.AccountActorCodeID)
rt.ExpectVerifySignature(crypto.Signature{}, dealProposal.Client, mustCbor(&dealProposal), tc.signatureVerificationError)
Expand Down Expand Up @@ -949,7 +954,7 @@ func TestPublishStorageDealsFailures(t *testing.T) {
{CID: deal2.PieceCID},
}}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids,big.Zero(), nil, exitcode.Ok)
rt.ExpectSend(deal1.Provider, builtin.MethodsMiner.EnsureNoPiece, &batchPids, big.Zero(), nil, exitcode.Ok)
rt.ExpectSend(deal1.Provider, builtin.MethodsMiner.StoredAny, &batchPids, big.Zero(), &cbgFalse, exitcode.Ok)

rt.SetCaller(worker, builtin.AccountActorCodeID)
rt.ExpectVerifySignature(crypto.Signature{}, deal1.Client, mustCbor(&deal1), nil)
Expand Down Expand Up @@ -1379,18 +1384,18 @@ func TestOnMinerSectorsTerminate(t *testing.T) {
actor.terminateDeals(rt, provider, dealId1)
ss = actor.checkState(rt)
require.True(t, len(ss.DealOpEpochStats)==2 )
_, ok := ss.DealOpEpochStats[currentEpoch+abi.ChainEpoch(market.DealTerminateLatency+dealId1)]
_, ok := ss.DealOpEpochStats[currentEpoch + market.DealTerminateLatency + abi.ChainEpoch(dealId1)]
require.True(t, ok)

// set a new epoch and terminate again -> however slash epoch will still be the old epoch.
newEpoch := currentEpoch + 1
rt.SetEpoch(newEpoch)
actor.terminateDeals(rt, provider, dealId1, dealId2, dealId3)
ss = actor.checkState(rt)
require.True(t, len(ss.DealOpEpochStats)==4 )
_, ok = ss.DealOpEpochStats[newEpoch+abi.ChainEpoch(market.DealTerminateLatency+dealId2)]
require.True(t, len(ss.DealOpEpochStats) == 4)
_, ok = ss.DealOpEpochStats[newEpoch + market.DealTerminateLatency + abi.ChainEpoch(dealId2)]
require.True(t, ok)
_, ok = ss.DealOpEpochStats[newEpoch+abi.ChainEpoch(market.DealTerminateLatency+dealId3)]
_, ok = ss.DealOpEpochStats[newEpoch + market.DealTerminateLatency + abi.ChainEpoch(dealId3)]
require.True(t, ok)

st := actor.getDealState(rt, dealId1)
Expand Down Expand Up @@ -1599,7 +1604,7 @@ func TestCronTick(t *testing.T) {

// slash deal1
slashEpoch := abi.ChainEpoch(150)
terminateEpoch := slashEpoch + abi.ChainEpoch(market.DealTerminateLatency + dealId1)
terminateEpoch := slashEpoch + market.DealTerminateLatency + abi.ChainEpoch(dealId1)
rt.SetEpoch(slashEpoch)
actor.terminateDeals(rt, provider, dealId1)

Expand Down Expand Up @@ -1637,7 +1642,7 @@ func TestCronTick(t *testing.T) {
rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &builtin.GetControlAddressesReturn{Worker: worker, Owner: owner, Coinbase: coinbase}, 0)
batchPids := builtin.BatchPieceCIDParams{PieceCIDs: []builtin.CheckedCID{{CID: d2.PieceCID}}}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(d2.Provider, builtin.MethodsMiner.EnsureNoPiece, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(d2.Provider, builtin.MethodsMiner.StoredAny, &batchPids, big.Zero(), &cbgFalse, exitcode.Ok)
/* expectQueryNetworkInfo(rt, actor) */
rt.SetCaller(worker, builtin.AccountActorCodeID)
rt.ExpectVerifySignature(crypto.Signature{}, d2.Client, mustCbor(&d2), nil)
Expand Down Expand Up @@ -1942,7 +1947,7 @@ func TestCronTickTimedoutDeals(t *testing.T) {
rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &builtin.GetControlAddressesReturn{Worker: worker, Owner: owner,Coinbase: coinbase}, 0)
batchPids := builtin.BatchPieceCIDParams{PieceCIDs: []builtin.CheckedCID{{CID: d2.PieceCID}}}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(d2.Provider, builtin.MethodsMiner.EnsureNoPiece, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(d2.Provider, builtin.MethodsMiner.StoredAny, &batchPids, big.Zero(), &cbgFalse, exitcode.Ok)

/* expectQueryNetworkInfo(rt, actor) */
rt.SetCaller(worker, builtin.AccountActorCodeID)
Expand Down Expand Up @@ -2361,7 +2366,7 @@ func TestMarketActorDeals(t *testing.T) {
rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &builtin.GetControlAddressesReturn{Worker: worker, Owner: owner, Coinbase: coinbase}, 0)
batchPids := builtin.BatchPieceCIDParams{PieceCIDs: []builtin.CheckedCID{{CID: dealProposal.PieceCID}}}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(provider, builtin.MethodsMiner.EnsureNoPiece, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(provider, builtin.MethodsMiner.StoredAny, &batchPids, big.Zero(), &cbgFalse, exitcode.Ok)

/* expectQueryNetworkInfo(rt, actor) */
rt.ExpectVerifySignature(crypto.Signature{}, client, mustCbor(&params.Deals[0].Proposal), nil)
Expand Down Expand Up @@ -2419,7 +2424,7 @@ func TestMaxDealLabelSize(t *testing.T) {
rt.ExpectSend(provider, builtin.MethodsMiner.ControlAddresses, nil, abi.NewTokenAmount(0), &builtin.GetControlAddressesReturn{Worker: worker, Owner: owner,Coinbase: coinbase}, 0)
batchPids := builtin.BatchPieceCIDParams{PieceCIDs: []builtin.CheckedCID{{CID: dealProposal.PieceCID}}}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(provider, builtin.MethodsMiner.EnsureNoPiece, &batchPids, big.Zero(),nil,exitcode.Ok)
rt.ExpectSend(provider, builtin.MethodsMiner.StoredAny, &batchPids, big.Zero(), &cbgFalse, exitcode.Ok)

/* expectQueryNetworkInfo(rt, actor) */
rt.ExpectVerifySignature(crypto.Signature{}, client, mustCbor(&params.Deals[0].Proposal), nil)
Expand Down Expand Up @@ -3085,7 +3090,7 @@ func (h *marketActorTestHarness) publishDeals(rt *mock.Runtime, minerAddrs *mine
batchPids.PieceCIDs = append(batchPids.PieceCIDs, builtin.CheckedCID{CID: dr.deal.PieceCID})
}
rt.ExpectSend(builtin.ExpertFundActorAddr, builtin.MethodsExpertFunds.BatchCheckData, &batchPids, big.Zero(), nil, exitcode.Ok)
rt.ExpectSend(minerAddrs.provider, builtin.MethodsMiner.EnsureNoPiece, &batchPids, big.Zero(), nil, exitcode.Ok)
rt.ExpectSend(minerAddrs.provider, builtin.MethodsMiner.StoredAny, &batchPids, big.Zero(), &cbgFalse, exitcode.Ok)
/* expectQueryNetworkInfo(rt, h) */

params := market.PublishStorageDealsParams{
Expand Down
3 changes: 2 additions & 1 deletion actors/builtin/market/policy.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package market

import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/v2/actors/builtin"
)

// The number of epochs between payment and other state processing for deals.
const DealUpdatesInterval = builtin.EpochsInDay // PARAM_SPEC //TODO:
const DealTerminateLatency = 240 // 4 deadlines
const DealTerminateLatency = abi.ChainEpoch(60) // 1 deadline

/* // The percentage of normalized cirulating
// supply that must be covered by provider collateral in a deal
Expand Down
5 changes: 3 additions & 2 deletions actors/builtin/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ var MethodsMiner = struct {
AddPledge abi.MethodNum
WithdrawPledge abi.MethodNum
ChangeCoinbase abi.MethodNum
EnsureNoPiece abi.MethodNum
}{MethodConstructor, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}
StoredAny abi.MethodNum
DisputeWindowedPoSt abi.MethodNum
}{MethodConstructor, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}

// var MethodsVerifiedRegistry = struct {
// Constructor abi.MethodNum
Expand Down
Loading

0 comments on commit d0e0bc9

Please sign in to comment.