diff --git a/chain/sync.go b/chain/sync.go index dac2a79e5..55ac65719 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -2,6 +2,7 @@ package chain import ( "context" + "errors" "fmt" "sync" "time" @@ -368,6 +369,10 @@ func (syncer *Syncer) Sync(ctx context.Context, maybeHead *types.TipSet) error { return nil } +func isPermanent(err error) bool { + return !errors.Is(err, ErrTemporal) +} + func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet) error { ctx, span := trace.StartSpan(ctx, "validateTipSet") defer span.End() @@ -379,7 +384,9 @@ func (syncer *Syncer) ValidateTipSet(ctx context.Context, fts *store.FullTipSet) for _, b := range fts.Blocks { if err := syncer.ValidateBlock(ctx, b); err != nil { - syncer.bad.Add(b.Cid()) + if isPermanent(err) { + syncer.bad.Add(b.Cid()) + } return xerrors.Errorf("validating block %s: %w", b.Cid(), err) } @@ -444,6 +451,8 @@ func (syncer *Syncer) validateTickets(ctx context.Context, mworker address.Addre return nil } +var ErrTemporal = errors.New("temporal error") + // Should match up with 'Semantical Validation' in validation.md in the spec func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) error { ctx, span := trace.StartSpan(ctx, "validateBlock") @@ -470,7 +479,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err } if h.Timestamp > uint64(time.Now().Unix()+build.AllowableClockDrift) { - return xerrors.Errorf("block was from the future") + return xerrors.Errorf("block was from the future: %w", ErrTemporal) } if h.Timestamp < baseTs.MinTimestamp()+uint64(build.BlockDelay*len(h.Tickets)) {