fix(engine): log self-built block verification failures instead of dropping them silently

A block the engine builds itself that fails its own Verify() was dropped with a bare
continue — no log at any level. Because the VM re-notifies while its txs remain in the
mempool, the engine rebuilds and re-drops indefinitely: an invisible hot loop (observed
4.07M consecutive 'built block' lines with the chain stuck at height 1 and zero errors
logged). Dropping an unverifiable block is correct; doing it silently is not.
This commit is contained in:
zeekay
2026-07-15 12:46:35 -07:00
parent c4581d40ea
commit 30f44fbc0f
+13
View File
@@ -3798,6 +3798,19 @@ func (t *Transitive) buildBlocksLocked(ctx context.Context) error {
// is never added to consensus, so IsAccepted cannot return true for it.
t.mu.Unlock()
if err := vmBlock.Verify(ctx); err != nil {
// A block we built ourselves that fails its OWN verification is a real fault
// (VM state, proposer/epoch rule, timestamp window...). Dropping it silently left
// the node in an INVISIBLE HOT LOOP: the VM keeps re-notifying while its txs sit in
// the mempool, so the engine rebuilds → drops → rebuilds forever — no block ever
// enters consensus and NOT ONE log line says why (observed: 4.07M consecutive
// "built block" lines, chain stuck at height 1, zero errors logged). The drop itself
// is correct (an unverifiable block must never reach consensus); the SILENCE is the
// bug. Log the fault so it is diagnosable at the point of failure.
t.log.Error("built block failed verification — dropping",
"blkID", vmBlock.ID(),
"height", vmBlock.Height(),
"parentID", vmBlock.ParentID(),
"error", err)
t.mu.Lock()
continue
}