From a1ea4fd884bcef5fe2094f9134de142d84ff242f Mon Sep 17 00:00:00 2001 From: circle-github-action-bot Date: Fri, 22 May 2026 01:02:54 +0900 Subject: [PATCH] chore: sync to arc-node - bb2ff1d1b5a8fbbd35cc58139bedce67b7bc414c fix(NoStory): split public CI integration tests (#2196) by circle-github-action-bot <[internal]> - ab534e397d84f85e11f43078d11e565f3a1c09f8 chore: sync from main@6ecc47fb46c66d286436ed47a654b336696... by circle-github-action-bot <[internal]> GitOrigin-RevId: bb2ff1d1b5a8fbbd35cc58139bedce67b7bc414c --- .github/workflows/ci.yml | 7 +- docs/running-an-arc-node.md | 266 ++++++++++++++++++++++++++++++++++++ 2 files changed, 271 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6e67fb..31928da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: tool: nextest - name: Run unit tests - run: cargo nextest run --locked --workspace + run: cargo nextest run --locked --workspace --exclude arc-test-integration rust-integration-test: name: Rust Integration Tests @@ -129,11 +129,14 @@ jobs: with: tool: nextest + - name: Run node integration tests + run: cargo nextest run --locked -p arc-test-integration --test-threads 1 + - name: Start integration services run: make up - name: Run integration tests - run: cargo nextest run --locked --workspace --features integration + run: cargo nextest run --locked --workspace --exclude arc-test-integration --features integration # --------------------------------------------------------------------------- # Protocol Buffers (standalone, no deps) diff --git a/docs/running-an-arc-node.md b/docs/running-an-arc-node.md index cfbb3ee..93f04f9 100644 --- a/docs/running-an-arc-node.md +++ b/docs/running-an-arc-node.md @@ -415,6 +415,272 @@ address and port, exposing the _protected_ RPC endpoint. --- +## RPC Provider Nodes + +RPC provider nodes (relay nodes) serve public JSON-RPC traffic on behalf of the +network. They differ from follow nodes in two key ways: + +1. **Direct peering** — they connect to network sentries via devp2p (EL) and + libp2p (CL), rather than using follow-mode HTTP/WebSocket endpoints. +2. **Public exposure** — they expose RPC endpoints to the public internet, + requiring a more restrictive configuration. + +This section covers the configuration specific to RPC provider nodes. It assumes +you have completed the initial setup steps from [Binaries](#binaries) (paths, +directories, snapshots, consensus init). For EL ↔ CL communication options (IPC +vs RPC), see the [Binaries](#binaries) and [Separated hosts](#separated-hosts) +sections. + +### RPC namespaces + +Only the following namespaces may be exposed: + +```text +eth,net,web3,rpc +``` + +All other namespaces **must not** be enabled. Specifically, the following are +prohibited: `txpool`, `debug`, `trace`, `admin`, `flashbots`, `mev`, `ots`. + +```bash +--http.api eth,net,web3,rpc +--ws.api eth,net,web3,rpc +--public-api +``` + +The `--public-api` flag enforces these restrictions at runtime: it hides +pending-transaction RPCs and warns at startup if `--http.api` or `--ws.api` +exposes namespaces outside the safe set. + +To verify, call `rpc_modules`: + +```bash +curl -s -X POST http://localhost:8545 \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"rpc_modules","params":[],"id":1}' | jq .result +``` + +Expected output (the `arc` namespace is added automatically by `--enable-arc-rpc`): + +```json +{ + "arc": "1.0", + "net": "1.0", + "rpc": "1.0", + "eth": "1.0", + "web3": "1.0" +} +``` + +If you see `txpool`, `debug`, `trace`, `admin`, or any other unexpected +namespace, the node is misconfigured. + +### Arc RPC extension + +The `--enable-arc-rpc` flag adds a custom `arc` JSON-RPC namespace with two +methods: + +- `arc_getCertificate(height)` — returns the BFT commit certificate for a given + block height +- `arc_getVersion()` — returns build and version information + +The EL proxies certificate requests to the co-located CL's REST API, defaulting +to `http://127.0.0.1:31000`. Override with `--arc-rpc-upstream-url` or the +`ARC_RPC_UPSTREAM_URL` environment variable if the CL listens on a different +address. Your load balancer must allow `arc_getCertificate` on the EL's RPC port +(8545). + +`arc_getCertificate` responses are safe to cache by height at the edge — once a +block is finalized, any valid certificate for that height is valid indefinitely. +The same applies to `eth_getBlockByNumber` — finalized block payloads are +immutable and safe to cache by block number. + +### Transaction propagation + +Transactions must only be propagated to trusted peers: + +```bash +--tx-propagation-policy Trusted +``` + +### Peering + +Use `--trusted-peers` with the enode URLs provided during onboarding: + +```bash +--trusted-peers +``` + +RPC nodes run as full nodes: + +```bash +--full +``` + +### Prohibited configuration + +Do **not** use any of the following: + +| Flag / Feature | Reason | +| --------------------------------- | ----------------------------------------------------- | +| `--rpc.forwarder` | Request forwarding to upstream must not be configured | +| Bundle APIs | Bundle submission endpoints must not be exposed | +| `--http.api all` / `--ws.api all` | Exposes prohibited namespaces | + +### Firewall and network + +| Port | Service | Protocol | Exposure | +| ----- | ----------------------- | --------- | --------------------------------------------------------------------- | +| 8545 | EL HTTP RPC | TCP | **Public** — serves end users and permissionless nodes | +| 8546 | EL WebSocket RPC | TCP | **Public** — serves end users and permissionless nodes | +| 30303 | EL P2P (devp2p) | TCP + UDP | **Public** — allows permissionless nodes to gossip transactions | +| 27000 | CL P2P (libp2p) | TCP | **Restricted** — allow only IPs of peers provided during onboarding | +| 8551 | EL Engine API (authrpc) | TCP | **Internal only** — CL-to-EL communication, never expose externally | +| 31000 | CL RPC | TCP | **Internal only** — required for CL operation, never expose externally| + +Key rules: + +- RPC ports (8545, 8546) and EL P2P port (30303) are the **only** ports that + should be open to the public internet. +- CL P2P port (27000) must be reachable by network sentries but **not** by the + general public. Use IP allowlisting or the `--p2p.persistent-peers-only` flag. +- Engine API (8551) and CL RPC (31000) must **never** be exposed outside the + host. Bind to `127.0.0.1` if EL and CL are colocated, or use a private + network interface. +- If you enable metrics (`--metrics` for both EL and CL), restrict the metrics + ports accordingly. +- Deploy a reverse proxy or load balancer in front of ports 8545 and 8546 with + rate limiting, request size limits, and connection throttling. The node itself + does not enforce per-client request limits, so without an external layer, + a single client can saturate the RPC interface. + +### Consensus layer configuration + +The CL on an RPC node syncs decided blocks from sentry endpoints rather than +using follow mode: + +```bash +--p2p.persistent-peers +``` + +Replace `` with the peer multiaddrs provided during onboarding. + +To restrict CL P2P to only the configured persistent peers (recommended, since +RPC nodes should only communicate with sentries): + +```bash +--p2p.persistent-peers-only +``` + +The `--rpc.addr` flag is **required** when `--enable-arc-rpc` is enabled on the +EL: + +```bash +--rpc.addr=127.0.0.1:31000 +``` + +#### Sync-only mode + +By default the CL participates in the consensus protocol. To run a node that +only syncs blocks without participating in consensus (recommended for RPC +nodes): + +```bash +--no-consensus +``` + +When set, the node only runs the synchronization protocol and does not subscribe +to consensus-related gossip topics. + +### Complete example + +This example uses IPC for EL ↔ CL communication (recommended when colocated). +See [Separated hosts](#separated-hosts) for the RPC alternative. + +```bash +# Execution Layer (start first) +arc-node-execution node \ + --chain=arc-testnet \ + --datadir=$ARC_EXECUTION \ + --trusted-peers \ + --full \ + --http --http.addr=0.0.0.0 --http.port=8545 \ + --http.api eth,net,web3,rpc \ + --ws --ws.addr=0.0.0.0 --ws.port=8546 \ + --ws.api eth,net,web3,rpc \ + --enable-arc-rpc \ + --public-api \ + --tx-propagation-policy Trusted \ + --metrics 127.0.0.1:9001 \ + --ipcpath=$ARC_RUN/reth.ipc \ + --auth-ipc \ + --auth-ipc.path=$ARC_RUN/auth.ipc + +# Consensus Layer (start after EL is healthy) +arc-node-consensus start \ + --home=$ARC_CONSENSUS \ + --p2p.persistent-peers \ + --p2p.persistent-peers-only \ + --rpc.addr=127.0.0.1:31000 \ + --eth-socket=$ARC_RUN/reth.ipc \ + --execution-socket=$ARC_RUN/auth.ipc \ + --no-consensus \ + --metrics 127.0.0.1:29000 +``` + +**Important notes:** + +- Start the EL first. The CL connects to the EL on startup, so it will fail if + the EL is not running. +- The `--rpc.addr` flag on the CL is **required** because of the EL + `--enable-arc-rpc` flag. +- When using IPC, both processes must have read/write access to the socket + directory. If running in containers, mount the same directory into both. + +### Checklist + +**General:** + +- [ ] `arc-node-consensus init` has been run +- [ ] `--http.api` and `--ws.api` set to `eth,net,web3,rpc` only +- [ ] Prohibited namespaces (`txpool`, `debug`, `trace`, `admin`, `flashbots`, `mev`, `ots`) return "Method not found" +- [ ] `--enable-arc-rpc` is set and `arc_getCertificate` is accessible on port 8545 +- [ ] `--public-api` is set on the EL +- [ ] Pending-transaction RPCs are hidden — verify with: + ```bash + curl -s -X POST http://localhost:8545 \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"eth_newPendingTransactionFilter","params":[],"id":1}' \ + | jq .error + ``` + This should return an error (code `-32001`), not a filter ID. +- [ ] `--tx-propagation-policy Trusted` is set +- [ ] `--rpc.forwarder` is **not** configured +- [ ] No bundle APIs are exposed +- [ ] `--trusted-peers` is set to the enode URLs provided during onboarding +- [ ] `--full` is set on the EL +- [ ] Ports 8545, 8546 and 30303 are open to the public internet +- [ ] Port 27000 (CL P2P) is restricted to peer IPs provided during onboarding +- [ ] Engine API (8551, if using RPC) and CL RPC (31000) are not externally accessible +- [ ] CL has `--rpc.addr` set +- [ ] CL has `--no-consensus` set (recommended) + +**If using IPC:** + +- [ ] JWT secret is **not** configured (mutually exclusive with IPC) +- [ ] EL has `--ipcpath`, `--auth-ipc`, and `--auth-ipc.path` set +- [ ] CL has `--eth-socket` and `--execution-socket` set +- [ ] Both processes can read/write the socket directory + +**If using RPC:** + +- [ ] JWT secret file has been generated and is accessible to both EL and CL +- [ ] EL exposes auth RPC via `--authrpc.addr`, `--authrpc.port`, and `--authrpc.jwtsecret` +- [ ] CL connects to EL via `--eth-rpc-endpoint`, `--execution-endpoint`, and `--execution-jwt` +- [ ] `--arc-rpc-upstream-url` points to the CL's RPC address (the default `http://127.0.0.1:31000` only works when colocated) + +--- + ## Operational Guide ### System Requirements