mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
Pre-existing idle-builder wake race (not caused by QCv2): on a demand-driven C-Chain with no empty blocks, a tx arriving while no builder is parked in waitForNeedToBuild broadcasts pendingSignal to no waiter and is lost; the tx is then only caught on the NEXT needToBuild() poll, which — depending on the proposervm slot loop and engine re-call cadence — could leave the first tx after idle pending for a long/indefinite time (the mainnet treasury-sweep-stuck and v1.32.1 devnet DEXFill-didn't-complete symptoms). Fix: startPendingTxPoll — a node-lifetime ticker (builderPollInterval = 500ms) that periodically broadcasts pendingSignal so any parked builder re-evaluates needToBuild() against the live mempool. It is decomplected from the tx-submit subscription (awaitSubmittedTxs remains the primary, immediate wake) so the two wake sources are independent. It NEVER forces an empty block — a wake only produces a build when needToBuild() is true — so demand-driven chains stay empty-block-free, and it changes wake TIMING only, never block CONTENTS, so validators still build byte-identical blocks (deterministic). needToBuild now routes through an injectable pendingTxs predicate so the wake path is testable without a live txpool. Regression: TestBuilderWakesOnPendingTxAfterIdle reproduces the node bridge's exact waitForEvent call on an idle builder, delivers a pending tx with NO submit broadcast, and asserts it returns PendingTxs within a bounded deadline. It FAILS on the pre-fix code (times out — the lost wakeup) and passes after. TestBuilderPollBackstopStopsOnShutdown asserts the ticker exits cleanly. Builder tests green under -race. Co-authored-by: Hanzo Dev <[email protected]>