Fix handling of re-precommit

This commit is contained in:
Łukasz Magiera 2020-06-02 23:45:28 +02:00
parent 9b92e145e7
commit 222f3d876c
4 changed files with 57 additions and 11 deletions

View File

@ -24,6 +24,8 @@ type ErrExpiredDeals struct{ error }
type ErrBadCommD struct{ error }
type ErrExpiredTicket struct{ error }
type ErrBadTicket struct{ error }
type ErrPrecommitOnChain struct{ error }
type ErrBadSeed struct{ error }
type ErrInvalidProof struct{ error }
@ -82,6 +84,18 @@ func checkPrecommit(ctx context.Context, maddr address.Address, si SectorInfo, t
return &ErrExpiredTicket{xerrors.Errorf("ticket expired: seal height: %d, head: %d", si.TicketEpoch+SealRandomnessLookback, height)}
}
pci, err := api.StateSectorPreCommitInfo(ctx, maddr, si.SectorNumber, tok)
if err != nil {
return &ErrApi{xerrors.Errorf("getting precommit info: %w", err)}
}
if pci != nil {
if pci.Info.SealRandEpoch != si.TicketEpoch {
return &ErrBadTicket{}
}
return &ErrPrecommitOnChain{}
}
return nil
}

2
fsm.go
View File

@ -48,6 +48,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto
on(SectorSealPreCommitFailed{}, SealFailed),
on(SectorPreCommitted{}, PreCommitWait),
on(SectorChainPreCommitFailed{}, PreCommitFailed),
on(SectorPreCommitLanded{}, WaitSeed),
),
PreCommitWait: planOne(
on(SectorChainPreCommitFailed{}, PreCommitFailed),
@ -79,6 +80,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto
on(SectorRetryPreCommit{}, PreCommitting),
on(SectorRetryWaitSeed{}, WaitSeed),
on(SectorSealPreCommitFailed{}, SealFailed),
on(SectorPreCommitLanded{}, WaitSeed),
),
ComputeProofFailed: planOne(
on(SectorRetryComputeProof{}, Committing),

View File

@ -46,13 +46,37 @@ func (m *Sealing) handlePacking(ctx statemachine.Context, sector SectorInfo) err
return ctx.Send(SectorPacked{FillerPieces: fillerPieces})
}
func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo) error {
func (m *Sealing) getTicket(ctx statemachine.Context, sector SectorInfo) (abi.SealRandomness, abi.ChainEpoch, error) {
tok, epoch, err := m.api.ChainHead(ctx.Context())
if err != nil {
log.Errorf("handlePreCommit1: api error, not proceeding: %+v", err)
return nil
return nil, 0, nil
}
ticketEpoch := epoch - miner.ChainFinalityish
buf := new(bytes.Buffer)
if err := m.maddr.MarshalCBOR(buf); err != nil {
return nil, 0, err
}
pci, err := m.api.StateSectorPreCommitInfo(ctx.Context(), m.maddr, sector.SectorNumber, tok)
if err != nil {
return nil, 0, xerrors.Errorf("getting precommit info: %w", err)
}
if pci != nil {
ticketEpoch = pci.Info.SealRandEpoch
}
rand, err := m.api.ChainGetRandomness(ctx.Context(), tok, crypto.DomainSeparationTag_SealRandomness, ticketEpoch, buf.Bytes())
if err != nil {
return nil, 0, err
}
return abi.SealRandomness(rand), ticketEpoch, nil
}
func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo) error {
if err := checkPieces(ctx.Context(), sector, m.api); err != nil { // Sanity check state
switch err.(type) {
case *ErrApi:
@ -68,16 +92,10 @@ func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo)
}
log.Infow("performing sector replication...", "sector", sector.SectorNumber)
ticketEpoch := epoch - miner.ChainFinalityish
buf := new(bytes.Buffer)
if err := m.maddr.MarshalCBOR(buf); err != nil {
return err
}
rand, err := m.api.ChainGetRandomness(ctx.Context(), tok, crypto.DomainSeparationTag_SealRandomness, ticketEpoch, buf.Bytes())
ticketValue, ticketEpoch, err := m.getTicket(ctx, sector)
if err != nil {
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("getting ticket failed: %w", err)})
}
ticketValue := abi.SealRandomness(rand)
pc1o, err := m.sealer.SealPreCommit1(ctx.Context(), m.minerSector(sector.SectorNumber), ticketValue, sector.pieceInfos())
if err != nil {
@ -117,7 +135,7 @@ func (m *Sealing) handlePreCommitting(ctx statemachine.Context, sector SectorInf
}
if err := checkPrecommit(ctx.Context(), m.Address(), sector, tok, height, m.api); err != nil {
switch err.(type) {
switch err := err.(type) {
case *ErrApi:
log.Errorf("handlePreCommitting: api error, not proceeding: %+v", err)
return nil
@ -125,6 +143,10 @@ func (m *Sealing) handlePreCommitting(ctx statemachine.Context, sector SectorInf
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("bad CommD error: %w", err)})
case *ErrExpiredTicket:
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("ticket expired: %w", err)})
case *ErrBadTicket:
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("bad expired: %w", err)})
case *ErrPrecommitOnChain:
return ctx.Send(SectorPreCommitLanded{TipSet: tok}) // we re-did precommit
default:
return xerrors.Errorf("checkPrecommit sanity check error: %w", err)
}

View File

@ -72,6 +72,10 @@ func (m *Sealing) handlePreCommitFailed(ctx statemachine.Context, sector SectorI
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("bad CommD error: %w", err)})
case *ErrExpiredTicket:
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("ticket expired error: %w", err)})
case *ErrBadTicket:
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("bad expired: %w", err)})
case *ErrPrecommitOnChain:
// noop
default:
return xerrors.Errorf("checkPrecommit sanity check error: %w", err)
}
@ -80,7 +84,7 @@ func (m *Sealing) handlePreCommitFailed(ctx statemachine.Context, sector SectorI
if pci, is := m.checkPreCommitted(ctx, sector); is && pci != nil {
if sector.PreCommitMessage != nil {
log.Warn("sector %d is precommitted on chain, but we don't have precommit message", sector.SectorNumber)
return nil // TODO: SeedWait needs this currently
return ctx.Send(SectorPreCommitLanded{TipSet: tok})
}
if pci.Info.SealedCID != *sector.CommR {
@ -139,6 +143,10 @@ func (m *Sealing) handleCommitFailed(ctx statemachine.Context, sector SectorInfo
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("bad CommD error: %w", err)})
case *ErrExpiredTicket:
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("ticket expired error: %w", err)})
case *ErrBadTicket:
return ctx.Send(SectorSealPreCommitFailed{xerrors.Errorf("bad expired: %w", err)})
case *ErrPrecommitOnChain:
// noop, this is expected
default:
return xerrors.Errorf("checkPrecommit sanity check error: %w", err)
}