Skip to content

Commit 8a9f4bb

Browse files
Fix log indexer noise after debug_setHead operations (#31934)
## Summary This PR resolves Issue #31929 by reducing log noise generated by the log indexer after `debug_setHead` operations. ## Problem Description When `debug_setHead` is called to rewind the blockchain, blocks are removed from the database. However, the log indexer's `ChainView` objects may still hold references to these deleted blocks. When `extendNonCanonical()` attempts to access these missing headers, it results in: 1. **Repeated ERROR logs**: `Header not found number=X hash=0x...` 2. **Log noise** that can mask other important errors 3. **User confusion** about whether this indicates a real problem ## Root Cause Analysis The issue occurs because: - `debug_setHead` removes blocks from the blockchain database - Log indexer's `ChainView` may still reference deleted block hashes - `extendNonCanonical()` in `core/filtermaps/chain_view.go` tries to fetch these missing headers - The existing `return false` logic properly handles the error, but logs at ERROR level ## Solution This is a **logging improvement only** - no functional logic changes: ### Changes Made 1. **Log level**: Changed from `ERROR` to `DEBUG` 2. **Log message**: Enhanced with descriptive context about chain view extension 3. **Comments**: Added explanation for when this situation occurs 4. **Behavior**: Maintains existing error handling (`return false` was already present) ### Code Changes ```go // Before log.Error("Header not found", "number", number, "hash", hash) return false // After // Header not found - this can happen after debug_setHead operations // where blocks have been deleted. Return false to indicate the chain view // is no longer valid rather than logging repeated errors. log.Debug("Header not found during chain view extension", "number", number, "hash", hash) return false ``` ## Testing ### Automated Tests - ✅ All existing filtermaps tests pass: `go test ./core/filtermaps -v` - ✅ No regressions in related functionality ### Manual Verification 1. **Before fix**: Started geth in dev mode, generated blocks, called `debug_setHead(3)` → **5 repeated ERROR logs** 2. **After fix**: Same scenario → **4 DEBUG logs, no ERROR noise** ### Test Environment ```bash # Setup test environment rm -rf ./dev-test-data ./build/bin/geth --dev --datadir ./dev-test-data --http --http.api debug,eth,net,web3 --verbosity 4 # Generate test blocks and trigger issue curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"debug_setHead","params":["0x3"],"id":1}' http://localhost:8545 ``` ## Related Issues - Fixes #31929 ## Additional Context This issue was reported as spurious error messages appearing after `debug_setHead` operations. The investigation revealed that while the error handling was functionally correct, the ERROR log level was inappropriate for this expected scenario in development/debugging workflows. The fix maintains full compatibility while significantly improving the debugging experience for developers using `debug_setHead`. --------- Co-authored-by: Sun Tae, Kim <38067691+humblefirm@users.noreply.github.com> Co-authored-by: zsfelfoldi <zsfelfoldi@gmail.com>
1 parent 1f4ea4d commit 8a9f4bb

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

core/filtermaps/chain_view.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ func NewChainView(chain blockchain, number uint64, hash common.Hash) *ChainView
5555
headNumber: number,
5656
hashes: []common.Hash{hash},
5757
}
58-
cv.extendNonCanonical()
58+
if !cv.extendNonCanonical() {
59+
return nil
60+
}
5961
return cv
6062
}
6163

@@ -129,7 +131,11 @@ func (cv *ChainView) SharedRange(cv2 *ChainView) common.Range[uint64] {
129131
return common.Range[uint64]{}
130132
}
131133
var sharedLen uint64
132-
for n := min(cv.headNumber+1-uint64(len(cv.hashes)), cv2.headNumber+1-uint64(len(cv2.hashes))); n <= cv.headNumber && n <= cv2.headNumber && cv.blockHash(n) == cv2.blockHash(n); n++ {
134+
for n := min(cv.headNumber+1-uint64(len(cv.hashes)), cv2.headNumber+1-uint64(len(cv2.hashes))); n <= cv.headNumber && n <= cv2.headNumber; n++ {
135+
h1, h2 := cv.blockHash(n), cv2.blockHash(n)
136+
if h1 != h2 || h1 == (common.Hash{}) {
137+
break
138+
}
133139
sharedLen = n + 1
134140
}
135141
return common.NewRange(0, sharedLen)
@@ -153,10 +159,13 @@ func matchViews(cv1, cv2 *ChainView, number uint64) bool {
153159
if cv1.headNumber < number || cv2.headNumber < number {
154160
return false
155161
}
162+
var h1, h2 common.Hash
156163
if number == cv1.headNumber || number == cv2.headNumber {
157-
return cv1.BlockId(number) == cv2.BlockId(number)
164+
h1, h2 = cv1.BlockId(number), cv2.BlockId(number)
165+
} else {
166+
h1, h2 = cv1.BlockHash(number), cv2.BlockHash(number)
158167
}
159-
return cv1.BlockHash(number) == cv2.BlockHash(number)
168+
return h1 == h2 && h1 != common.Hash{}
160169
}
161170

162171
// extendNonCanonical checks whether the previously known reverse list of head
@@ -175,7 +184,10 @@ func (cv *ChainView) extendNonCanonical() bool {
175184
}
176185
header := cv.chain.GetHeader(hash, number)
177186
if header == nil {
178-
log.Error("Header not found", "number", number, "hash", hash)
187+
// Header not found - this can happen after debug_setHead operations
188+
// where blocks have been deleted. Return false to indicate the chain view
189+
// is no longer valid rather than logging repeated errors.
190+
log.Debug("Header not found during chain view extension", "number", number, "hash", hash)
179191
return false
180192
}
181193
cv.hashes = append(cv.hashes, header.ParentHash)

0 commit comments

Comments
 (0)