Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,14 @@ type BlockChain struct {
// Readers don't need to take it, they can just read the database.
chainmu *syncx.ClosableMutex

currentBlock atomic.Pointer[types.Header] // Current head of the chain
currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block
currentSafeBlock atomic.Pointer[types.Header] // Latest (consensus) safe block
currentUnsealedBlock *types.UnsealedBlock // Current unsealed block
unsealedBlockDbState *state.StateDB // StateDB for the current unsealed block
currentBlock atomic.Pointer[types.Header] // Current head of the chain
currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
currentFinalBlock atomic.Pointer[types.Header] // Latest (consensus) finalized block
currentSafeBlock atomic.Pointer[types.Header] // Latest (consensus) safe block

currentUnsealedBlock *types.UnsealedBlock // Current unsealed block
unsealedBlockDbState *state.StateDB // StateDB for the current unsealed block
unsealedBlockLock sync.Mutex // Lock for the unsealedBlock

bodyCache *lru.Cache[common.Hash, *types.Body]
bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue]
Expand Down Expand Up @@ -2551,3 +2553,8 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
return time.Duration(bc.flushInterval.Load())
}

// UnsealedBlockLock returns a pointer to the unsealed block lock
func (bc *BlockChain) UnsealedBlockLock() *sync.Mutex {
return &bc.unsealedBlockLock
}
13 changes: 10 additions & 3 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,16 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B

// Latest state is the current open unselaed block
if number == rpc.LatestBlockNumber {
stateDb := b.eth.BlockChain().CurrentUnsealedBlockState()
if stateDb != nil {
return stateDb, b.eth.BlockChain().CurrentUnsealedBlock().TempHeader(), nil
// if the lock is held, we can't access the unsealed block
if b.eth.BlockChain().UnsealedBlockLock().TryLock() {
defer b.eth.BlockChain().UnsealedBlockLock().Unlock()

stateDb := b.eth.BlockChain().CurrentUnsealedBlockState()
if stateDb != nil {
return stateDb.Copy(), b.eth.BlockChain().CurrentUnsealedBlock().TempHeader(), nil
}
} else {
log.Warn("unsealed block lock is held, falling back to latest state")
}
}

Expand Down
13 changes: 6 additions & 7 deletions eth/catalyst/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ type ConsensusAPI struct {
forkchoiceLock sync.Mutex // Lock for the forkChoiceUpdated method
newPayloadLock sync.Mutex // Lock for the NewPayload method

unsealedBlockLock sync.Mutex // Lock for the unsealedBlock
}

// NewConsensusAPI creates a new consensus api for the given backend.
Expand Down Expand Up @@ -1357,13 +1356,13 @@ func validateRequests(requests [][]byte) error {
func (api *ConsensusAPI) NewFragV0(frag engine.SignedNewFrag) (string, error) {
log.Info("new frag received", "forBlock", frag.Frag.BlockNumber, "current", api.eth.BlockChain().CurrentBlock().Number)

api.unsealedBlockLock.Lock()
api.eth.BlockChain().UnsealedBlockLock().Lock()
res, err := api.newFragV0(frag)
if err != nil {
log.Error("failed to insert new frag, discarding unsealed block", "error", err)
api.eth.BlockChain().ResetCurrentUnsealedBlock()
}
api.unsealedBlockLock.Unlock()
api.eth.BlockChain().UnsealedBlockLock().Unlock()

log.Info("new frag handled successfully")

Expand Down Expand Up @@ -1445,13 +1444,13 @@ func (api *ConsensusAPI) SealFragV0(seal engine.SignedSeal) (string, error) {
return engine.VALID, nil
}

api.unsealedBlockLock.Lock()
api.eth.BlockChain().UnsealedBlockLock().Lock()
res, err := api.sealFragV0(seal)
if err != nil {
log.Error("failed to seal block, discarding unsealed block", "error", err)
api.eth.BlockChain().ResetCurrentUnsealedBlock()
}
api.unsealedBlockLock.Unlock()
api.eth.BlockChain().UnsealedBlockLock().Unlock()

return res, err
}
Expand Down Expand Up @@ -1521,14 +1520,14 @@ func (api *ConsensusAPI) ValidateSealFragV0(preSealedBlock *types.Block, seal en
func (api *ConsensusAPI) EnvV0(env engine.SignedEnv) (string, error) {
log.Info("env received", "forBlock", env.Env.Number, "current", api.eth.BlockChain().CurrentBlock().Number, "env", env.Env)

api.unsealedBlockLock.Lock()
api.eth.BlockChain().UnsealedBlockLock().Lock()
res, err := api.envV0(env)
if err != nil {
log.Error("failed to open unsealed block, discarding unsealed block", "error", err)
api.eth.BlockChain().ResetCurrentUnsealedBlock()
log.Error("EnvV0 failed", "error", err)
}
api.unsealedBlockLock.Unlock()
api.eth.BlockChain().UnsealedBlockLock().Unlock()

log.Info("env handled successfully")

Expand Down