Skip to content

feat(node): layer1 verify-mode skips tendermint + own metrics server#974

Merged
tomatoishealthy merged 9 commits into
feat/sequencer-finalfrom
feat/single-metrics-server
Jun 4, 2026
Merged

feat(node): layer1 verify-mode skips tendermint + own metrics server#974
tomatoishealthy merged 9 commits into
feat/sequencer-finalfrom
feat/single-metrics-server

Conversation

@curryxbo
Copy link
Copy Markdown
Contributor

@curryxbo curryxbo commented Jun 4, 2026

Summary

  • Layer1 verify mode skips tendermint — fullnodes started with `--derivation.verify-mode=layer1` no longer spin up a no-op tendermint replica behind derivation. Sequencer mode (signer != nil) and default `local` mode are unchanged.
  • Layer1 mode brings its own /metrics listener — without tmnode, no `:26660` exists. main.go starts a small promhttp server on `tmCfg.Instrumentation.PrometheusListenAddr` so derivation/sync metrics stay scrape-able. Other modes inherit `/metrics` from tendermint exactly as before; `tmCfg.Instrumentation` is never overridden by the node.
  • Default Confirmations 10 (was `rpc.SafeBlockNumber`). Lower lag, paired with the always-on L1 reorg detector (SPEC-005 §4.7.6) so deeper reorgs are still recoverable.
  • Drop dead morphnode flags — `--metrics-server-enable / --metrics-hostname / --metrics-port` (the derivation-internal listener was the only consumer; layer1 uses tendermint's listen-addr now) and the unused `--l1.chain-id`.
  • Misc derivation cleanups — `DefaultFetchBlockRange` 100→500 on the derivation path (sync stays 100; CommitBatch event filter is small); `baseHeight` defaults to current L2 head when unset; drop the dead `L1Confirmations` branch in `derivation.SetCliContext` (`sync.Config` still owns that flag).

Mode matrix

Mode tendermint derivation /metrics
sequencer (`signer != nil`) skipped tendermint (config.toml)
fullnode local tendermint (config.toml)
fullnode layer1 skipped own listener on tendermint's listen-addr
mock skipped none (dev-only path, unchanged)

Operator-visible changes

  • Removed CLI flags / env vars: `--metrics-server-enable` (`MORPH_NODE_METRICS_SERVER_ENABLE`), `--metrics-hostname` (`MORPH_NODE_METRICS_HOSTNAME`), `--metrics-port` (`MORPH_NODE_METRICS_PORT`), `--l1.chain-id` (`MORPH_NODE_L1_CHAIN_ID`).
  • Metrics endpoint config consolidates onto tendermint's `config.toml`:
    ```
    [instrumentation]
    prometheus = true
    prometheus_listen_addr = ":26660"
    ```
  • Default `derivation.confirmations` shifted from `rpc.SafeBlockNumber` (-4, ~6 min lag) to `10` (~2 min). Operators can override with `--derivation.confirmations` (negative tags still accepted, e.g. `-3` for finalized).

Test plan

  • `go build ./...` and `go vet ./...` clean.
  • `go test ./node/derivation/...` passes.
  • Devnet: fullnode in default mode — confirm `:26660/metrics` returns both `tendermint_consensus_height` and `morphnode_derivation_*`.
  • Devnet: fullnode with `--derivation.verify-mode=layer1` — confirm tendermint is NOT bound (no PBFT logs, no `:26657` rpc), but `:26660/metrics` still serves `morphnode_derivation_`. `tendermint_` series will be empty (expected — no consensus running).
  • Sequencer node — confirm tendermint runs and `:26660/metrics` serves both prefixes.
  • Confirm scrape config in monitoring no longer references the removed CLI flags.

🤖 Generated with Claude Code

- Layer1 verify mode: skip tendermint setup for fullnodes (derivation
  alone reconstructs the chain from L1 batches/blobs). Sequencer mode
  (signer != nil) still starts tendermint as before.
- Single Prometheus endpoint owned by main.go, sourced from
  tmCfg.Instrumentation.PrometheusListenAddr (config.toml). Tendermint's
  own listener is force-disabled so the node never exposes two
  /metrics URLs serving the same DefaultGatherer set.
- Drop --metrics-server-enable / --metrics-hostname / --metrics-port
  flags and the Config.Metrics* fields; ops only needs config.toml's
  instrumentation block now.
- DefaultConfig.Confirmations: rpc.SafeBlockNumber -> 10. Pairs with the
  always-on L1 reorg detector (SPEC-005 §4.7.6) so a deeper reorg is
  still recoverable, while keeping derivation lag low.
- Drop the dead L1Confirmations branch in derivation.SetCliContext
  (sync still owns that flag); DerivationConfirmations remains the
  only override path for derivation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@curryxbo curryxbo requested a review from a team as a code owner June 4, 2026 07:48
@curryxbo curryxbo requested review from secmgt and removed request for a team June 4, 2026 07:48
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 4, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 34630b31-ed9c-493b-8707-fb213985d348

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/single-metrics-server

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

corey and others added 8 commits June 4, 2026 16:06
verify-mode is a derivation knob; combining it with a sequencer signer
is a misconfig, not a state to defend against. Letting the layer1 branch
match unconditionally surfaces the mistake as "tendermint never started"
instead of silently ignoring the flag and pretending nothing's wrong.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All nodes (node-0/1/2/3, sentry-node-0/1) now require MORPH_NODE_L1_SEQUENCER_CONTRACT
environment variable to initialize the L1 sequencer verifier component.

This is required by the new sequencer verification logic in PR 974 which uses
the L1Sequencer contract to verify block proposer identity during consensus.

Tested: All nodes start successfully and metrics endpoints are working.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…seHeight default

- Extract Confirmations=10 as a named const so the value lives next to
  the comment that explains it instead of being a magic number in
  DefaultConfig.
- Bump DefaultFetchBlockRange 100 -> 500 on the derivation path
  (sync.DefaultFetchBlockRange stays 100). The derivation eth_getLogs
  filter is just CommitBatch events, so a 500-block window stays small
  on the wire while cutting round-trips 5x during catch-up.
- Default baseHeight to the current L2 head when unset. baseHeight is
  the height below which stateRoot checks are skipped; pinning it to
  the live head means a fresh node only verifies blocks it derives
  from this point forward, instead of re-checking historical blocks
  against an empty rollup cursor.
- Drop the unused L1ChainID flag (no consumer in morphnode; the
  ops/l2-genesis copy is a separate package).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tmCfg.Instrumentation.Prometheus is overloaded inside tendermint:
DefaultMetricsProvider returns NopMetrics() when it's false, so
cs/p2p/sm/proxy collectors never register to prometheus.DefaultRegisterer.
The previous "Prometheus=false" approach silently dropped every
tendermint_consensus/p2p/state/proxy series from our unified endpoint —
not just the duplicate :26660 binding it was meant to suppress.

Switch to clearing PrometheusListenAddr instead. node.OnStart's HTTP-bind
guard (`Prometheus && addr != ""`) trips on the empty addr, but
DefaultMetricsProvider keeps the real Prometheus collectors. Capture the
operator's configured addr first so our top-level startMetricsServer
still serves on it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Walk back the global tmCfg.Instrumentation override. Local / sequencer /
mock paths inherit tendermint's :26660 listener exactly as upstream
configured it; only the layer1 fullnode path (where tmnode never starts)
brings up its own promhttp listener on the same address from config.toml.

Trades the "single mechanism in all modes" symmetry for a much smaller
blast radius: no risk of subtly altering what tendermint registers to
DefaultRegisterer in the modes that actually run consensus.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
In layer1 mode tendermint never starts, so its Instrumentation.Prometheus
flag has no semantic anchor — it gates a listener that doesn't exist
here. Let startMetricsServer's empty-addr fast-path be the single off
switch. Operators who want metrics off either leave the addr empty or
clear it explicitly; they shouldn't have to also flip a tendermint flag
that's otherwise irrelevant to this code path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@curryxbo curryxbo changed the title feat(node): single metrics endpoint + layer1 verify-mode tendermint skip feat(node): layer1 verify-mode skips tendermint + own metrics server Jun 4, 2026
@tomatoishealthy tomatoishealthy merged commit f3addb2 into feat/sequencer-final Jun 4, 2026
6 of 7 checks passed
@tomatoishealthy tomatoishealthy deleted the feat/single-metrics-server branch June 4, 2026 10:03
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.

2 participants