Skip to content

feat: allow loading external chain definitions at startup (e.g. NODECORE_EXTRA_CHAINS_PATH) #186

@robbeverhelst

Description

@robbeverhelst

Use case

We run nodecore in front of EVM-compatible upstreams that aren't in drpcorg/public and never will be — they're customer-specific private/consortium networks (e.g. Hyperledger Besu running with customer-assigned chain IDs). The list of public chains in pkg/chains/public/chains.yaml is exactly right as a default, but there's currently no way to extend it at runtime.

Why a config-only workaround isn't enough

We tried:

  • chain: ethereum + options.disable-chain-validation: true — works for most methods, but eth_chainId and net_version are marked "settings": {"local": true} in pkg/methods/specs/eth.json and answered locally from the chain registry. The response is the spoofed chain's id (e.g. 0x1), not the upstream's actual id. This breaks EIP-155 transaction signing for any client that does eth_chainId discovery (ethers / viem / web3.js / hardhat / foundry), which is essentially every modern client.
  • methods.disable: [eth_chainId] per-upstream — doesn't override the local: true behaviour. The method is still answered from the chain registry.

So with the current code there's no way to serve eth_chainId correctly for a chain that isn't in the embedded chains.yaml.

Proposal

Mirror the existing pattern in pkg/methods (NewMethodSpecLoaderWithFs(fs.FS)) on the chains side:

  1. Refactor pkg/chains/chains.go so the embedded chainsCfg parse step can also merge an optional external YAML blob (same schema as drpcorg/public/chains.yaml).
  2. In cmd/nodecore/main.go, look for NODECORE_EXTRA_CHAINS_PATH at startup; if set, read the file and merge.
  3. Document the env var and a minimal example in docs/nodecore/05-upstream-config.md.

Net effect: a deployer who needs private chains drops a small extra-chains.yaml next to the binary, sets the env var, and nodecore behaves correctly (eth_chainId returns the configured id, method specs inherit via method-spec: eth, etc.) — no fork required.

Optionally also wire up NODECORE_EXTRA_SPECS_PATH symmetrically since NewMethodSpecLoaderWithFs is already exported but unused — would let private chains override method specs too if needed.

Happy to send the PR

Estimated ~200 LOC + tests. Wanted to check the design lands before opening it. Specifically:

  • Env var vs config-file field — preference?
  • Strict merge (error on conflict) vs override (extra wins) vs append-only (no overlapping short-names / chain-id)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions