mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-25 13:07:17 +00:00
fix concurrent badHeaders map writes crush (#2175)
* fix concurrent map writes crush * fix concurrent map writes crush
This commit is contained in:
parent
159777db29
commit
d7f7445a5e
@ -264,14 +264,14 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx ethdb.RwTx, cfg HeadersCfg)
|
||||
if hash, err = rawdb.ReadCanonicalHash(tx, blockHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.hd.BadHeaders[hash] = struct{}{}
|
||||
cfg.hd.ReportBadHeader(hash)
|
||||
}
|
||||
if err = rawdb.DeleteCanonicalHash(tx, blockHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if u.BadBlock != (common.Hash{}) {
|
||||
cfg.hd.BadHeaders[u.BadBlock] = struct{}{}
|
||||
cfg.hd.ReportBadHeader(u.BadBlock)
|
||||
// Find header with biggest TD
|
||||
tdCursor, cErr := tx.Cursor(dbutils.HeaderTDBucket)
|
||||
if cErr != nil {
|
||||
@ -292,7 +292,7 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx ethdb.RwTx, cfg HeadersCfg)
|
||||
}
|
||||
var hash common.Hash
|
||||
copy(hash[:], k[8:])
|
||||
if _, bad := cfg.hd.BadHeaders[hash]; bad {
|
||||
if cfg.hd.IsBadHeader(hash) {
|
||||
continue
|
||||
}
|
||||
var td big.Int
|
||||
|
@ -54,7 +54,7 @@ func (hd *HeaderDownload) SplitIntoSegments(headersRaw [][]byte, msg []*types.He
|
||||
dedupMap := make(map[common.Hash]struct{}) // Map used for detecting duplicate headers
|
||||
for i, header := range msg {
|
||||
headerHash := header.Hash()
|
||||
if _, bad := hd.BadHeaders[headerHash]; bad {
|
||||
if _, bad := hd.badHeaders[headerHash]; bad {
|
||||
return nil, BadBlockPenalty, nil
|
||||
}
|
||||
if _, duplicate := dedupMap[headerHash]; duplicate {
|
||||
@ -100,12 +100,26 @@ func (hd *HeaderDownload) SingleHeaderAsSegment(headerRaw []byte, header *types.
|
||||
hd.lock.RLock()
|
||||
defer hd.lock.RUnlock()
|
||||
headerHash := header.Hash()
|
||||
if _, bad := hd.BadHeaders[headerHash]; bad {
|
||||
if _, bad := hd.badHeaders[headerHash]; bad {
|
||||
return nil, BadBlockPenalty, nil
|
||||
}
|
||||
return []*ChainSegment{{HeadersRaw: [][]byte{headerRaw}, Headers: []*types.Header{header}}}, NoPenalty, nil
|
||||
}
|
||||
|
||||
// ReportBadHeader -
|
||||
func (hd *HeaderDownload) ReportBadHeader(headerHash common.Hash) {
|
||||
hd.lock.Lock()
|
||||
defer hd.lock.Unlock()
|
||||
hd.badHeaders[headerHash] = struct{}{}
|
||||
}
|
||||
|
||||
func (hd *HeaderDownload) IsBadHeader(headerHash common.Hash) bool {
|
||||
hd.lock.RLock()
|
||||
defer hd.lock.RUnlock()
|
||||
_, ok := hd.badHeaders[headerHash]
|
||||
return ok
|
||||
}
|
||||
|
||||
// FindAnchors attempts to find anchors to which given chain segment can be attached to
|
||||
func (hd *HeaderDownload) findAnchors(segment *ChainSegment) (found bool, start int) {
|
||||
// Walk the segment from children towards parents
|
||||
@ -561,7 +575,7 @@ func (hd *HeaderDownload) InsertHeaders(hf func(header *types.Header, blockHeigh
|
||||
hd.insertList = hd.insertList[:len(hd.insertList)-1]
|
||||
skip := false
|
||||
if !link.preverified {
|
||||
if _, bad := hd.BadHeaders[link.hash]; bad {
|
||||
if _, bad := hd.badHeaders[link.hash]; bad {
|
||||
skip = true
|
||||
} else if err := hd.engine.VerifyHeader(hd.headerReader, link.header, true /* seal */); err != nil {
|
||||
log.Warn("Verification failed for header", "hash", link.header.Hash(), "height", link.blockHeight, "error", err)
|
||||
|
@ -167,7 +167,7 @@ type CalcDifficultyFunc func(childTimestamp uint64, parentTime uint64, parentDif
|
||||
|
||||
type HeaderDownload struct {
|
||||
lock sync.RWMutex
|
||||
BadHeaders map[common.Hash]struct{}
|
||||
badHeaders map[common.Hash]struct{}
|
||||
anchors map[common.Hash]*Anchor // Mapping from parentHash to collection of anchors
|
||||
preverifiedHashes map[common.Hash]struct{} // Set of hashes that are known to belong to canonical chain
|
||||
preverifiedHeight uint64 // Block height corresponding to the last preverified hash
|
||||
@ -203,7 +203,7 @@ func NewHeaderDownload(
|
||||
) *HeaderDownload {
|
||||
persistentLinkLimit := linkLimit / 16
|
||||
hd := &HeaderDownload{
|
||||
BadHeaders: make(map[common.Hash]struct{}),
|
||||
badHeaders: make(map[common.Hash]struct{}),
|
||||
anchors: make(map[common.Hash]*Anchor),
|
||||
persistedLinkLimit: persistentLinkLimit,
|
||||
linkLimit: linkLimit - persistentLinkLimit,
|
||||
|
@ -51,7 +51,7 @@ func TestSplitIntoSegments(t *testing.T) {
|
||||
}
|
||||
|
||||
// Single header with a bad hash
|
||||
hd.BadHeaders[h.Hash()] = struct{}{}
|
||||
hd.ReportBadHeader(h.Hash())
|
||||
if chainSegments, penalty, err := hd.SplitIntoSegments([][]byte{{}}, []*types.Header{&h}); err == nil {
|
||||
if penalty != BadBlockPenalty {
|
||||
t.Errorf("expected BadBlock penalty, got %s", penalty)
|
||||
@ -166,7 +166,7 @@ func TestSingleHeaderAsSegment(t *testing.T) {
|
||||
}
|
||||
|
||||
// Same header with a bad hash
|
||||
hd.BadHeaders[h.Hash()] = struct{}{}
|
||||
hd.ReportBadHeader(h.Hash())
|
||||
if chainSegments, penalty, err := hd.SingleHeaderAsSegment([]byte{}, &h); err == nil {
|
||||
if penalty != BadBlockPenalty {
|
||||
t.Errorf("expected BadBlock penalty, got %s", penalty)
|
||||
|
@ -384,7 +384,7 @@ func (ms *MockSentry) InsertChain(chain *core.ChainPack) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, bad := ms.downloader.Hd.BadHeaders[chain.TopBlock.Hash()]; bad {
|
||||
if ms.downloader.Hd.IsBadHeader(chain.TopBlock.Hash()) {
|
||||
return fmt.Errorf("block %d %x was invalid", chain.TopBlock.NumberU64(), chain.TopBlock.Hash())
|
||||
}
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user