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