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:
parent
2e0ad2cb4d
commit
4c9e7d1b18
1 changed files with 6 additions and 0 deletions
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue