Skip to content

Add trustless ENS resolution via Helios light client #1

@Rinse12

Description

@Rinse12

Motivation

BsoResolver currently trusts whatever public RPC it's pointed at (default list: eth.drpc.org, ethereum.publicnode.com, ethereum-rpc.publicnode.com, rpc.mevblocker.io, 1rpc.io/eth, eth-pokt.nodies.app). A malicious or compromised RPC can return any ENS text record / content hash and we'd cache it as authoritative. For a name-resolution library this is the main remaining trust-on-third-party surface.

We should offer a mode where the RPC response is verified locally via an Ethereum light client.

Proposal: integrate @a16z/helios

Helios (a16z crypto) is a Rust light client with a pure-WASM TypeScript binding. It runs a local consensus layer that verifies beacon-chain sync-committee signatures, then uses those authenticated beacon blocks to prove execution-layer state (account balances, contract storage, eth_call results) from an untrusted execution RPC. The upshot: even if the execution RPC lies, Helios rejects the answer.

  • npm: @a16z/helios@0.11.1 (published 2026-02-27), MIT, deps only eventemitter3 + uuid, ~11.7 MB unpacked, no native bindings.
  • Runs in-process in Node.js. No Docker sidecar, no new ports.
  • Exposes an EIP-1193 provider; viem accepts it as transport: custom(heliosProvider) — drop-in for the existing http(rpcUrl) transport we pass to createPublicClient.
  • "Syncs in seconds, no storage."

Benefits for bso-resolver

  • Trustless ENS resolution: getEnsText, getEnsAvatar, content-hash lookups, CCIP-read — all flow through Helios and are cryptographically verified against a recent finalized checkpoint. A hostile RPC can no longer inject a fake bitsocial text record.
  • No infra changes downstream: consumers (e.g. bitsocial-cli's Docker image) don't gain a new service, port, or binary. It's just an npm dep.
  • Portable: pure WASM means no platform matrix (works on linux x64/arm64, macOS, Windows) and no rebuild on Node upgrades.
  • Low sync cost: seconds on startup, no disk state, so daemon cold-starts and CI jobs aren't meaningfully slower.
  • Clean integration: we keep BsoResolver's public API, SQLite cache, and viem call sites exactly as they are. Only the transport swaps.

Core change

import { createHeliosProvider } from '@a16z/helios';
import { createPublicClient, custom } from 'viem';
import { mainnet } from 'viem/chains';

const heliosProvider = await createHeliosProvider({
  executionRpc,     // existing chain provider URL
  consensusRpc,     // new: public beacon API
  network: 'mainnet',
  checkpoint,       // optional; fetch from a checkpoint-sync endpoint at startup
}, 'ethereum');

await heliosProvider.waitSynced();

const publicClient = createPublicClient({
  chain: mainnet,
  transport: custom(heliosProvider),
});

Everything downstream (getEnsText, the SQLite cache, BsoResolver public API) stays the same. Cache entries should tag _resolvedBy as helios:<executionRpc> so we can distinguish trustless hits from trusted ones.

API sketch

New optional BsoResolver options:

  • trustless: boolean (default false — opt-in for first couple of releases).
  • consensusRpcUrl: string (required when trustless: true).
  • checkpoint?: string (0x…, optional — fetched from checkpoint-sync endpoint if omitted).
  • checkpointSyncUrl?: string (optional).

On teardown, call heliosProvider.shutdown().

Endpoints available (mainnet, free, public)

Consensus (beacon) REST API — needs /eth/v1/beacon/... 24/7:

  • https://ethereum-beacon-api.publicnode.com
  • https://www.lightclientdata.org
  • https://ethereum.operationsolarstorm.org (recommended in Helios README)
  • https://lodestar-mainnet.chainsafe.io
  • Ankr beacon (free tier)
  • dRPC beacon

Checkpoint sync — from eth-clients/checkpoint-sync-endpoints (verified=true, mainnet):

  • https://sync-mainnet.beaconcha.in (beaconcha.in)
  • https://beaconstate.info
  • https://beaconstate.ethstaker.cc (EthStaker)
  • https://checkpointz.pietjepuk.net (PietjePuk)
  • https://mainnet-checkpoint-sync.stakely.io
  • https://mainnet.checkpoint.sigp.io (Sigma Prime)
  • https://mainnet-checkpoint-sync.attestant.io
  • https://beaconstate-mainnet.chainsafe.io

Open questions

  • One Helios instance with fallback logic, or N instances mirroring the per-URL BsoResolver shape? Needs a short look at Helios' JS API for reconnect/shutdown behavior.
  • Default consensus + checkpoint lists (pick 3 of each for a rotating default).
  • When to flip trustless to default true — recommend keeping opt-in for 1–2 releases to see sync behavior in the wild first.

Downstream work

Once this lands, bitsocial-cli can bump the dep and add oclif flags (--trustlessEnsResolver, --consensusProviderUrls, --checkpointSyncUrls) on daemon to expose the new mode. No Docker image changes needed.

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