Skip to content

Add eth_capabilities method for routing capability discovery#755

Open
Termina1 wants to merge 4 commits intoethereum:mainfrom
drpcorg:admin-capabilities-spec-manual
Open

Add eth_capabilities method for routing capability discovery#755
Termina1 wants to merge 4 commits intoethereum:mainfrom
drpcorg:admin-capabilities-spec-manual

Conversation

@Termina1
Copy link

@Termina1 Termina1 commented Feb 23, 2026

Summary

Add a new public-facing capability discovery method, eth_capabilities, to the OpenRPC spec, plus schemas and happy-path .io fixtures.

  • Namespace: eth
  • Method: eth_capabilities
  • Params: []
  • Result: { config, effective }

Motivation

We (dRPC, drpc.org) operate an RPC marketplace/router and route traffic across many independent node operators. A recurring operational problem is that an RPC endpoint typically does not tell you what historical data it actually has (state at old blocks, tx/receipt lookup depth, log search range, block data, proof-related trie node availability).

Today we approximate this via heuristics and active probing. Probing is expensive and still often wrong, causing misrouting and retries.

Background discussion + example response (discussion with the geth team):
ethereum/go-ethereum#33828

Proposal

eth_capabilities returns:

config (client-specific snapshot)

config is intentionally client-specific and generic: a map of sections to arbitrary objects. This keeps the spec from standardizing per-client flags/settings while still allowing operators to expose useful config context for observability.

effective (routing-focused)

effective is strict and intended for routing decisions. It contains:

  • state: historical account/storage state availability.
  • tx: historical transaction lookup availability.
  • logs: log-indexed search/filter availability.
  • receipts: receipt lookup availability (tx/block receipt data).
  • blocks: historical block/header/body availability.
  • trienodes: proof/trie-node availability (e.g. eth_getProof depth window).

Each resource has:

  • disabled (boolean)
  • oldestBlock (hex quantity; earliest block expected to be served correctly)
  • deleteStrategy:
    • none
    • window + retentionBlocks (integer)

Routers should use effective. If the method is unavailable or access is restricted, routers should treat capabilities as unknown and fall back to existing behavior.

Exposure

This method is in eth_* because capability discovery is useful to public API consumers and routing layers. Operators can still gate access or serve gateway-level aggregated capabilities where applicable.

Scope / Compatibility

  • Adds a new method only; no breaking changes.
  • Spec-only change in execution-apis (OpenRPC). Client implementations are out of scope.
  • Optional method; clients/gateways may implement incrementally.

Validation

  • make build
  • make test (all passing)

@Termina1 Termina1 marked this pull request as ready for review February 23, 2026 16:25
@s1na
Copy link
Contributor

s1na commented Feb 23, 2026

IMO this should be under the eth_ namespace. The consumer of a public API should know what kind of data it can expect from the node. I don't know how that would play out for the providers who are running multiple nodes. I expect they can return the "full" index at the gateway level.

@Termina1
Copy link
Author

IMO this should be under the eth_ namespace. The consumer of a public API should know what kind of data it can expect from the node. I don't know how that would play out for the providers who are running multiple nodes. I expect they can return the "full" index at the gateway level.

I generally agree, just wanted to be more cautious. Solana, for example, has method getfirstavailableblock.

If nobody sees any downsides, I can change the namespace to eth.

@s1na
Copy link
Contributor

s1na commented Feb 23, 2026

It contains state, tx, logs, blocks, each with:

I would propose blocks, receipts, tx, state, trienodes. Receipts as parent types of logs might make more sense here. I assume pruning behavior is at receipt level rather than log level in most clients. Also proposing addition of trienodes for eth_getProof. It will become more normal for clients to have a window of proof data.

@Termina1
Copy link
Author

Termina1 commented Feb 24, 2026

I am not 100% sure but for some clients receipts are basically logs + transactions setting, but I may be wrong

@Termina1
Copy link
Author

I updated the spec, but moved to eth_ and added trienodes and kept receipts and logs both, so to not depend on client implementation of pruning

@MysticRyuujin
Copy link
Contributor

I don't think this API is viable for a few reasons:

  1. Exposing your CLI flags over API is probably a non-starter for many RPC providers. If you're running your own node, you know your flags.

  2. Most RPC providers run multiple clients, how do they respond to this? They might run full nodes, archive nodes, indexers, and custom methods via complex load balancing. How do they respond?

I could see this being somewhat useful for aload balancer, like eRPC, to call the node and make note of its specific capabilities but exposing it back to end users on the eth namespace doesn't make as much sense to me.

If you run your own node you know its capabilities, if you're not running your own node, you're likely going through some load balancing system anyway that would/could/should abstract the capabilities of the backend nodes anyway.

@s1na
Copy link
Contributor

s1na commented Mar 2, 2026

Most RPC providers run multiple clients, how do they respond to this? They might run full nodes, archive nodes, indexers, and custom methods via complex load balancing. How do they respond?

The response will be that they support the full range for all data models. As for the CLI flags I think they can return empty simply. It can still be a valid response.

Would you say that still causes issues if they return such a blanket response?

@MysticRyuujin
Copy link
Contributor

It might be OK if the spec is written in a way that returning config is optional, and RPC providers can more or less hardcode a generic response to the API. It would have to be scoped in a way on every client that it would only expose certain flags and not sensitive information (secrets, paths, etc.) that you might find in a cli flag. Also, some configs are done via TOML or ENV.

I do see the value in the use case DRPC has here, I'm mostly just questioning its necessity.

Writing tests would be challenging with the current setup, but we could just ignore the config flags.

Honestly, I'd probably just remove the config part entirely, and focus on the effective retention policy.

@s1na
Copy link
Contributor

s1na commented Mar 3, 2026

Honestly, I'd probably just remove the config part entirely, and focus on the effective retention policy.

Nothing against that from my side

@Termina1
Copy link
Author

Termina1 commented Mar 3, 2026

@s1na @MysticRyuujin what do you think if we move the config part to the admin namespace? I think it's actually very important for whoever wants to build something akin to dRPC (like any service that wants to redistribute traffic to other providers' nodes).
For example, not long ago Erigon rolled out a state cache feature with a bug. That bug led to returning outdated information from specific contracts. It's extremely hard to pinpoint, but it's even harder to exclude such nodes from routing.
Having a simple API to know flags/config options is very important for us, because unfortunately we can't standardize node configuration. On the other hand, there are bugs in every release of almost all blockchain clients. While we're not a fully decentralized RPC provider, we're trying to be at least some kind of counterweight to vertically integrated, fully centralized RPC providers, allowing some smaller players like easy2stake, stakesquid, brightlystake and others access to the RPC market.
99% of our clients already do not care about decentralization, and when they face data inconsistency bugs, they just blame us and switch to our competitors. In the case above, it would be trivial for us to ban all nodes that enabled this feature if there were an API for node configuration introspection.

@MysticRyuujin
Copy link
Contributor

I do not have any serious objections to an admin namespace defined method that can return node configuration.

With that said I think you're going to have one heck of an uphill battle getting all the clients to implement such a thing.

  1. How do you define what should and should not be returned via the method? You'd essentially have to return a massive config (like the resulting geth dumpconfig but for every client) to cover every possible scenario like you're mentioning here.

  2. It risks unintended leakage of data. As an example, metrics might have usernames and passwords. ethstats flags could leak a secret. People might have static peers, or leak private IPs they didn't want exposed.

  3. With the introduction of new flags and configs that might introduce errors and bugs, you don't even know if the upstream clients will return that specific flag in the config outputs. e.g. If reth adds an experimental --storage.v3, forgets to add it to the JSON-RPC output, and that has a bug, you're at square 1.

Then there's the problem of exposing the admin namespace publicly to begin with, you're asking decentralized nodes to allow you to call admin methods against their nodes. That'd be a no from me, as a person who runs my own nodes at home...I just wouldn't do that.

@Termina1
Copy link
Author

Termina1 commented Mar 3, 2026

Ok, thanks for the input. I will at least update the spec to exclude the config from eth namespace.

@Termina1 Termina1 changed the title Add admin_capabilities method for routing capability discovery Add eth_capabilities method for routing capability discovery Mar 3, 2026
@Termina1
Copy link
Author

Termina1 commented Mar 3, 2026

Removed the config section for now — the response contains only effective routing capabilities directly at the top level. Will revisit config exposure separately if needed.

@s1na
Copy link
Contributor

s1na commented Mar 4, 2026

Question re retentionStrategy: geth can currently prune blocks and receipts only up to the merge block. Would you consider that as oldestBlock: <0xmergeBlock>, retentionStrategy: "none"? Just highlighting that either the node has the whole history, or it has a "window" retention strategy or a fixed retention strategy up to some block

@Termina1
Copy link
Author

Termina1 commented Mar 6, 2026

Yeah, oldestBlock: <mergeBlock> with deleteStrategy: { "type": "none" } should be the right representation for this case. oldestBlock already conveys the boundary, "none" just means it's not going to move.

One thing though — in production we observe cases where pruning is non-linear, e.g. on Arbitrum nodes there are gaps in tx data rather than a clean cutoff. But I think that's an edge case we can ignore for now and keep it simple with a single oldestBlock.

@s1na
Copy link
Contributor

s1na commented Mar 9, 2026

Comments from discussion on the RPC call:

  • rename trienodes to stateproofs
  • Add more docs, e.g. how each resource maps to which methods (can be in form of open-rpc summary/description fields.
  • add head block info (number & hash)

And a proposal came up during the call to do this in shape of a subscription. I.e. the node will keep notifying the node whenever the block ranges it persists changes. It means that for data resources with a window retention strategy the consumer will get an update on every block that the block window has shifted. The goal would be to avoid returning the strategy type and only block range info. What do you think of this idea as the OG author @Termina1?

@Termina1
Copy link
Author

Termina1 commented Mar 9, 2026

Renamed trienodes to stateproofs, added descriptions for each resource with affected methods mapping, and added head (blockNumber + blockHash) to the response.

Re subscription idea — sounds good, could be a separate eth_subscribe("capabilities") that pushes updates whenever block ranges change. Would keep the polling method as-is and add the subscription on top.

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