Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,27 @@ are byte-identical to pre-change behaviour.
hinting `lantern devnet-init --force` to re-capture from the running
lotus.

Not in this PR: `ChainHead` head-poll lag on devnet ([#123](https://github.com/Reiers/lantern/issues/123)
findings 8+9). Folding it into a separate `--devnet-head-poll-interval`
knob PR.
Not in this PR: standalone `cmd/lantern` mpool wiring baseline (a
pre-existing gap discovered during the live-smoke run for this PR).

### Devnet: `--devnet-head-poll-interval` knob (closes [#123](https://github.com/Reiers/lantern/issues/123) findings 8+9)

- **Devnet header-store poll interval now defaults to match block
cadence instead of the mainnet 30s.** On a single-node docker devnet
the gossipsub mesh can't form, so head arrives ONLY via RPC polling;
the mainnet-oriented 30s cadence lags a 4s-epoch devnet by ~7x block
time (finding 8+9 originally documented lags of ~80 epochs = ~320s).
On devnet, the daemon now derives the poll interval from
`build.GetDevnetConfig().BlockDelaySecs` (captured at devnet-init time
by [#125](https://github.com/Reiers/lantern/pull/125)), falling back to 4s if unavailable.
Live smoke: cold-boot head lag dropped from ~80 epochs to 4-7 epochs
sustained (~10x improvement).

- **New `--devnet-head-poll-interval` flag** (cmd/lantern) +
`Config.DevnetHeadPollInterval` field (pkg/daemon) let operators
override the derived cadence. Zero (default) means auto: read from
`BlockDelaySecs`. Ignored on mainnet / calibration (the gossip-primary
cadence logic stays untouched there).

### Devnet: bridge-first read ordering for eth_* (closes [#123](https://github.com/Reiers/lantern/issues/123) finding 7)

Expand Down
19 changes: 19 additions & 0 deletions cmd/lantern/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ func cmdDaemon(args []string) error {
noHS := fs.Bool("no-header-store", false, "Disable the persistent header store (legacy synthetic-head mode)")
hsPath := fs.String("header-store", "", "Header store BadgerDB path (default: <data-dir>/<network>/headerstore)")
syncInterval := fs.Duration("sync-interval", 6*time.Second, "Header-store sync poll interval")
devnetHeadPollInterval := fs.Duration("devnet-head-poll-interval", 0, "Devnet-only: override the header-store poll interval on devnet (default 0 = auto: use BlockDelaySecs from devnet-config, or 4s if unavailable). Fixes lantern#123 findings 8+9: a single-node docker devnet can't form a gossipsub mesh, so head updates come only from RPC polling; the mainnet-oriented 30s cadence lags a 4s-cadence devnet by ~7x block time. Ignored on mainnet/calibration.")
staleResetThreshold := fs.Int64("stale-reset-threshold", 2880, "Epochs behind live head past which a persisted header store re-anchors near live head instead of backfilling (#51). 0 disables. Chain state only; keys are never touched.")
notifyBufSize := fs.Int("notify-buf", headnotify.DefaultBufferSize, "ChainNotify per-subscriber buffer size")
p2pListen := fs.String("p2p-listen", "/ip4/0.0.0.0/tcp/0,/ip4/0.0.0.0/udp/0/quic-v1", "libp2p listen multiaddrs (comma-separated). Empty disables the libp2p host.")
Expand Down Expand Up @@ -1175,6 +1176,24 @@ func cmdDaemon(args []string) error {
if gossipEnabled && effSyncInterval == 6*time.Second {
effSyncInterval = 30 * time.Second
}
// lantern#123 findings 8+9: on devnet, a single-node docker cluster
// can't form a gossipsub mesh, so head arrives ONLY via polling. The
// mainnet-oriented 30s cadence set above is 7.5x block-time on a
// 4s-epoch devnet. Override with the user's --devnet-head-poll-interval
// flag if set, otherwise derive from the devnet-config BlockDelaySecs
// (captured at devnet-init time by #125), falling back to 4s.
if network == build.Devnet {
switch {
case *devnetHeadPollInterval > 0:
effSyncInterval = *devnetHeadPollInterval
default:
cadence := 4 * time.Second
if devnetCfg := build.GetDevnetConfig(); devnetCfg != nil && devnetCfg.BlockDelaySecs > 0 {
cadence = time.Duration(devnetCfg.BlockDelaySecs) * time.Second
}
effSyncInterval = cadence
}
}
sync = hstore.NewSync(store, src, hstore.SyncOptions{
Interval: effSyncInterval,
MaxBacktrack: 60,
Expand Down
11 changes: 11 additions & 0 deletions pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,17 @@ type Config struct {
// SyncInterval is the header-store poll cadence. Default 6s.
SyncInterval time.Duration

// DevnetHeadPollInterval, when > 0, overrides the header-store poll
// cadence on devnet only. Zero (default) means auto: use
// build.GetDevnetConfig().BlockDelaySecs (persisted by
// `lantern devnet-init`), or 4s if unavailable. Fixes lantern#123
// findings 8+9: a single-node docker devnet can't form a gossipsub
// mesh, so head arrives ONLY via RPC polling; the mainnet-oriented
// 30s cadence lags a 4s-epoch devnet by ~7x block time. Ignored on
// mainnet + calibration (SyncInterval / gossip logic is unchanged
// there).
DevnetHeadPollInterval time.Duration

// PersistentCache enables the on-disk (Badger) block cache instead of
// the in-memory MemBlockStore. This is the PDP / mid-node tier: the warm
// contract subtrees (PDP/payments/registry/USDFC) SURVIVE restart, so a
Expand Down
18 changes: 18 additions & 0 deletions pkg/daemon/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,24 @@ func (d *Daemon) startInternal(ctx context.Context) error {
if libp2pEnabled {
syncInterval = 30 * time.Second
}
// lantern#123 findings 8+9: on devnet, a single-node docker cluster
// can't form a gossipsub mesh, so head arrives ONLY via polling. The
// mainnet-oriented 30s cadence set above is 7.5x block-time on a 4s
// devnet. Honor an explicit DevnetHeadPollInterval override, otherwise
// derive from the devnet-config BlockDelaySecs (captured at
// devnet-init time by #125), falling back to 4s.
if network == build.Devnet {
switch {
case d.cfg.DevnetHeadPollInterval > 0:
syncInterval = d.cfg.DevnetHeadPollInterval
default:
cadence := 4 * time.Second
if devnetCfg := build.GetDevnetConfig(); devnetCfg != nil && devnetCfg.BlockDelaySecs > 0 {
cadence = time.Duration(devnetCfg.BlockDelaySecs) * time.Second
}
syncInterval = cadence
}
}

// Issue #33: the hardened Sync resumes catch-up contiguously from
// currentHead+1 in CatchUpChunk-sized steps (never skips epochs),
Expand Down
Loading