Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLAUDE.md
100 changes: 100 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
## Overview

Rainbow Bridge ETH→NEAR light client. An on-chain Ethereum light client contract on NEAR that tracks Ethereum beacon chain finality via sync committee updates, plus a relayer that feeds it data.

## Repository Layout

Two Cargo workspaces plus a standalone crate:

- **`contracts/near/`** — NEAR smart contracts workspace (`eth2-client`, `eth-prover`, `eth-types`)
- **`eth2near/`** — Legacy relayer workspace (7 crates)
- **`relayer/`** — New relayer (standalone, Rust edition 2024)

The eth2 light client lives in `contracts/near/eth2-client/`. Supporting crates:
- `eth-types` — Ethereum execution/consensus type definitions (BlockHeader, BeaconBlockHeader, SyncCommittee, etc.)
- `eth2-utility` — Consensus logic: network configs, fork handling, merkle proof verification, sync committee period computation
- `eth2_hashing` — WASM-compatible Keccak256 (patched ethereum_hashing for NEAR SDK)

## Test, Lint

All contract commands run from `contracts/near/`:

```bash
# Test (the canonical CI sequence — builds test WASM first, then runs tests twice: with and without default features)
cd contracts/near/eth2-client && ./test.sh

# Run all tests
cd contracts/near && cargo test -p eth2-client

# Unit tests only (no mainnet feature, allows validate_updates=false)
cd contracts/near && cargo test -p eth2-client --no-default-features -- --nocapture

# Lint
cd contracts/near && cargo clippy
cd contracts/near && cargo fmt --check
```

**Feature flags** (eth2-client): `default = ["logs", "mainnet"]`
- `mainnet` — enforces `validate_updates` and `verify_bls_signatures` on init
- `logs` — enables `env::log_str()` output
- Unit tests marked `#[cfg(not(feature = "mainnet"))]` only run with `--no-default-features`

**CI** (`.github/workflows/contracts-near.yml`): runs `make build-eth2-client`, `./test.sh`, and relayer tests. Requires `git-lfs` for test data.

## Contract State Machine
Comment thread
karim-en marked this conversation as resolved.

The eth2-client alternates between two modes (`ClientMode` enum):

```
┌───────────────────────────────────────────────────────────┐
│ │
▼ │
SubmitLightClientUpdate │
│ submit_beacon_chain_light_client_update(update) │
│ 1. verify_finality_branch: merkle proof that │
│ update.finalized_header is in attested_header │
│ 2. check ≥2/3 sync committee participation │
│ 3. verify_bls_signatures (aggregate BLS via │
│ NEAR host fns: bls12381_p1_sum, pairing_check) │
│ 4. commit: if period advanced (P→P+1), rotate │
│ current_sync_committee ← next, next ← from update │
│ 5. set finalized_beacon_header, switch mode │
│ │
▼ │
SubmitHeader │
│ submit_execution_header(block_header) ×N │
│ — called once per block, newest→oldest │
│ — first call: block whose hash matches │
│ finalized_beacon_header.execution_block_hash │
│ — each subsequent: parent of the previous │
│ — inserts block_number→block_hash in LookupMap │
│ — GCs blocks beyond hashes_gc_threshold │
│ — last call: block_number == old_finalized + 1, │
│ verifies parent_hash links to old finalized hash ────┘
│ (chain is "closed"), updates finalized_execution_header
```

**Period constraint**: light client updates can advance by at most 1 sync committee period (`update_period == finalized_period || finalized_period + 1`). This bounds the execution block gap (and thus GC work) to at most one period's worth of blocks per cycle.

**GC**: `gc_finalized_execution_blocks` removes old entries from `finalized_execution_blocks` LookupMap. Bounded to `MAX_GC_BLOCKS_PER_CALL` (= one period = 8192) removals per call. In steady state this removes exactly 1 block per `submit_execution_header` call.

## Key Protocol Constants
Comment thread
karim-en marked this conversation as resolved.

Defined in `eth2-utility/src/consensus.rs`, per the [Ethereum Consensus Spec](https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md):

- `SLOTS_PER_EPOCH = 32` (~6.4 min)
- `EPOCHS_PER_SYNC_COMMITTEE_PERIOD = 256`
- One sync committee period = 32 × 256 = 8192 slots ≈ 27 hours
- `MIN_SYNC_COMMITTEE_PARTICIPANTS = 1` (contract enforces ≥2/3 of 512)
- `hashes_gc_threshold` is typically 51000 (~7 days of blocks)

## Test Data

Test data lives in `contracts/near/eth2-client/src/data/` (LFS-tracked JSON files). Sepolia is the primary test network. Regenerate with:
```bash
cd contracts/near/eth2-client/src/data && uv run dump_sepolia_data.py
```

## New Relayer (`relayer/`)

Standalone binary with CLI subcommands: `run` (continuous), `run-job` (single execution for Cloud Run), `init`, `generate-config`, `validate-config`. Config via TOML or env vars with `RELAYER_` prefix. Uses Lighthouse types for beacon chain, Alloy for execution RPC, near-fetch for NEAR.
Loading