eRPC: add consensus failsafe (maxParticipants=3, agreementThreshold=2) for state-read methods
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- yaml
- Domain
- infrastructure
Research direction
Start with internal/embed/infrastructure/values/erpc.yaml.gotmpl and inspect the four EVM network blocks and their upstreams arrays. Then read internal/network/erpc_test.go and render the template to verify the failsafe configuration, upstream counts, and preservation of eth_sendRawTransaction routing. Done means the configuration and validation cover the requested consensus behavior and network prerequisites.
Written by the indexing model from the issue text.
Description
Problem
The obol-stack eRPC config (internal/embed/infrastructure/values/erpc.yaml.gotmpl) routes each RPC request to a single upstream chosen by eRPC's selectionPolicy + score, with hedge for latency fallback. For four EVM networks (mainnet, hoodi, base, base-sepolia) we currently rely on one upstream's answer per request.
For our read paths that underpin payment/registration correctness — agent-registration document fetches, ERC-8004 registry reads, USDC balance checks, eth_call of payment requirements — a single malicious or desynced upstream can return a wrong answer that no layer above detects. Consensus validation between multiple upstreams catches this cheaply.
Proposed config
Add a consensus entry to the failsafe list for high-trust read methods on each EVM network:
failsafe:
- matchMethod: "eth_call|eth_getLogs|eth_getTransactionReceipt|eth_getTransactionByHash|eth_getBlockByNumber|eth_getBlockByHash|eth_chainId"
consensus:
maxParticipants: 3 # fan out to 3 upstreams in parallel
agreementThreshold: 2 # 2 of 3 must match → return majority answer
punishMisbehavior:
disputeThreshold: 3
disputeWindow: 10s
sitOutPenalty: 5m
- matchMethod: "*" # non-consensus path stays for latency-sensitive reads
timeout:
duration: 30s
retry:
maxAttempts: 2
delay: 100ms
hedge:
delay: 500ms
maxCount: 1
Apply to all four EVM network blocks (lines ~80-145 of the gotmpl). Keep the existing selectionPolicy intact for eth_sendRawTransaction routing; consensus only activates for read methods.
Why 3/2, not 2/2
2/2means every paid request fails as soon as one upstream is flaky → negates the resilience we already have.3/2tolerates one upstream failure/disagreement per request, returns the majority answer, and thepunishMisbehaviorblock auto-quarantines consistently-misbehaving upstreams for 5 min.
Upstream prerequisite
Each affected chain must have ≥ 3 upstreams configured in the upstreams: array for consensus to have anyone to vote with. Current state:
chainId: 1(mainnet) — verify count; add more public RPCs viaobol network addif needed.chainId: 560048(hoodi) — likely only 1 today.chainId: 8453(base) — verify.chainId: 84532(base-sepolia) — 1 (base-sepolia-publicnode) + whatever is added byobol network add.
When count < 3, eRPC degrades gracefully — it queries however many exist — but the resilience goal isn't met. So this issue should include bumping the default ChainList seed count or guaranteeing a minimum.
Explicit non-goals
- Do not apply consensus to
eth_sendRawTransaction— routing stays single-upstream (already handled byselectionPolicy). - Do not apply to
eth_blockNumber/eth_syncing/latency-critical head checks — treat those as thematchMethod: "*"fallthrough. - Do not use
agreementThreshold: 3(of 3) — one slow upstream fails every call.
Optional: nonce handling
For eth_getTransactionCount, lagging replicas routinely disagree. Instead of strict consensus, use:
- matchMethod: "eth_getTransactionCount"
consensus:
maxParticipants: 3
agreementThreshold: 1
preferHighestValueFor:
eth_getTransactionCount:
- result
This returns the highest observed nonce, preventing stale-nonce transaction failures.
Validation plan
- Unit:
internal/network/erpc_test.go— template render with the new failsafe block. - Integration: seed 3 base-sepolia RPCs (publicnode + alchemy public + drpc public). Probe
eth_callagainst the registry contract; flip one upstream to return wrong data (mock); confirm request still returns majority answer. - Observability: eRPC emits metrics on consensus participation — expose them in Grafana.
References
- eRPC docs: networks, upstreams, failsafe/integrity, complete example
- File to touch:
internal/embed/infrastructure/values/erpc.yaml.gotmpl
- Dominant language
- Go
- Stars
- 11
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ObolNetwork/obol-stack
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
ObolNetwork/obol-stack#612 ·
-
Difficulty 5/5 Over a week Newbie friendliness 30/100
ObolNetwork/obol-stack#829 ·
-
bug
Difficulty 3/5 1-2 days Newbie friendliness 72/100
ObolNetwork/obol-stack#828 ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
ObolNetwork/obol-stack#821 · 1 comment ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
ObolNetwork/obol-stack#807 · 1 comment ·
All issues in ObolNetwork/obol-stack
Similar issues
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
microsoft/agent-framework-go#1179 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
[Bug]: OLLAMA_KEEP_ALIVE="5m" / "24h" crashes Ollama embedding and vision models with ValueError Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
infiniflow/ragflow#20223 · 1 reaction ·
-
bug needs triage pkg/translator/faro
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
open-telemetry/opentelemetry-collector-contrib#51484 · 1 comment ·