From da08ab9fd81f5ac9f9168652cf175f965db7c8da Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 9 Oct 2019 17:50:57 +0900 Subject: [PATCH] Implement cache for bad blocks --- chain/badtscache.go | 31 +++++++++++++++++++++++++++++++ chain/sync.go | 19 ++++++++++++++----- 2 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 chain/badtscache.go diff --git a/chain/badtscache.go b/chain/badtscache.go new file mode 100644 index 000000000..9f2cfb1e4 --- /dev/null +++ b/chain/badtscache.go @@ -0,0 +1,31 @@ +package chain + +import ( + "sync" + + "github.com/ipfs/go-cid" +) + +type BadBlockCache struct { + lk sync.Mutex + badBlocks map[cid.Cid]struct{} +} + +func NewBadBlockCache() *BadBlockCache { + return &BadBlockCache{ + badBlocks: make(map[cid.Cid]struct{}), + } +} + +func (bts *BadBlockCache) Add(c cid.Cid) { + bts.lk.Lock() + defer bts.lk.Unlock() + bts.badBlocks[c] = struct{}{} +} + +func (bts *BadBlockCache) Has(c cid.Cid) bool { + bts.lk.Lock() + defer bts.lk.Unlock() + _, ok := bts.badBlocks[c] + return ok +} diff --git a/chain/sync.go b/chain/sync.go index 03465f47a..0a3aace6d 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -44,7 +44,7 @@ type Syncer struct { syncLock sync.Mutex // TipSets known to be invalid - bad BadTipSetCache + bad *BadBlockCache // handle to the block sync service Bsync *BlockSync @@ -71,6 +71,7 @@ func NewSyncer(sm *stmgr.StateManager, bsync *BlockSync, self peer.ID) (*Syncer, } return &Syncer{ + bad: NewBadBlockCache(), Genesis: gent, Bsync: bsync, peerHeads: make(map[peer.ID]*types.TipSet), @@ -80,10 +81,6 @@ func NewSyncer(sm *stmgr.StateManager, bsync *BlockSync, self peer.ID) (*Syncer, }, nil } -type BadTipSetCache struct { - badBlocks map[cid.Cid]struct{} -} - const BootstrapPeerThreshold = 1 // InformNewHead informs the syncer about a new potential tipset @@ -359,6 +356,7 @@ 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()) return xerrors.Errorf("validating block %s: %w", b.Cid(), err) } } @@ -610,6 +608,12 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, from *types.TipSet, to // If, for some reason, we have a suffix of the chain locally, handle that here for blockSet[len(blockSet)-1].Height() > untilHeight { log.Warn("syncing local: ", at) + for _, bc := range at { + if syncer.bad.Has(bc) { + return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s)", from.Cids(), bc) + } + } + ts, err := syncer.store.LoadTipSet(at) if err != nil { if xerrors.Is(err, bstore.ErrNotFound) { @@ -651,6 +655,11 @@ loop: if b.Height() < untilHeight { break loop } + for _, bc := range b.Cids() { + if syncer.bad.Has(bc) { + return nil, xerrors.Errorf("chain contained block marked previously as bad (%s, %s)", from.Cids(), bc) + } + } blockSet = append(blockSet, b) }