Skip to content

fix(#123): --devnet-head-poll-interval knob + auto-match block cadence (findings 8+9)#127

Merged
Reiers merged 1 commit into
mainfrom
fix/devnet-head-poll-interval
Jul 12, 2026
Merged

fix(#123): --devnet-head-poll-interval knob + auto-match block cadence (findings 8+9)#127
Reiers merged 1 commit into
mainfrom
fix/devnet-head-poll-interval

Conversation

@Reiers

@Reiers Reiers commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Closes the last two findings from #123: ChainHead and eth_blockNumber head lag on single-node docker devnet.

The problem

On a single-node docker devnet the gossipsub mesh can't form (no peers), so ChainHead and eth_blockNumber arrive ONLY via the RPC-fallback poll. The mainnet-oriented 30s cadence set by startGossipHead (and its cmd/lantern twin) is 7.5x block-time on a 4s-epoch devnet, so head trails live by ~80 epochs = ~320s at all times. Breaks any timing-sensitive consumer (curio schedulers, proving-window logic, latency-sensitive read-your-write patterns).

The fix

On devnet, the daemon derives the effective poll interval from build.GetDevnetConfig().BlockDelaySecs (captured at devnet-init time by #125), falling back to 4s if the config is absent or predates #125.

  • New CLI flag --devnet-head-poll-interval (cmd/lantern) — zero means auto (derive from config), nonzero overrides.
  • New embedded field Config.DevnetHeadPollInterval (pkg/daemon) — same semantics for consumers like curio-core.

Both consumer paths gated on network == build.Devnet. Mainnet + calibration paths untouched.

Live evidence

Curio-fork docker devnet at height 17798+, tested via alternating Filecoin.ChainHead on lotus (127.0.0.1:1234) vs Lantern (127.0.0.1:2348):

Cold boot, default (sync every 4s from BlockDelaySecs):

t lotus lantern lag
10s 17798 17794 4 epochs
20s 17800 17796 4 epochs
30s 17803 17796 7 epochs
40s 17805 17799 6 epochs
50s 17808 17803 5 epochs
60s 17810 17803 7 epochs

Sustained lag: 4-7 epochs. Pre-fix baseline (from #123 finding 8+9): ~80 epochs sustained.

With user override --devnet-head-poll-interval 2s:

Boot log confirms: header store: ... (sync every 2s, buf=64). Lag stays in 5-8 epochs; the remaining floor comes from other Sync knobs (BootstrapDepth, MaxBacktrack), not poll interval. Poll cadence itself is the correct value.

Blast radius

Tests

No new unit tests: the change is a single conditional on network == build.Devnet gating a derived value, and existing devnet-init tests already cover the BlockDelaySecs field. go test ./... reports 52 packages ok.

What's left from #123 followups

Closes lantern#123 findings 8+9. On a single-node docker devnet the
gossipsub mesh can't form, so ChainHead + eth_blockNumber arrive ONLY
via the RPC-fallback poll. The mainnet-oriented 30s cadence set by
startGossipHead (and its cmd/lantern twin) is 7.5x block-time on a
4s-epoch devnet, so head trails live by ~80 epochs = ~320s at all
times \u2014 breaks any timing-sensitive consumer (curio schedulers,
proving-window logic, latency-sensitive read-your-write patterns).

On devnet, the daemon now derives the effective poll interval from
build.GetDevnetConfig().BlockDelaySecs (captured at devnet-init time
by #125), falling back to 4s if the config is absent or older than
#125. Operators can override with --devnet-head-poll-interval (CLI)
or Config.DevnetHeadPollInterval (embedded).

Mainnet + calibration paths are untouched: the gossip-primary logic
(30s catch-up cadence when libp2p is enabled) still runs; only when
network == build.Devnet does the derivation fire.

Applied to both consumer paths:
  - cmd/lantern/main.go   (standalone `lantern daemon` CLI)
  - pkg/daemon/start.go   (embedded consumers like curio-core)

Live smoke, curio-fork docker devnet at height 17798+:

  Cold-boot head lag (default, sync every 4s):
    t=10s   lotus=17798  lantern=17794  lag= 4 epochs
    t=30s   lotus=17803  lantern=17796  lag= 7 epochs
    t=60s   lotus=17810  lantern=17803  lag= 7 epochs

  With --devnet-head-poll-interval 2s (user override honored):
    Boot log: "header store: ... (sync every 2s, buf=64)"

  Pre-fix baseline (from #123 finding 8+9): ~80 epochs sustained.

Full suite: go test ./... reports 52 packages ok, no failures.
@Reiers Reiers merged commit 0600fa4 into main Jul 12, 2026
1 check passed
@Reiers Reiers deleted the fix/devnet-head-poll-interval branch July 12, 2026 12:12
@Reiers Reiers mentioned this pull request Jul 14, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant