Skip to content

cmd, ethconfig: consolidate flag reading and remove global statecfg side effects#20390

Merged
mh0lt merged 3 commits into
mainfrom
feat/componentization-config
Apr 8, 2026
Merged

cmd, ethconfig: consolidate flag reading and remove global statecfg side effects#20390
mh0lt merged 3 commits into
mainfrom
feat/componentization-config

Conversation

@mh0lt

@mh0lt mh0lt commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary

First step in the componentization series. Removes global side effects from flag
parsing and consolidates config construction:

  • Config snapshot tests: adds golden-file tests that capture the exact
    EthConfig produced by flag combinations, preventing accidental regressions
    as config wiring is refactored.

  • statecfg globals → config fields: moves statecfg.OverridePragueTime and
    similar package-level variables into EthConfig fields, eliminating
    init-order-dependent side effects during flag reading.

  • BuildEthConfig consolidation: introduces a single entry point for building
    EthConfig from CLI flags, replacing scattered calls across node setup.

These are safe, incremental refactors — no behavior changes, no new features.
Foundation for subsequent component extraction PRs.

Test plan

  • make lint clean
  • make erigon integration builds
  • Config snapshot tests pass
  • CI passes

mh0lt added 3 commits April 7, 2026 18:16
Add tests that capture the exact ethconfig.Config produced by the full
flag parsing pipeline (SetEthConfig + ApplyFlagsForEthConfig). These
tests serve as a safety net for the upcoming flag consolidation refactor:

- TestConfigDefaults: verifies default config values (no flags)
- TestConfigWithFlags: verifies 6 common flag combinations
- TestConfigSnapshotStability: JSON snapshot of full config for diff

Any change to the flag reading code that alters the resulting config
will cause these tests to fail with a clear diff.
SetEthConfig previously called statecfg.EnableHistoricalCommitment()
and set statecfg.ExperimentalConcurrentCommitment directly as side
effects of flag parsing. This made config non-deterministic — the same
config struct could produce different behavior depending on whether
it was built by SetEthConfig or constructed programmatically.

- Add ExperimentalConcurrentCommitment field to ethconfig.Sync
- Remove statecfg global writes from SetEthConfig (cmd/utils/flags.go)
- Apply globals from config fields in eth.New (single init point)
- Config fields are now the source of truth; globals are derived

The 80+ call sites that read statecfg.Schema are unchanged — they
still read the globals, which are now set from config in eth.New.
The ethconfig was previously built by two separate functions called
sequentially: utils.SetEthConfig() and erigoncli.ApplyFlagsForEthConfig().
The split was historical (erigon-lib vs turbo boundaries) and made it
unclear where a given flag was read.

Add BuildEthConfig() in node/cli that calls both in sequence, providing
a single entry point for flag-to-config mapping. NewEthConfigUrfave now
calls only BuildEthConfig.

ApplyFlagsForEthConfig is kept as a deprecated wrapper for the cobra-based
integration commands that call it independently.

The import direction (node/cli → cmd/utils) prevents consolidating the
other way. Flag definitions remain in their current packages.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors CLI flag → ethconfig.Config construction to a single entry point and moves statecfg global mutations out of flag parsing and into node startup, laying groundwork for future componentization.

Changes:

  • Introduces BuildEthConfig as the consolidated flag-to-config builder and updates node setup to use it.
  • Moves commitment/trie related statecfg global mutations from cmd/utils.SetEthConfig into node/eth.New based on config fields.
  • Adds config snapshot tests to exercise common flag combinations (and a new config field for concurrent commitment).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
node/ethconfig/config.go Adds ExperimentalConcurrentCommitment to Sync config.
node/eth/backend.go Applies config-driven statecfg globals during backend initialization.
node/cli/flags.go Adds BuildEthConfig and refactors eth flag application flow.
cmd/utils/flags.go Removes statecfg side effects from flag parsing; sets config fields instead.
cmd/erigon/node/node.go Switches eth config construction to BuildEthConfig.
cmd/erigon/node/config_snapshot_test.go Adds snapshot-style tests for config defaults and selected flag combos.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread node/eth/backend.go
Comment on lines +314 to +316
if config.ExperimentalConcurrentCommitment {
statecfg.ExperimentalConcurrentCommitment = true
}

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

statecfg.ExperimentalConcurrentCommitment is treated as config-driven global state, but it's only ever set to true here. If any earlier code path sets the global to true (e.g., tests/backtester/integration commands in the same process), starting a node with config.ExperimentalConcurrentCommitment == false will not restore the intended default. Consider assigning the global explicitly from the config (set to config.ExperimentalConcurrentCommitment) rather than conditionally setting it to true.

Suggested change
if config.ExperimentalConcurrentCommitment {
statecfg.ExperimentalConcurrentCommitment = true
}
statecfg.ExperimentalConcurrentCommitment = config.ExperimentalConcurrentCommitment

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +46
logger := log.Root()
nodeCfg := &nodecfg.Config{}
nodeCfg.Dirs.DataDir = t.TempDir()
ethCfg := ethconfig.Defaults
erigoncli.BuildEthConfig(ctx, nodeCfg, &ethCfg, logger)

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

The test initializes nodeCfg with an empty nodecfg.Config and only sets Dirs.DataDir. utils.SetEthConfig uses other Dirs fields (e.g., Dirs.Snap, Dirs.DataDir/logs) when building the downloader config, so leaving them empty can cause the snapshot tests to write/read from unexpected paths and/or emit errors. Prefer setting nodeCfg.Dirs = datadir.New(t.TempDir()) (or datadir.Open + dir.MustExist) to fully populate the directory layout used by production code.

Copilot uses AI. Check for mistakes.
Comment on lines +191 to +208
// TestConfigSnapshotStability creates a full JSON snapshot of the config
// from default flags. This test exists to detect ANY config field change
// during the consolidation refactor — if this test fails, the diff shows
// exactly which fields changed.
func TestConfigSnapshotStability(t *testing.T) {
cfg := buildEthConfig(t, nil)
snap := snapshotConfig(cfg)

// Marshal to JSON for readable diffs
got, err := json.MarshalIndent(snap, "", " ")
require.NoError(t, err)

// If this test fails during refactoring, the diff shows which field changed.
// Update the expected JSON only after verifying the change is intentional.
t.Logf("Config snapshot (update expected if intentional):\n%s", string(got))

// Verify key structural invariants rather than exact JSON match,
// since some defaults depend on runtime (CPU count, etc.)

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

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

This test is described as a "full JSON snapshot" / "detect ANY config field change" and the PR description mentions golden-file snapshot testing, but the implementation only logs JSON and asserts a small set of invariants. Either add an actual golden-file comparison (e.g., testdata/*.golden.json with an update workflow) or adjust the test name/comments to reflect that it's an invariant-based smoke test over a subset of fields.

Copilot uses AI. Check for mistakes.
@mh0lt mh0lt added this pull request to the merge queue Apr 8, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 8, 2026
@mh0lt mh0lt added this pull request to the merge queue Apr 8, 2026
Merged via the queue into main with commit dd05cc3 Apr 8, 2026
39 checks passed
@mh0lt mh0lt deleted the feat/componentization-config branch April 8, 2026 16:51
@mh0lt mh0lt restored the feat/componentization-config branch April 9, 2026 19:16
github-merge-queue Bot pushed a commit that referenced this pull request Apr 15, 2026
## Summary

Second PR in the componentization series (after #20390). Adds the core
component framework under `node/app/`:

- **Component lifecycle**: `node/app/component/` — typed components with
dependency tracking, hierarchical domains, and ordered
activation/deactivation
- **Event bus**: `node/app/event/` — typed publish/subscribe for
inter-component communication, replacing direct callback coupling
- **Worker pool**: `node/app/workerpool/` — work-stealing pool for
component task execution
- **Utilities**: `node/app/util/` — Result types, await helpers,
execution pool

This is a pure addition — no existing code is modified (except
go.mod/go.sum). The framework will be used by subsequent PRs to extract
backend.go subsystems (downloader, txpool, sentry, etc.) into
independent components.

Ported from the `app_components` branch, with the stale `erigon-lib`
test file removed.

## Test plan

- [x] `make lint` passes
- [x] `make erigon integration` builds
- [x] `go test ./node/app/...` — all component/event/workerpool tests
pass
- [ ] CI (unit tests, lint)

---------

Co-authored-by: Alexey Sharov <AskAlexSharov@gmail.com>
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.

3 participants