Skip to content

Commit ce07eca

Browse files
authored
chore: sync to arc-node (#75)
Automated sync via Copybara.
2 parents 205d270 + a1ea4fd commit ce07eca

2 files changed

Lines changed: 271 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
tool: nextest
8989

9090
- name: Run unit tests
91-
run: cargo nextest run --locked --workspace
91+
run: cargo nextest run --locked --workspace --exclude arc-test-integration
9292

9393
rust-integration-test:
9494
name: Rust Integration Tests
@@ -129,11 +129,14 @@ jobs:
129129
with:
130130
tool: nextest
131131

132+
- name: Run node integration tests
133+
run: cargo nextest run --locked -p arc-test-integration --test-threads 1
134+
132135
- name: Start integration services
133136
run: make up
134137

135138
- name: Run integration tests
136-
run: cargo nextest run --locked --workspace --features integration
139+
run: cargo nextest run --locked --workspace --exclude arc-test-integration --features integration
137140

138141
# ---------------------------------------------------------------------------
139142
# Protocol Buffers (standalone, no deps)

docs/running-an-arc-node.md

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,272 @@ address and port, exposing the _protected_ RPC endpoint.
415415

416416
---
417417

418+
## RPC Provider Nodes
419+
420+
RPC provider nodes (relay nodes) serve public JSON-RPC traffic on behalf of the
421+
network. They differ from follow nodes in two key ways:
422+
423+
1. **Direct peering** — they connect to network sentries via devp2p (EL) and
424+
libp2p (CL), rather than using follow-mode HTTP/WebSocket endpoints.
425+
2. **Public exposure** — they expose RPC endpoints to the public internet,
426+
requiring a more restrictive configuration.
427+
428+
This section covers the configuration specific to RPC provider nodes. It assumes
429+
you have completed the initial setup steps from [Binaries](#binaries) (paths,
430+
directories, snapshots, consensus init). For EL ↔ CL communication options (IPC
431+
vs RPC), see the [Binaries](#binaries) and [Separated hosts](#separated-hosts)
432+
sections.
433+
434+
### RPC namespaces
435+
436+
Only the following namespaces may be exposed:
437+
438+
```text
439+
eth,net,web3,rpc
440+
```
441+
442+
All other namespaces **must not** be enabled. Specifically, the following are
443+
prohibited: `txpool`, `debug`, `trace`, `admin`, `flashbots`, `mev`, `ots`.
444+
445+
```bash
446+
--http.api eth,net,web3,rpc
447+
--ws.api eth,net,web3,rpc
448+
--public-api
449+
```
450+
451+
The `--public-api` flag enforces these restrictions at runtime: it hides
452+
pending-transaction RPCs and warns at startup if `--http.api` or `--ws.api`
453+
exposes namespaces outside the safe set.
454+
455+
To verify, call `rpc_modules`:
456+
457+
```bash
458+
curl -s -X POST http://localhost:8545 \
459+
-H "Content-Type: application/json" \
460+
-d '{"jsonrpc":"2.0","method":"rpc_modules","params":[],"id":1}' | jq .result
461+
```
462+
463+
Expected output (the `arc` namespace is added automatically by `--enable-arc-rpc`):
464+
465+
```json
466+
{
467+
"arc": "1.0",
468+
"net": "1.0",
469+
"rpc": "1.0",
470+
"eth": "1.0",
471+
"web3": "1.0"
472+
}
473+
```
474+
475+
If you see `txpool`, `debug`, `trace`, `admin`, or any other unexpected
476+
namespace, the node is misconfigured.
477+
478+
### Arc RPC extension
479+
480+
The `--enable-arc-rpc` flag adds a custom `arc` JSON-RPC namespace with two
481+
methods:
482+
483+
- `arc_getCertificate(height)` — returns the BFT commit certificate for a given
484+
block height
485+
- `arc_getVersion()` — returns build and version information
486+
487+
The EL proxies certificate requests to the co-located CL's REST API, defaulting
488+
to `http://127.0.0.1:31000`. Override with `--arc-rpc-upstream-url` or the
489+
`ARC_RPC_UPSTREAM_URL` environment variable if the CL listens on a different
490+
address. Your load balancer must allow `arc_getCertificate` on the EL's RPC port
491+
(8545).
492+
493+
`arc_getCertificate` responses are safe to cache by height at the edge — once a
494+
block is finalized, any valid certificate for that height is valid indefinitely.
495+
The same applies to `eth_getBlockByNumber` — finalized block payloads are
496+
immutable and safe to cache by block number.
497+
498+
### Transaction propagation
499+
500+
Transactions must only be propagated to trusted peers:
501+
502+
```bash
503+
--tx-propagation-policy Trusted
504+
```
505+
506+
### Peering
507+
508+
Use `--trusted-peers` with the enode URLs provided during onboarding:
509+
510+
```bash
511+
--trusted-peers <ENODE_URLS>
512+
```
513+
514+
RPC nodes run as full nodes:
515+
516+
```bash
517+
--full
518+
```
519+
520+
### Prohibited configuration
521+
522+
Do **not** use any of the following:
523+
524+
| Flag / Feature | Reason |
525+
| --------------------------------- | ----------------------------------------------------- |
526+
| `--rpc.forwarder` | Request forwarding to upstream must not be configured |
527+
| Bundle APIs | Bundle submission endpoints must not be exposed |
528+
| `--http.api all` / `--ws.api all` | Exposes prohibited namespaces |
529+
530+
### Firewall and network
531+
532+
| Port | Service | Protocol | Exposure |
533+
| ----- | ----------------------- | --------- | --------------------------------------------------------------------- |
534+
| 8545 | EL HTTP RPC | TCP | **Public** — serves end users and permissionless nodes |
535+
| 8546 | EL WebSocket RPC | TCP | **Public** — serves end users and permissionless nodes |
536+
| 30303 | EL P2P (devp2p) | TCP + UDP | **Public** — allows permissionless nodes to gossip transactions |
537+
| 27000 | CL P2P (libp2p) | TCP | **Restricted** — allow only IPs of peers provided during onboarding |
538+
| 8551 | EL Engine API (authrpc) | TCP | **Internal only** — CL-to-EL communication, never expose externally |
539+
| 31000 | CL RPC | TCP | **Internal only** — required for CL operation, never expose externally|
540+
541+
Key rules:
542+
543+
- RPC ports (8545, 8546) and EL P2P port (30303) are the **only** ports that
544+
should be open to the public internet.
545+
- CL P2P port (27000) must be reachable by network sentries but **not** by the
546+
general public. Use IP allowlisting or the `--p2p.persistent-peers-only` flag.
547+
- Engine API (8551) and CL RPC (31000) must **never** be exposed outside the
548+
host. Bind to `127.0.0.1` if EL and CL are colocated, or use a private
549+
network interface.
550+
- If you enable metrics (`--metrics` for both EL and CL), restrict the metrics
551+
ports accordingly.
552+
- Deploy a reverse proxy or load balancer in front of ports 8545 and 8546 with
553+
rate limiting, request size limits, and connection throttling. The node itself
554+
does not enforce per-client request limits, so without an external layer,
555+
a single client can saturate the RPC interface.
556+
557+
### Consensus layer configuration
558+
559+
The CL on an RPC node syncs decided blocks from sentry endpoints rather than
560+
using follow mode:
561+
562+
```bash
563+
--p2p.persistent-peers <SENTRY_MULTIADDRS>
564+
```
565+
566+
Replace `<SENTRY_MULTIADDRS>` with the peer multiaddrs provided during onboarding.
567+
568+
To restrict CL P2P to only the configured persistent peers (recommended, since
569+
RPC nodes should only communicate with sentries):
570+
571+
```bash
572+
--p2p.persistent-peers-only
573+
```
574+
575+
The `--rpc.addr` flag is **required** when `--enable-arc-rpc` is enabled on the
576+
EL:
577+
578+
```bash
579+
--rpc.addr=127.0.0.1:31000
580+
```
581+
582+
#### Sync-only mode
583+
584+
By default the CL participates in the consensus protocol. To run a node that
585+
only syncs blocks without participating in consensus (recommended for RPC
586+
nodes):
587+
588+
```bash
589+
--no-consensus
590+
```
591+
592+
When set, the node only runs the synchronization protocol and does not subscribe
593+
to consensus-related gossip topics.
594+
595+
### Complete example
596+
597+
This example uses IPC for EL ↔ CL communication (recommended when colocated).
598+
See [Separated hosts](#separated-hosts) for the RPC alternative.
599+
600+
```bash
601+
# Execution Layer (start first)
602+
arc-node-execution node \
603+
--chain=arc-testnet \
604+
--datadir=$ARC_EXECUTION \
605+
--trusted-peers <ENODE_URLS> \
606+
--full \
607+
--http --http.addr=0.0.0.0 --http.port=8545 \
608+
--http.api eth,net,web3,rpc \
609+
--ws --ws.addr=0.0.0.0 --ws.port=8546 \
610+
--ws.api eth,net,web3,rpc \
611+
--enable-arc-rpc \
612+
--public-api \
613+
--tx-propagation-policy Trusted \
614+
--metrics 127.0.0.1:9001 \
615+
--ipcpath=$ARC_RUN/reth.ipc \
616+
--auth-ipc \
617+
--auth-ipc.path=$ARC_RUN/auth.ipc
618+
619+
# Consensus Layer (start after EL is healthy)
620+
arc-node-consensus start \
621+
--home=$ARC_CONSENSUS \
622+
--p2p.persistent-peers <SENTRY_MULTIADDRS> \
623+
--p2p.persistent-peers-only \
624+
--rpc.addr=127.0.0.1:31000 \
625+
--eth-socket=$ARC_RUN/reth.ipc \
626+
--execution-socket=$ARC_RUN/auth.ipc \
627+
--no-consensus \
628+
--metrics 127.0.0.1:29000
629+
```
630+
631+
**Important notes:**
632+
633+
- Start the EL first. The CL connects to the EL on startup, so it will fail if
634+
the EL is not running.
635+
- The `--rpc.addr` flag on the CL is **required** because of the EL
636+
`--enable-arc-rpc` flag.
637+
- When using IPC, both processes must have read/write access to the socket
638+
directory. If running in containers, mount the same directory into both.
639+
640+
### Checklist
641+
642+
**General:**
643+
644+
- [ ] `arc-node-consensus init` has been run
645+
- [ ] `--http.api` and `--ws.api` set to `eth,net,web3,rpc` only
646+
- [ ] Prohibited namespaces (`txpool`, `debug`, `trace`, `admin`, `flashbots`, `mev`, `ots`) return "Method not found"
647+
- [ ] `--enable-arc-rpc` is set and `arc_getCertificate` is accessible on port 8545
648+
- [ ] `--public-api` is set on the EL
649+
- [ ] Pending-transaction RPCs are hidden — verify with:
650+
```bash
651+
curl -s -X POST http://localhost:8545 \
652+
-H "Content-Type: application/json" \
653+
-d '{"jsonrpc":"2.0","method":"eth_newPendingTransactionFilter","params":[],"id":1}' \
654+
| jq .error
655+
```
656+
This should return an error (code `-32001`), not a filter ID.
657+
- [ ] `--tx-propagation-policy Trusted` is set
658+
- [ ] `--rpc.forwarder` is **not** configured
659+
- [ ] No bundle APIs are exposed
660+
- [ ] `--trusted-peers` is set to the enode URLs provided during onboarding
661+
- [ ] `--full` is set on the EL
662+
- [ ] Ports 8545, 8546 and 30303 are open to the public internet
663+
- [ ] Port 27000 (CL P2P) is restricted to peer IPs provided during onboarding
664+
- [ ] Engine API (8551, if using RPC) and CL RPC (31000) are not externally accessible
665+
- [ ] CL has `--rpc.addr` set
666+
- [ ] CL has `--no-consensus` set (recommended)
667+
668+
**If using IPC:**
669+
670+
- [ ] JWT secret is **not** configured (mutually exclusive with IPC)
671+
- [ ] EL has `--ipcpath`, `--auth-ipc`, and `--auth-ipc.path` set
672+
- [ ] CL has `--eth-socket` and `--execution-socket` set
673+
- [ ] Both processes can read/write the socket directory
674+
675+
**If using RPC:**
676+
677+
- [ ] JWT secret file has been generated and is accessible to both EL and CL
678+
- [ ] EL exposes auth RPC via `--authrpc.addr`, `--authrpc.port`, and `--authrpc.jwtsecret`
679+
- [ ] CL connects to EL via `--eth-rpc-endpoint`, `--execution-endpoint`, and `--execution-jwt`
680+
- [ ] `--arc-rpc-upstream-url` points to the CL's RPC address (the default `http://127.0.0.1:31000` only works when colocated)
681+
682+
---
683+
418684
## Operational Guide
419685

420686
### System Requirements

0 commit comments

Comments
 (0)