From da08ab9fd81f5ac9f9168652cf175f965db7c8da Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 9 Oct 2019 17:50:57 +0900 Subject: [PATCH 1/4] 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) } From b333247fab63b14dc0b41189a4a8a56da3678e08 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 9 Oct 2019 21:23:45 +0900 Subject: [PATCH 2/4] switch to a bounded cache --- chain/badtscache.go | 15 ++++++++++----- go.mod | 1 + 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/chain/badtscache.go b/chain/badtscache.go index 9f2cfb1e4..ca428ff30 100644 --- a/chain/badtscache.go +++ b/chain/badtscache.go @@ -3,29 +3,34 @@ package chain import ( "sync" + lru "github.com/hashicorp/golang-lru" "github.com/ipfs/go-cid" ) type BadBlockCache struct { lk sync.Mutex - badBlocks map[cid.Cid]struct{} + badBlocks *lru.ARCCache } func NewBadBlockCache() *BadBlockCache { + cache, err := lru.NewARC(8192) + if err != nil { + panic(err) + } + return &BadBlockCache{ - badBlocks: make(map[cid.Cid]struct{}), + badBlocks: cache, } } func (bts *BadBlockCache) Add(c cid.Cid) { bts.lk.Lock() defer bts.lk.Unlock() - bts.badBlocks[c] = struct{}{} + bts.badBlocks.Add(c, nil) } func (bts *BadBlockCache) Has(c cid.Cid) bool { bts.lk.Lock() defer bts.lk.Unlock() - _, ok := bts.badBlocks[c] - return ok + return bts.badBlocks.Contains(c) } diff --git a/go.mod b/go.mod index 1ffbb7fda..807508321 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1 github.com/go-ole/go-ole v1.2.4 // indirect github.com/gorilla/websocket v1.4.0 + github.com/hashicorp/golang-lru v0.5.3 github.com/ipfs/go-bitswap v0.1.8 github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.3-0.20190908200855-f22eea50656c From bb974d23e60b47fb7b3f04c893a06aa713a58249 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 9 Oct 2019 21:50:07 +0900 Subject: [PATCH 3/4] arc cache is threadsafe --- chain/badtscache.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/chain/badtscache.go b/chain/badtscache.go index ca428ff30..1e2b67f39 100644 --- a/chain/badtscache.go +++ b/chain/badtscache.go @@ -1,14 +1,11 @@ package chain import ( - "sync" - lru "github.com/hashicorp/golang-lru" "github.com/ipfs/go-cid" ) type BadBlockCache struct { - lk sync.Mutex badBlocks *lru.ARCCache } @@ -24,13 +21,9 @@ func NewBadBlockCache() *BadBlockCache { } func (bts *BadBlockCache) Add(c cid.Cid) { - bts.lk.Lock() - defer bts.lk.Unlock() bts.badBlocks.Add(c, nil) } func (bts *BadBlockCache) Has(c cid.Cid) bool { - bts.lk.Lock() - defer bts.lk.Unlock() return bts.badBlocks.Contains(c) } From 67058aee53ff86e3149e2b038b5a1470a4af52b6 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Wed, 9 Oct 2019 21:55:27 +0900 Subject: [PATCH 4/4] make it a const --- build/params.go | 3 +++ chain/badtscache.go | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/build/params.go b/build/params.go index 6743b7b01..633614756 100644 --- a/build/params.go +++ b/build/params.go @@ -85,3 +85,6 @@ func init() { panic("could not parse InitialRewardStr") } } + +// Sync +const BadBlockCacheSize = 8192 diff --git a/chain/badtscache.go b/chain/badtscache.go index 1e2b67f39..ee63c1abd 100644 --- a/chain/badtscache.go +++ b/chain/badtscache.go @@ -1,6 +1,7 @@ package chain import ( + "github.com/filecoin-project/go-lotus/build" lru "github.com/hashicorp/golang-lru" "github.com/ipfs/go-cid" ) @@ -10,7 +11,7 @@ type BadBlockCache struct { } func NewBadBlockCache() *BadBlockCache { - cache, err := lru.NewARC(8192) + cache, err := lru.NewARC(build.BadBlockCacheSize) if err != nil { panic(err) }