fix(core/txpool): subscribe to head events in New and release on Init error #35048 - #2543
fix(core/txpool): subscribe to head events in New and release on Init error #35048#2543gzliudan wants to merge 2 commits into
Conversation
dad2f5f to
581cee2
Compare
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Moves txpool head-event subscription into construction to prevent missed events and stale nonce state.
Changes:
- Subscribes synchronously in
txpool.New. - Adds regression coverage for immediate block insertion.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
core/txpool/txpool.go |
Moves head subscription into the constructor. |
core/txpool/txpool_head_event_test.go |
Tests immediate head-event delivery and transaction acceptance. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
26138cc to
9b5b77e
Compare
…eum#35048 The pool subscribed to chain head events only after its loop goroutine started, so a head event emitted by InsertChain right after New could be missed. The pool then reset against a stale head, keeping pending nonces at genesis and rejecting fresh transactions as ErrNonceTooHigh (this also caused the TestResubmit/TestJournal flakes). Move the subscription into New so events are captured from the start, and add TestHeadEventDeliveredAfterNew which waits for the pool to observe the head inserted right after New.
9b5b77e to
a445d13
Compare
New subscribes to chain head events before the fallible SubPool.Init calls. When Init fails, New returns without starting the loop, so the loop's deferred Unsubscribe never runs and the chain feed stays subscribed to an unconsumed, unbuffered channel; a later head publication can block until the whole blockchain is stopped. Unsubscribe on this error path before returning, and add TestNewUnsubscribesOnInitError which fails if the subscription is leaked.
a445d13 to
c2ca613
Compare
Summary
Fixes lost chain head events in the txpool that left the pool resetting against a stale head, rejecting fresh transactions as
ErrNonceTooHigh(this also caused sporadicTestResubmit/TestJournalflakes on CI).Ref: ethereum#35048
Root cause
The pool subscribed to chain head events only after its
loopgoroutine started:Because the subscription is established asynchronously, a head event emitted by
InsertChainright afterNewcould be missed. The pool then reset against a stale head, keeping pending nonces at genesis (nonce 0); transactions built on the new chain nonce were rejected withErrNonceTooHigh.Fix
New(matching upstream geth):newHeadCh/newHeadSubbecomeTxPoolfields andchain.SubscribeChainHeadEventis called before any block can be inserted, so head events are never lost.Newsubscribes before the fallibleSubPool.Initcalls; ifInitfails,Newreturns without starting the loop, so the loop's deferredUnsubscribenever runs and the chain feed stays subscribed to an unconsumed, unbuffered channel — a later head publication can block until the chain is stopped. The error path now unsubscribes before returning.Tests
TestHeadEventDeliveredAfterNew: inserts blocks right afterNewand waits for the pool's pending nonce to advance to the new head — it times out if the head event is lost.TestNewUnsubscribesOnInitError: forces aSubPool.Initfailure and asserts the head event subscription is released (fails if leaked).Upstream reference
Aligns the head-event subscription with upstream geth commit
b71f75091(core, core/txpool, eth: move subscriptions to constructor, ethereum#35048; closes ethereum#20554). XDPoSChain was still on the pre-ethereum#35048 shape where the loop subscribed asynchronously inside its goroutine. The Init-failure release goes beyond upstream, fixing a leak also present in geth's current shape.Verification
core/txpool: full package passes;TestHeadEventDeliveredAfterNewandTestNewUnsubscribesOnInitErrorpass repeated runs under-coverand-race;core/txpool/locals: 100 consecutive runs under-coverall pass (theTestResubmit/TestJournalflakes were rooted in this head-event loss).Compatibility
Internal txpool concurrency control only; no protocol, RPC, or state-transition changes.