Skip to content

feat(evm): mine + claim test ETH via evm.faucet - #277

Open
qu0b wants to merge 4 commits into
masterfrom
qu0b/faucet-agent-command
Open

feat(evm): mine + claim test ETH via evm.faucet#277
qu0b wants to merge 4 commits into
masterfrom
qu0b/faucet-agent-command

Conversation

@qu0b

@qu0b qu0b commented Jul 2, 2026

Copy link
Copy Markdown
Member

What

evm.faucet(network, address) mines the network's PoW faucet and claims test ETH, returning the claim tx hash (it used to return a browser URL — useless to an agent). Crucially, the faucet is reachable only through the panda proxy, which authenticates the caller — a client-side login check is meaningless if the endpoint is open.

from ethpandaops import evm
w = evm.wallet()
tx = evm.faucet("glamsterdam-devnet-6", w["address"])   # mines + claims, returns tx hash

How

  • pkg/proxy /faucet/{network}/ passthrough (handlers/faucet.go) — mirrors the ethnode handler: the proxy's auth middleware authenticates the caller, then it forwards to the network's credential-gated faucet host with basic auth that only the proxy holds. No public faucet surface for panda users.
  • pkg/faucet Transport — the Argon2id mining flow (x/crypto/argon2, zero external deps) runs either directly (tests/CLI) or through the proxy.
  • evm.faucet op — routes via proxyRequest("/faucet/<network>/…"); the local panda auth check is only a fast pre-check now, the proxy is the real boundary.

Auth model

The proxy is the single authenticated gateway (same as every datasource). The faucet endpoint is credential-gated and only the proxy holds the credential, so there is no way to reach it except an authenticated request through the proxy. The full chain: panda auth login → OIDC issuer (GitHub OAuth behind it) → proxy verifies the bearer → proxy attaches the faucet basic-auth credential upstream. Every faucet surface (web UI, REST API, websocket) sits behind the ingress basic auth.

The credential is configurable: an optional faucet: block in the proxy config gives the faucet its own basic-auth pair (rotatable independently of node access); when omitted it falls back to the ethnode credential, since the faucet lives on the same credential-gated *.ethpandaops.io surface as the nodes.

Tests

  • Unit: mining core vs a faithful mock (real argon2 + difficulty), non-standard-param rejection, difficulty mask; proxy FaucetHandler (host derivation, bearer→basic-auth rewrite, path validation); op auth gate (401) + resolution errors.
  • e2e through a local panda-proxy against glamsterdam-devnet-6: pkg/faucet → proxy /faucet/… → faucet → mine → claim → funded 1 ETH in ~30 s (tx confirmed).

Deploy order — the faucet lockdown is LAST

  1. Merge this PR → panda-proxy build has the faucet handler.
  2. Deploy panda-proxy (with the handler) + panda-server.
  3. Then make the faucet non-public (basic-auth ingress). Doing this earlier breaks both the direct and proxy paths.

Faucet-side notes (ACG #554 / glamsterdam)

  • ipinfo disabled on the agent faucet: behind the proxy the faucet sees the proxy's IP, so IP-reputation checks fail — they don't apply to a proxy-gated faucet.
  • Per-IP concurrency/recurring limits also collapse behind the proxy (all traffic shares the proxy IP). Addressed on both sides: the proxy rate-limits startSession per authenticated user (30/h rolling, in this PR), and the faucet scopes concurrency + recurring limits per target address via byAddrOnly (ethereum-helm-charts#485 chart 1.1.0, wired in ACG#554).

Requires a PoWFaucet build with the agent REST API at Argon2id/v19 (live: ghcr.io/qu0b/powfaucet:v2.5.0-agent.4).

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🐼 Smoke eval — 23efca6: ✅ 8/8 pass

📊 Interactive report — tokens p50 18,295 · tokens/solve 20,489.

Reference points: master@1f61a26 100% · v0.38.7 98% · qu0b/faucet-agent-command@cf93705 100%.

question result tokens tools
forky_node_coverage 16,193 7
tracoor_node_coverage 17,486 7
mainnet_block_arrival_p50 15,265 6
list_datasources 13,020 2
block_count_24h 25,239 12
missed_slots_24h 19,424 15
chartkit_default_arrival_distribution 38,184 20
storage_upload_session_scoped 19,104 13
🔭 Langfuse traces (8 runs; ⚠️ = failed)

The report walks this branch's commits against the master baseline and the most recent release. A self-contained copy is in the run's eval-smoke-* artifact.

qu0b added 3 commits July 30, 2026 11:24
evm.faucet(network, address) previously returned a browser URL, which an
agent cannot use (no browser, captcha, or WebSocket). It now runs the full
PoWFaucet agent-REST flow server-side and returns the claim transaction hash.

- pkg/faucet: Go mining core using golang.org/x/crypto/argon2 (Argon2id).
  Zero external/runtime deps, so it works on any OS panda ships to.
- evm.faucet server operation: auth-gated (requires 'panda auth'), resolves
  the network's faucet URL from Cartographoor, delegates to pkg/faucet.
- sandbox evm.faucet() delegates to the operation and returns the tx hash.

Requires the network's faucet to run a PoWFaucet build with the agent REST
API (Argon2id/v19). Tests: mining core against a faithful mock + auth gate;
faucet_live_test.go is an env-guarded live e2e.
The client-side auth check is meaningless if the faucet endpoint is open, so
the faucet is now reachable only through the panda proxy:

- pkg/proxy: add a /faucet/{network}/ passthrough that mirrors the ethnode
  handler — the proxy's auth middleware authenticates the caller, then it
  forwards to the network's credential-gated faucet host with basic auth the
  proxy alone holds.
- pkg/faucet: introduce a Transport so the mining flow runs either directly
  (tests/CLI) or through the proxy.
- evm.faucet op: route via proxyRequest(/faucet/<network>/...); the local
  auth check is now only a fast pre-check, the proxy is the real boundary.
Behind the proxy every faucet request carries the proxy's IP, so the
faucet's own per-IP protections collapse to one global bucket. Restore
per-user fairness where the authenticated identity is known: cap
startSession to 30/user/hour, keyed on the auth subject. Only
startSession is counted; the many powChallenge/powSubmit calls a single
claim makes pass through untouched.
The faucet passthrough reused the ethnode basic-auth credential, putting the
faucet in the same access ring as node RPC. An optional proxy-config faucet
block gives it its own credential so faucet access rotates independently;
omitted, the ethnode credential still applies.
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.

1 participant