@@ -44,6 +44,8 @@ type Blockchain struct {
4444 previousHeaderHash common.Hash
4545 latestCtx sdk.Context
4646 mu sync.RWMutex
47+
48+ testingCommitMu sync.RWMutex
4749}
4850
4951// NewBlockchain creates a new Blockchain instance that bridges Cosmos SDK state with Ethereum mempools.
@@ -211,13 +213,34 @@ func (b *Blockchain) StateAt(hash common.Hash) (vm.StateDB, error) {
211213 return nil , fmt .Errorf ("failed to get latest context for StateAt: %w" , err )
212214 }
213215
214- appHash := ctx .BlockHeader ().AppHash
215- stateDB := statedb .New (ctx , b .vmKeeper , statedb .NewEmptyTxConfig ())
216+ // Create a cache context to isolate the StateDB from concurrent commits.
217+ // This prevents race conditions when the background txpool reorg goroutine
218+ // reads state while the main thread is committing new blocks.
219+ cacheCtx , _ := ctx .CacheContext ()
220+ // Use an infinite gas meter to avoid tracking gas for read-only state queries
221+ cacheCtx = cacheCtx .WithGasMeter (sdktypes .NewInfiniteGasMeter ())
222+
223+ appHash := cacheCtx .BlockHeader ().AppHash
224+ stateDB := statedb .New (cacheCtx , b .vmKeeper , statedb .NewEmptyTxConfig ())
216225
217226 b .logger .Debug ("StateDB created successfully" , "app_hash" , common .Hash (appHash ).Hex ())
218227 return stateDB , nil
219228}
220229
230+ // BeginCommit acquires an exclusive lock to prevent mempool state reads during Commit.
231+ // This avoids data races in the underlying storage (e.g., IAVL) when tests run with -race.
232+ func (b * Blockchain ) BeginCommit () { b .testingCommitMu .Lock () }
233+
234+ // EndCommit releases the exclusive lock acquired by BeginCommit.
235+ func (b * Blockchain ) EndCommit () { b .testingCommitMu .Unlock () }
236+
237+ // BeginRead acquires a shared lock for background readers (e.g., txpool reorg).
238+ // This enables optional coordination with Commit without importing the type.
239+ func (b * Blockchain ) BeginRead () { b .testingCommitMu .RLock () }
240+
241+ // EndRead releases the shared read lock acquired by BeginRead.
242+ func (b * Blockchain ) EndRead () { b .testingCommitMu .RUnlock () }
243+
221244func (b * Blockchain ) getPreviousHeaderHash () common.Hash {
222245 b .mu .RLock ()
223246 defer b .mu .RUnlock ()
0 commit comments