fsm: Handle invalid Commits
This commit is contained in:
parent
25bd37364c
commit
dcfd0943d5
33
cbor_gen.go
33
cbor_gen.go
@ -178,7 +178,7 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error {
|
|||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := w.Write([]byte{176}); err != nil {
|
if _, err := w.Write([]byte{177}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,6 +450,22 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// t.InvalidProofs (uint64) (uint64)
|
||||||
|
if len("InvalidProofs") > cbg.MaxLength {
|
||||||
|
return xerrors.Errorf("Value in field \"InvalidProofs\" was too long")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len("InvalidProofs")))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte("InvalidProofs")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.InvalidProofs))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// t.FaultReportMsg (cid.Cid) (struct)
|
// t.FaultReportMsg (cid.Cid) (struct)
|
||||||
if len("FaultReportMsg") > cbg.MaxLength {
|
if len("FaultReportMsg") > cbg.MaxLength {
|
||||||
return xerrors.Errorf("Value in field \"FaultReportMsg\" was too long")
|
return xerrors.Errorf("Value in field \"FaultReportMsg\" was too long")
|
||||||
@ -802,6 +818,21 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) error {
|
|||||||
t.CommitMessage = &c
|
t.CommitMessage = &c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// t.InvalidProofs (uint64) (uint64)
|
||||||
|
case "InvalidProofs":
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
maj, extra, err = cbg.CborReadHeader(br)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if maj != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
|
}
|
||||||
|
t.InvalidProofs = uint64(extra)
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.FaultReportMsg (cid.Cid) (struct)
|
// t.FaultReportMsg (cid.Cid) (struct)
|
||||||
case "FaultReportMsg":
|
case "FaultReportMsg":
|
||||||
|
42
checks.go
42
checks.go
@ -9,6 +9,8 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/sector-storage/ffiwrapper"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||||
"github.com/filecoin-project/specs-actors/actors/crypto"
|
"github.com/filecoin-project/specs-actors/actors/crypto"
|
||||||
@ -31,6 +33,7 @@ type ErrBadCommD struct{ error }
|
|||||||
type ErrExpiredTicket struct{ error }
|
type ErrExpiredTicket struct{ error }
|
||||||
|
|
||||||
type ErrBadSeed struct{ error }
|
type ErrBadSeed struct{ error }
|
||||||
|
type ErrInvalidProof struct{ error }
|
||||||
|
|
||||||
// checkPieces validates that:
|
// checkPieces validates that:
|
||||||
// - Each piece han a corresponding on chain deal
|
// - Each piece han a corresponding on chain deal
|
||||||
@ -121,8 +124,8 @@ func checkPrecommit(ctx context.Context, maddr address.Address, si SectorInfo, a
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCommit(ctx context.Context, si SectorInfo, api sealingApi) (err error) {
|
func (m *Sealing) checkCommit(ctx context.Context, si SectorInfo) (err error) {
|
||||||
head, err := api.ChainHead(ctx)
|
head, err := m.api.ChainHead(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ErrApi{xerrors.Errorf("getting chain head: %w", err)}
|
return &ErrApi{xerrors.Errorf("getting chain head: %w", err)}
|
||||||
}
|
}
|
||||||
@ -131,14 +134,45 @@ func checkCommit(ctx context.Context, si SectorInfo, api sealingApi) (err error)
|
|||||||
return &ErrBadSeed{xerrors.Errorf("seed epoch was not set")}
|
return &ErrBadSeed{xerrors.Errorf("seed epoch was not set")}
|
||||||
}
|
}
|
||||||
|
|
||||||
rand, err := api.ChainGetRandomness(ctx, head.Key(), crypto.DomainSeparationTag_InteractiveSealChallengeSeed, si.Seed.Epoch, nil)
|
seed, err := m.api.ChainGetRandomness(ctx, head.Key(), crypto.DomainSeparationTag_InteractiveSealChallengeSeed, si.Seed.Epoch, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ErrApi{xerrors.Errorf("failed to get randomness for computing seal proof: %w", err)}
|
return &ErrApi{xerrors.Errorf("failed to get randomness for computing seal proof: %w", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(rand) != string(si.Seed.Value) {
|
if string(seed) != string(si.Seed.Value) {
|
||||||
return &ErrBadSeed{xerrors.Errorf("seed has changed")}
|
return &ErrBadSeed{xerrors.Errorf("seed has changed")}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ss, err := m.api.StateMinerSectorSize(ctx, m.maddr, head.Key())
|
||||||
|
if err != nil {
|
||||||
|
return &ErrApi{err}
|
||||||
|
}
|
||||||
|
_, spt, err := ffiwrapper.ProofTypeFromSectorSize(ss)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ok, err := ffiwrapper.ProofVerifier.VerifySeal(abi.SealVerifyInfo{
|
||||||
|
SectorID: m.minerSector(si.SectorID),
|
||||||
|
OnChain: abi.OnChainSealVerifyInfo{
|
||||||
|
SealedCID: *si.CommR,
|
||||||
|
InteractiveEpoch: si.Seed.Epoch,
|
||||||
|
RegisteredProof: spt,
|
||||||
|
Proof: si.Proof,
|
||||||
|
SectorNumber: si.SectorID,
|
||||||
|
SealRandEpoch: si.Ticket.Epoch,
|
||||||
|
},
|
||||||
|
Randomness: si.Ticket.Value,
|
||||||
|
InteractiveRandomness: si.Seed.Value,
|
||||||
|
UnsealedCID: *si.CommD,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("verify seal: %w", err)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return &ErrInvalidProof{xerrors.New("invalid proof (compute error?)")}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
1
fsm.go
1
fsm.go
@ -84,6 +84,7 @@ var fsmPlanners = map[api.SectorState]func(events []statemachine.Event, state *S
|
|||||||
on(SectorSealPreCommitFailed{}, api.SealFailed),
|
on(SectorSealPreCommitFailed{}, api.SealFailed),
|
||||||
on(SectorRetryWaitSeed{}, api.WaitSeed),
|
on(SectorRetryWaitSeed{}, api.WaitSeed),
|
||||||
on(SectorRetryComputeProof{}, api.Committing),
|
on(SectorRetryComputeProof{}, api.Committing),
|
||||||
|
on(SectorRetryInvalidProof{}, api.Committing),
|
||||||
),
|
),
|
||||||
|
|
||||||
api.Faulty: planOne(
|
api.Faulty: planOne(
|
||||||
|
@ -96,7 +96,9 @@ func (evt SectorPreCommit2) apply(state *SectorInfo) {
|
|||||||
type SectorSealPreCommitFailed struct{ error }
|
type SectorSealPreCommitFailed struct{ error }
|
||||||
|
|
||||||
func (evt SectorSealPreCommitFailed) FormatError(xerrors.Printer) (next error) { return evt.error }
|
func (evt SectorSealPreCommitFailed) FormatError(xerrors.Printer) (next error) { return evt.error }
|
||||||
func (evt SectorSealPreCommitFailed) apply(*SectorInfo) {}
|
func (evt SectorSealPreCommitFailed) apply(si *SectorInfo) {
|
||||||
|
si.InvalidProofs = 0 // reset counter
|
||||||
|
}
|
||||||
|
|
||||||
type SectorChainPreCommitFailed struct{ error }
|
type SectorChainPreCommitFailed struct{ error }
|
||||||
|
|
||||||
@ -170,6 +172,13 @@ type SectorRetryComputeProof struct{}
|
|||||||
|
|
||||||
func (evt SectorRetryComputeProof) apply(state *SectorInfo) {}
|
func (evt SectorRetryComputeProof) apply(state *SectorInfo) {}
|
||||||
|
|
||||||
|
type SectorRetryInvalidProof struct{}
|
||||||
|
|
||||||
|
func (evt SectorRetryInvalidProof) apply(state *SectorInfo) {
|
||||||
|
state.InvalidProofs++
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Faults
|
// Faults
|
||||||
|
|
||||||
type SectorFaulty struct{}
|
type SectorFaulty struct{}
|
||||||
|
@ -205,6 +205,10 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo)
|
|||||||
return ctx.Send(SectorComputeProofFailed{xerrors.Errorf("computing seal proof failed: %w", err)})
|
return ctx.Send(SectorComputeProofFailed{xerrors.Errorf("computing seal proof failed: %w", err)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := m.checkCommit(ctx.Context(), sector); err != nil {
|
||||||
|
return ctx.Send(SectorCommitFailed{xerrors.Errorf("commit check error: %w", err)})
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Consider splitting states and persist proof for faster recovery
|
// TODO: Consider splitting states and persist proof for faster recovery
|
||||||
|
|
||||||
params := &miner.ProveCommitSectorParams{
|
params := &miner.ProveCommitSectorParams{
|
||||||
|
@ -147,7 +147,7 @@ func (m *Sealing) handleCommitFailed(ctx statemachine.Context, sector SectorInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkCommit(ctx.Context(), sector, m.api); err != nil {
|
if err := m.checkCommit(ctx.Context(), sector); err != nil {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case *ErrApi:
|
case *ErrApi:
|
||||||
log.Errorf("handleCommitFailed: api error, not proceeding: %+v", err)
|
log.Errorf("handleCommitFailed: api error, not proceeding: %+v", err)
|
||||||
@ -155,6 +155,16 @@ func (m *Sealing) handleCommitFailed(ctx statemachine.Context, sector SectorInfo
|
|||||||
case *ErrBadSeed:
|
case *ErrBadSeed:
|
||||||
log.Errorf("seed changed, will retry: %+v", err)
|
log.Errorf("seed changed, will retry: %+v", err)
|
||||||
return ctx.Send(SectorRetryWaitSeed{})
|
return ctx.Send(SectorRetryWaitSeed{})
|
||||||
|
case *ErrInvalidProof:
|
||||||
|
if err := failedCooldown(ctx, sector); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if sector.InvalidProofs > 0 {
|
||||||
|
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("consecutive invalid proofs")})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Send(SectorRetryInvalidProof{})
|
||||||
default:
|
default:
|
||||||
return xerrors.Errorf("checkCommit sanity check error: %w", err)
|
return xerrors.Errorf("checkCommit sanity check error: %w", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user