From 4668a93150798d27e28f501d0e3a04819c8690db Mon Sep 17 00:00:00 2001 From: cuiweixie Date: Thu, 11 Jun 2026 20:00:00 +0800 Subject: [PATCH] core/types: reset Log.Removed in Receipt.DeriveFields DeriveFields rewrites every canonical inclusion field on each log (BlockNumber, BlockHash, BlockTimestamp, TxHash, TxIndex, Index) but left the transient Removed flag untouched. A canonically-included log is by definition not removed, so derivation should drive Removed back to false just like the other derived fields. This is a defensive consistency fix rather than a fix for a presently reachable bug. The only place Removed is set to true is collectReceiptsAndLogs, which operates on fresh receipts read via ReadRawReceipts (Removed is rlp:"-", so always decoded as false), derives fields before flagging removal, and discards those objects after emitting the reorg event. They are never cached or re-derived, and the cached receipts are separate instances, so no Removed==true log currently reaches DeriveFields. Resetting the flag here hardens the function against a reused/stale log object regardless of the calling path. --- core/types/receipt.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/types/receipt.go b/core/types/receipt.go index ba7d9900f0..b4ed5bcace 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -308,6 +308,10 @@ func (r *Receipt) DeriveFields(signer Signer, context DeriveReceiptContext) { r.Logs[j].TxHash = r.TxHash r.Logs[j].TxIndex = context.TxIndex r.Logs[j].Index = logIndex + // A canonically-included log is by definition not removed; reset the + // transient Removed flag so a reused log object can't carry a stale + // reorg marking into a canonical receipt. + r.Logs[j].Removed = false logIndex++ } // Also derive the Bloom if not derived yet