1
0
Fork 0
forked from forks/go-ethereum

core/filtermaps: make ChainView thread safe (#31671)

This PR makes `filtermaps.ChainView` thread safe because it is used
concurrently both by the indexer and multiple matcher threads. Even
though it represents an immutable view of the chain, adding a mutex lock
to the `blockHash` function is necessary because it does so by extending
its list of non-canonical hashes if the underlying blockchain is
changed.

The unsafe concurrency did cause a panic once after running the unit
tests for several hours and it could also happen during live operation.
This commit is contained in:
Felföldi Zsolt 2025-04-18 14:00:11 +02:00 committed by GitHub
parent 2e0ad2cb4d
commit 4c9e7d1b18
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -17,6 +17,8 @@
package filtermaps
import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
@ -39,6 +41,7 @@ type blockchain interface {
// of the underlying blockchain, it should only possess the block headers
// and receipts up until the expected chain view head.
type ChainView struct {
lock sync.Mutex
chain blockchain
headNumber uint64
hashes []common.Hash // block hashes starting backwards from headNumber until first canonical hash
@ -147,6 +150,9 @@ func (cv *ChainView) extendNonCanonical() bool {
// blockHash returns the given block hash without doing the head number check.
func (cv *ChainView) blockHash(number uint64) common.Hash {
cv.lock.Lock()
defer cv.lock.Unlock()
if number+uint64(len(cv.hashes)) <= cv.headNumber {
hash := cv.chain.GetCanonicalHash(number)
if !cv.extendNonCanonical() {