diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index f4b59d344..f12962683 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -218,7 +218,7 @@ func StorageMiner(fc config.MinerFeeConfig) func(params StorageMinerParams) (*st ctx := helpers.LifecycleCtx(mctx, lc) - fps, err := storage.NewWindowedPoStScheduler(api, fc, as, sealer, sealer, j, maddr) + fps, err := storage.NewWindowedPoStScheduler(api, fc, as, sealer, verif, sealer, j, maddr) if err != nil { return nil, err } diff --git a/storage/wdpost_run.go b/storage/wdpost_run.go index 346ffc38d..c80617558 100644 --- a/storage/wdpost_run.go +++ b/storage/wdpost_run.go @@ -20,6 +20,7 @@ import ( "golang.org/x/xerrors" proof2 "github.com/filecoin-project/specs-actors/v2/actors/runtime/proof" + "github.com/filecoin-project/specs-actors/v3/actors/runtime/proof" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -594,10 +595,26 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *ty log.Infow("computing window post", "batch", batchIdx, "elapsed", elapsed) if err == nil { + // If we proved nothing, something is very wrong. if len(postOut) == 0 { return nil, xerrors.Errorf("received no proofs back from generate window post") } + // If we generated an incorrect proof, try again. + if correct, err := s.verifier.VerifyWindowPoSt(ctx, proof.WindowPoStVerifyInfo{ + Randomness: abi.PoStRandomness(rand), + Proofs: postOut, + ChallengedSectors: sinfos, + Prover: abi.ActorID(mid), + }); err != nil { + log.Errorw("window post verification failed", "post", postOut, "error", err) + time.Sleep(5 * time.Second) + continue + } else if !correct { + log.Errorw("generated incorrect window post proof", "post", postOut, "error", err) + continue + } + // Proof generation successful, stop retrying somethingToProve = true params.Partitions = partitions diff --git a/storage/wdpost_run_test.go b/storage/wdpost_run_test.go index e4c24ad3e..80bd8d3fb 100644 --- a/storage/wdpost_run_test.go +++ b/storage/wdpost_run_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "golang.org/x/xerrors" "github.com/ipfs/go-cid" @@ -123,6 +124,34 @@ func (m *mockProver) GenerateWindowPoSt(ctx context.Context, aid abi.ActorID, si }, nil, nil } +type mockVerif struct { +} + +func (m mockVerif) VerifyWinningPoSt(ctx context.Context, info proof2.WinningPoStVerifyInfo) (bool, error) { + panic("implement me") +} + +func (m mockVerif) VerifyWindowPoSt(ctx context.Context, info proof2.WindowPoStVerifyInfo) (bool, error) { + if len(info.Proofs) != 1 { + return false, xerrors.Errorf("expected 1 proof entry") + } + + proof := info.Proofs[0] + + if !bytes.Equal(proof.ProofBytes, []byte("post-proof")) { + return false, xerrors.Errorf("bad proof") + } + return true, nil +} + +func (m mockVerif) VerifySeal(proof2.SealVerifyInfo) (bool, error) { + panic("implement me") +} + +func (m mockVerif) GenerateWinningPoStSectorChallenge(context.Context, abi.RegisteredPoStProof, abi.ActorID, abi.PoStRandomness, uint64) ([]uint64, error) { + panic("implement me") +} + type mockFaultTracker struct { } @@ -176,6 +205,7 @@ func TestWDPostDoPost(t *testing.T) { scheduler := &WindowPoStScheduler{ api: mockStgMinerAPI, prover: &mockProver{}, + verifier: &mockVerif{}, faultTracker: &mockFaultTracker{}, proofType: proofType, actor: postAct, diff --git a/storage/wdpost_sched.go b/storage/wdpost_sched.go index 3d6073a63..8c24a5516 100644 --- a/storage/wdpost_sched.go +++ b/storage/wdpost_sched.go @@ -16,6 +16,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" sectorstorage "github.com/filecoin-project/lotus/extern/sector-storage" + "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/journal" "github.com/filecoin-project/lotus/node/config" @@ -27,6 +28,7 @@ type WindowPoStScheduler struct { feeCfg config.MinerFeeConfig addrSel *AddressSelector prover storage.Prover + verifier ffiwrapper.Verifier faultTracker sectorstorage.FaultTracker proofType abi.RegisteredPoStProof partitionSectors uint64 @@ -41,7 +43,7 @@ type WindowPoStScheduler struct { // failLk sync.Mutex } -func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, as *AddressSelector, sb storage.Prover, ft sectorstorage.FaultTracker, j journal.Journal, actor address.Address) (*WindowPoStScheduler, error) { +func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, as *AddressSelector, sb storage.Prover, verif ffiwrapper.Verifier, ft sectorstorage.FaultTracker, j journal.Journal, actor address.Address) (*WindowPoStScheduler, error) { mi, err := api.StateMinerInfo(context.TODO(), actor, types.EmptyTSK) if err != nil { return nil, xerrors.Errorf("getting sector size: %w", err) @@ -52,6 +54,7 @@ func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, as feeCfg: fc, addrSel: as, prover: sb, + verifier: verif, faultTracker: ft, proofType: mi.WindowPoStProofType, partitionSectors: mi.WindowPoStPartitionSectors,