From 5850970e57f40bb6625a6ad3aeb019d72477aa67 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sun, 12 Apr 2026 01:52:19 +0200 Subject: [PATCH] core/state: fix typed nil panic in StopPrefetcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commitAndFlush discarded errors from db.Reader() and db.Hasher() at lines 1040-1041, storing the result directly into s.reader/s.hasher. When Hasher() fails (e.g. newBinaryHasher returns nil, err), Go wraps the nil *binaryHasher in the Hasher interface as a typed nil — an interface value {type: *binaryHasher, value: nil} that passes == nil checks. StopPrefetcher then type-asserts to Prefetcher (succeeds) and calls TermPrefetch on the nil receiver, panicking at h.trie.term(). Fix: propagate errors from Reader() and Hasher() in commitAndFlush instead of discarding them, and add defensive nil-receiver guards to both binaryHasher.TermPrefetch and merkleHasher.TermPrefetch. --- core/state/database_hasher_binary.go | 3 +++ core/state/database_hasher_merkle.go | 3 +++ core/state/statedb.go | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/core/state/database_hasher_binary.go b/core/state/database_hasher_binary.go index 0e843d31ff..c12a9ab6b0 100644 --- a/core/state/database_hasher_binary.go +++ b/core/state/database_hasher_binary.go @@ -387,5 +387,8 @@ func (h *binaryHasher) PrefetchStorage(addr common.Address, keys []common.Hash, // TermPrefetch terminates all prefetcher goroutines. Safe to call multiple times. func (h *binaryHasher) TermPrefetch() { + if h == nil { + return + } h.trie.term() } diff --git a/core/state/database_hasher_merkle.go b/core/state/database_hasher_merkle.go index cd99a4cc9a..fa39df887c 100644 --- a/core/state/database_hasher_merkle.go +++ b/core/state/database_hasher_merkle.go @@ -457,6 +457,9 @@ func (h *merkleHasher) PrefetchStorage(addr common.Address, keys []common.Hash, // TermPrefetch terminates all prefetcher goroutines. Safe to call multiple times. func (h *merkleHasher) TermPrefetch() { + if h == nil { + return + } h.acctTrie.term() for _, tr := range h.storageTries { tr.term() diff --git a/core/state/statedb.go b/core/state/statedb.go index df4a6ec215..010c6768fa 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1040,8 +1040,18 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorag } s.DatabaseCommits = time.Since(start) - s.reader, _ = s.db.Reader(s.originalRoot) - s.hasher, _ = s.db.Hasher(s.originalRoot) + reader, err := s.db.Reader(s.originalRoot) + if err != nil { + return nil, err + } + s.reader = reader + + hasher, err := s.db.Hasher(s.originalRoot) + if err != nil { + return nil, err + } + s.hasher = hasher + return ret, nil }