Skip to content

sophic00/veriRPC

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

veriRPC

veriRPC is a small JSON-RPC gateway for Ethereum execution RPC providers.

It forwards each incoming request to multiple upstream providers, waits for a quorum of matching responses, and returns the agreed result. For selected methods, it also performs proof-based verification before returning the response.

What It Does

  • Accepts JSON-RPC 2.0 requests over HTTP.
  • Fans requests out to multiple Ethereum RPC providers.
  • Requires a strict-majority consensus on the response payload.
  • Verifies eth_getBalance against the Ethereum state trie using eth_getProof.
  • Exposes health and metrics endpoints.

Current Verification Coverage

  • eth_getBalance: verified.
  • eth_getTransactionReceipt: not yet verified.
  • All other methods: consensus only, no proof verification.

How It Works

For each JSON-RPC request:

  1. The gateway optionally resolves any "latest" block tags to a concrete block number by asking providers for eth_blockNumber.
  2. The dispatcher sends the request to all configured providers in parallel.
  3. Responses are bucketed by compacted JSON result or error.
  4. As soon as consensus.min_agree providers return the same payload, that payload becomes the agreed response.
  5. If the method is supported by the verifier, the verifier checks the agreed result before it is returned.

For eth_getBalance, the verifier:

  1. Reads the agreed balance from the JSON-RPC response.
  2. Fetches the block header:
    • from verifier.trusted_header_provider if configured
    • otherwise through the same provider consensus path
  3. Fetches an account proof from one of the agreeing providers.
  4. Verifies the Merkle-Patricia trie proof against the block stateRoot.
  5. Compares the balance in the proof with the agreed balance.

Requirements

  • Go 1.26.1
  • At least 3 Ethereum execution RPC providers

Build

go build -o verirpc .

Test

go test ./...

Run

  1. Copy and edit the example config:
cp example.config.toml config.toml
  1. Start the server:
go run . -config config.toml

Or run the built binary:

./verirpc -config config.toml

The default listen port is 8547.

Configuration

Configuration is loaded from a TOML file.

Full Schema

[gateway]
port = 8547
read_timeout = "5s"
write_timeout = "10s"

[dispatcher]
timeout = "3s"

[consensus]
min_agree = 2

[verifier]
trusted_header_provider = "infura"

[[providers]]
name = "infura"
url = "https://mainnet.infura.io/v3/..."

[[providers]]
name = "alchemy"
url = "https://eth-mainnet.g.alchemy.com/v2/..."

[[providers]]
name = "ankr"
url = "https://rpc.ankr.com/eth"

Fields

[gateway]

  • port: HTTP listen port. Default: 8547
  • read_timeout: HTTP server read timeout. Default: 5s
  • write_timeout: HTTP server write timeout. Default: 10s

[dispatcher]

  • timeout: timeout applied to each upstream provider request. Default: 3s

[consensus]

  • min_agree: minimum number of providers that must return the same result. Must be a strict majority of configured providers. If omitted, it defaults to len(providers)/2 + 1.

[verifier]

  • trusted_header_provider: optional provider name used only for block header lookups during verification. If omitted, header lookups use provider consensus instead.

[[providers]]

  • name: provider identifier
  • url: upstream JSON-RPC endpoint

Validation Rules

  • At least 3 providers must be configured.
  • consensus.min_agree must be a strict majority.
  • consensus.min_agree cannot exceed the number of providers.
  • If verifier.trusted_header_provider is set, it must match one of the configured provider names.

HTTP Routes

POST /

Ethereum JSON-RPC entrypoint.

Request body must be a single JSON-RPC 2.0 request object.

Batch requests are not supported.

Example:

curl -s http://127.0.0.1:8547/ \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"eth_getBalance",
    "params":["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045","latest"]
  }'

GET /health

Simple health check.

Example:

curl -s http://127.0.0.1:8547/health

GET /metrics

Returns an in-memory metrics snapshot.

Example:

curl -s http://127.0.0.1:8547/metrics

JSON-RPC Request Schema

Incoming requests must follow this shape:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getBalance",
  "params": ["0x...", "latest"]
}

Fields:

  • jsonrpc: must be "2.0"
  • id: any valid JSON-RPC id value
  • method: Ethereum JSON-RPC method name
  • params: JSON array of method parameters

JSON-RPC Response Schema

Successful responses:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x0"
}

Error responses:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "proof verification failed"
  }
}

Notes:

  • HTTP status is 200 OK for JSON-RPC errors.
  • Parse errors use id: null.
  • If no provider quorum is reached, the gateway returns:
    • code: -32603
    • message: "no consensus among providers"
  • If proof verification fails, the gateway returns:
    • code: -32603
    • message: "proof verification failed"

Health Response Schema

{
  "status": "ok"
}

Metrics Response Schema

GET /metrics returns:

{
  "dispatches": 10,
  "agreements": 9,
  "disagreements": 1,
  "providers": {
    "infura": {
      "requests": 10,
      "errors": 1,
      "error_rate": 0.1,
      "avg_latency_ms": 120.5,
      "agreed": 8,
      "agreement_rate": 0.8
    }
  }
}

Fields:

  • dispatches: total number of dispatched JSON-RPC requests
  • agreements: number of requests that reached quorum
  • disagreements: number of requests that failed to reach quorum
  • providers: per-provider counters and derived rates

Per-provider fields:

  • requests: upstream requests sent
  • errors: upstream requests that failed
  • error_rate: errors / requests
  • avg_latency_ms: average upstream latency in milliseconds
  • agreed: number of successful dispatches where the provider was in the agreeing set
  • agreement_rate: agreed / dispatches

Example End-to-End Calls

Get a balance through veriRPC:

curl -s http://127.0.0.1:8547/ \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"eth_getBalance",
    "params":["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045","0x10"]
  }'

Get the current health status:

curl -s http://127.0.0.1:8547/health

Get the metrics snapshot:

curl -s http://127.0.0.1:8547/metrics

Limitations

  • Only single JSON-RPC requests are supported.
  • Only eth_getBalance is currently proof-verified.
  • eth_getTransactionReceipt is not yet verified.
  • Verification depends on provider support for eth_getProof.
  • Metrics are in-memory only and reset on process restart.

About

Ethereum RPC proxy with Merkle Patricia Trie proof verifier

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors