Skip to content

Commit c33104f

Browse files
authored
sepolia: add reth-based node compose file (#135)
* sepolia: add reth-based node compose file Adds docker-compose-sepolia-reth.yml as an alternative to op-geth for running a sepolia verifier node, using reth as the execution client. Reuses the existing sepolia/genesis.json and sepolia/rollup.json. Execution image tag is a placeholder pending a publicly downloadable reth image/snapshot. * sepolia: add proxyd in front of reth for pre-cutoff/unreliable methods reth only has data from a fixed height onward (init-state/import-op), and eth_getProof/debug_trace* are unreliable on it regardless of height. Adds a proxyd service (mirroring the internal reth-rpc41 setup) that forwards both cases to the public RPC instead of failing locally, and forwards everything else straight to the local reth. Query through proxyd's port, not op-reth's own port directly. proxyd image tag is a placeholder pending a publicly downloadable image, same as the reth one. * sepolia-reth: 补上 op-node / op-reth 的正式发布镜像 tag op-node 用 v1.6.2,op-reth 用 op-reth-v2.2.1-mantle-arsia.2,替换掉之前的占位 tag。 * sepolia-reth: proxyd 补上正式发布的镜像 tag v1.0.2 之前只改了 op-node/op-reth 两行,漏了 proxyd 这行还是占位的 :latest。 * op-reth: use built-in mantle-sepolia chainspec instead of external genesis.json Matches production reth-rpc41's approach (same image, built-in chainspec avoids genesis hash mismatch against snapshot data). Also aligns ws.api and adds min-suggested-priority-fee to match production. * op-reth: fix healthcheck, nc is not installed in the image Use bash's /dev/tcp instead, which is available in the base image. * docs: document how to download the reth snapshot before first start reth has no genesis-sync path, snapshot is required. Snapshots are uploaded weekly to the same S3 bucket as the geth ones, just no current.info-style pointer yet, so probe the last few days. * proxyd: whitelist the full op-reth rpc surface, not just a curated subset proxyd was rejecting any method not in rpc_method_mappings with 'method not whitelisted', including plenty of standard eth/debug/txpool/net calls op-reth actually serves fine. Only eth_getProof/debug_trace* (known unreliable on reth) and pre-cutoff-height queries still get routed to the public fallback RPC; everything else goes straight to local reth now. * docs: use current-reth.info pointer for reth snapshot date Replaces the multi-day probe loop with a direct read of current-reth.info, mirroring the geth snapshot section's current.info pattern now that the pointer exists. Also fixes the checksum URL to use the verified .tar.zst.sha256sum file instead of the pre-verification .tmp file. --------- Co-authored-by: ZhiMing Zhang <7278445+BlueShells@users.noreply.github.com>
1 parent dfa7312 commit c33104f

3 files changed

Lines changed: 367 additions & 0 deletions

File tree

docker-compose-sepolia-reth.yml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
version: '3.4'
2+
3+
x-healthcheck: &healthcheck
4+
test: [ "CMD", "bash", "-c", "echo > /dev/tcp/127.0.0.1/8545" ]
5+
interval: 5s
6+
timeout: 5s
7+
retries: 3
8+
start_period: 60s
9+
10+
services:
11+
op-reth:
12+
image: mantlenetworkio/mantle-op-reth:op-reth-v2.2.1-mantle-arsia.2
13+
pull_policy: always
14+
deploy:
15+
resources:
16+
limits:
17+
cpus: '4'
18+
memory: 16000M
19+
reservations:
20+
cpus: '4'
21+
memory: 16000M
22+
restart_policy:
23+
condition: on-failure
24+
extra_hosts:
25+
- "host.docker.internal:host-gateway"
26+
entrypoint: sh
27+
command:
28+
- -c
29+
- |
30+
test -d /db/db || op-reth init --datadir /db --chain mantle-sepolia
31+
exec op-reth node \
32+
--chain=mantle-sepolia \
33+
--datadir=/db \
34+
--port=30300 \
35+
--metrics=0.0.0.0:9001 \
36+
--http \
37+
--http.corsdomain=* \
38+
--http.addr=0.0.0.0 \
39+
--http.port=8545 \
40+
--http.api=web3,eth,debug,txpool,net \
41+
--ws \
42+
--ws.addr=0.0.0.0 \
43+
--ws.port=8546 \
44+
--ws.origins=* \
45+
--ws.api=debug,eth,txpool,net \
46+
--txpool.nolocals \
47+
--authrpc.addr=0.0.0.0 \
48+
--authrpc.port=8551 \
49+
--authrpc.jwtsecret=/secret/jwt_secret_txt \
50+
--disable-discovery \
51+
--rpc.max-blocks-per-filter=0 \
52+
--min-suggested-priority-fee=100000 \
53+
--engine.persistence-threshold=0 \
54+
--engine.memory-block-buffer-target=0 \
55+
--rollup.sequencer-http=https://rpc.sepolia.mantle.xyz
56+
volumes:
57+
- ./sepolia/secret:/secret/
58+
- ./data/sepolia-reth:/db/
59+
ports:
60+
- ${VERIFIER_HTTP_PORT:-8545}:8545
61+
- ${VERIFIER_WS_PORT:-8546}:8546
62+
- ${VERIFIER_AUTH_PORT:-8551}:8551
63+
healthcheck:
64+
<<: *healthcheck
65+
proxyd:
66+
# Sits in front of op-reth. reth only has data from a fixed height onward
67+
# (see op-reth's init-state/import-op step above), and some methods
68+
# (eth_getProof, debug_trace*) are unreliable on reth regardless of height.
69+
# Both cases get forwarded to the public RPC (rpc.sepolia.mantle.xyz)
70+
# instead of erroring — see sepolia/proxyd.toml for the exact routing.
71+
#
72+
image: mantlenetworkio/mantle-proxyd:v1.0.2
73+
pull_policy: always
74+
deploy:
75+
resources:
76+
limits:
77+
cpus: '1'
78+
memory: 1000M
79+
reservations:
80+
cpus: '250m'
81+
memory: 256M
82+
restart_policy:
83+
condition: on-failure
84+
depends_on:
85+
op-reth:
86+
condition: service_healthy
87+
volumes:
88+
- ./sepolia/proxyd.toml:/etc/proxyd/proxyd.toml
89+
ports:
90+
- ${PROXYD_HTTP_PORT:-1545}:8545
91+
- ${PROXYD_WS_PORT:-1546}:8546
92+
op-node:
93+
image: mantlenetworkio/mantle-op-node:v1.6.2
94+
pull_policy: always
95+
deploy:
96+
resources:
97+
limits:
98+
cpus: '4'
99+
memory: 8000M
100+
reservations:
101+
cpus: '4'
102+
memory: 8000M
103+
restart_policy:
104+
condition: on-failure
105+
depends_on:
106+
op-reth:
107+
condition: service_healthy
108+
volumes:
109+
- ./sepolia/secret:/secret
110+
- ./sepolia/rollup.json:/config/rollup.json
111+
environment:
112+
OP_NODE_L1_ETH_RPC: $L1_RPC_SEPOLIA
113+
OP_NODE_L2_ENGINE_RPC: 'http://op-reth:8551'
114+
OP_NODE_L2_ENGINE_AUTH: /secret/jwt_secret_txt
115+
OP_NODE_ROLLUP_CONFIG: '/config/rollup.json'
116+
OP_NODE_P2P_PRIV_PATH: /secret/p2p_node_key_txt
117+
OP_NODE_VERIFIER_L1_CONFS: '3'
118+
OP_NODE_RPC_ADDR: '0.0.0.0'
119+
OP_NODE_RPC_PORT: 8545
120+
OP_NODE_P2P_LISTEN_IP: '0.0.0.0'
121+
OP_NODE_P2P_LISTEN_TCP_PORT: 9003
122+
OP_NODE_P2P_LISTEN_UDP_PORT: 9003
123+
OP_NODE_P2P_PEER_SCORING: 'light'
124+
OP_NODE_P2P_PEER_BANNING: 'true'
125+
OP_NODE_METRICS_ENABLED: 'true'
126+
OP_NODE_METRICS_ADDR: '0.0.0.0'
127+
OP_NODE_METRICS_PORT: 7300
128+
OP_NODE_PPROF_ENABLED: 'true'
129+
OP_NODE_PPROF_PORT: 6060
130+
OP_NODE_PPROF_ADDR: '0.0.0.0'
131+
OP_NODE_P2P_DISCOVERY_PATH: '/op-node/opnode_discovery_db'
132+
OP_NODE_P2P_PEERSTORE_PATH: '/op-node/opnode_peerstore_db'
133+
OP_NODE_L2_BACKUP_UNSAFE_SYNC_RPC: https://rpc.sepolia.mantle.xyz
134+
OP_NODE_P2P_STATIC: '/dns4/peer0.sepolia.mantle.xyz/tcp/9003/p2p/16Uiu2HAkywYkvLRUH2MXbD6tSoT3jSMAzTWTp1aDijxpXQXxG6VM'
135+
OP_NODE_SEQUENCER_ENABLED: 'false'
136+
OP_NODE_P2P_AGENT: 'mantle'
137+
OP_NODE_P2P_SYNC_REQ_RESP: 'true'
138+
OP_NODE_L1_BEACON: $L1_BEACON_SEPOLIA
139+
ports:
140+
- ${NODE_RPC_PORT:-9545}:8545

run-node-sepolia.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,38 @@ export L1_BEACON_SEPOLIA='https://eth-beacon-chain-sepolia.drpc.org/rest/' #ple
109109
docker-compose -f docker-compose-sepolia-upgrade-beacon.yml up -d
110110
```
111111

112+
#### 4.3 Start a reth-based node (alternative execution client)
113+
114+
If you'd rather run [reth](https://github.com/paradigmxyz/reth) instead of op-geth as the execution client, use `docker-compose-sepolia-reth.yml`. It uses the L1 beacon chain to pull data for the rollup node (same as 4.2), so you need `L1_RPC_SEPOLIA` and `L1_BEACON_SEPOLIA` set the same way.
115+
116+
reth only starts from a snapshot — there's no genesis-sync path, so restore one into `./data/sepolia-reth` before the first `up -d`:
117+
118+
```
119+
mkdir -p ./data/sepolia-reth
120+
121+
# Download the latest official snapshot
122+
SEPOLIA_RETH_TARBALL_DATE=`curl https://s3.ap-southeast-1.amazonaws.com/snapshot.sepolia.mantle.xyz/current-reth.info`
123+
wget -c https://s3.ap-southeast-1.amazonaws.com/snapshot.sepolia.mantle.xyz/${SEPOLIA_RETH_TARBALL_DATE}-sepolia-reth.tar.zst
124+
125+
# Then you can verify your download
126+
SEPOLIA_RETH_TARBALL_CHECKSUM=`curl https://s3.ap-southeast-1.amazonaws.com/snapshot.sepolia.mantle.xyz/${SEPOLIA_RETH_TARBALL_DATE}-sepolia-reth.tar.zst.sha256sum | awk '{print $1}'`
127+
echo "${SEPOLIA_RETH_TARBALL_CHECKSUM} *${SEPOLIA_RETH_TARBALL_DATE}-sepolia-reth.tar.zst" | shasum -a 256 --check
128+
129+
# Unzip snapshot to the ledger path
130+
tar --use-compress-program=unzstd -xvf ${SEPOLIA_RETH_TARBALL_DATE}-sepolia-reth.tar.zst -C ./data/sepolia-reth
131+
```
132+
133+
Then bring the stack up:
134+
135+
```
136+
export L1_RPC_SEPOLIA='https://rpc.ankr.com/eth_sepolia' #please replace
137+
export L1_BEACON_SEPOLIA='https://eth-beacon-chain-sepolia.drpc.org/rest/' #please replace
138+
139+
docker-compose -f docker-compose-sepolia-reth.yml up -d
140+
```
141+
142+
**Query through the `proxyd` service, not `op-reth` directly** (`${PROXYD_HTTP_PORT:-1545}` / `${PROXYD_WS_PORT:-1546}` on the host, default `http://localhost:1545`). reth only has chain data from a fixed height onward (see the `init-state`/`import-op` step in `docker-compose-sepolia-reth.yml`), and a few methods (`eth_getProof`, `debug_trace*`) are unreliable on reth regardless of height. `proxyd` forwards both cases to the public RPC (`rpc.sepolia.mantle.xyz`) instead of failing locally — see `sepolia/proxyd.toml` for the exact routing rules. Querying `op-reth`'s own port directly (`${VERIFIER_HTTP_PORT:-8545}`) skips this fallback and will error on pre-cutoff blocks or those methods.
143+
112144
## Check Installation Result
113145

114146
Follow these steps to check if the installation is successful

sepolia/proxyd.toml

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#####
2+
# Sits in front of a local reth node.
3+
#
4+
# reth is bootstrapped from a fixed height (see docker-compose-sepolia-reth.yml's
5+
# init-state/import-op step) rather than genesis, so it has no data below that
6+
# height. A handful of methods (eth_getProof, debug_trace*) are also heavier/less
7+
# reliable on reth for old data. Both cases are forwarded to the public RPC
8+
# (rpc.sepolia.mantle.xyz) instead of failing locally.
9+
#
10+
# Every other method op-reth exposes (web3/eth/debug/txpool/net, matching
11+
# --http.api on op-reth) is whitelisted below and goes straight to local reth —
12+
# proxyd only exists here to handle the two cases above, not to gatekeep methods.
13+
ws_method_whitelist = [
14+
"eth_subscribe",
15+
"eth_unsubscribe",
16+
"web3_clientVersion",
17+
"web3_sha3",
18+
"net_version",
19+
"net_listening",
20+
"net_peerCount",
21+
"eth_chainId",
22+
"eth_syncing",
23+
"eth_gasPrice",
24+
"eth_maxPriorityFeePerGas",
25+
"eth_feeHistory",
26+
"eth_blockNumber",
27+
"eth_getBalance",
28+
"eth_getStorageAt",
29+
"eth_getTransactionCount",
30+
"eth_getCode",
31+
"eth_getBlockByHash",
32+
"eth_getBlockByNumber",
33+
"eth_getHeaderByHash",
34+
"eth_getHeaderByNumber",
35+
"eth_getBlockRange",
36+
"eth_getBlockTransactionCountByHash",
37+
"eth_getBlockTransactionCountByNumber",
38+
"eth_getUncleCountByBlockHash",
39+
"eth_getUncleCountByBlockNumber",
40+
"eth_getUncleByBlockHashAndIndex",
41+
"eth_getUncleByBlockNumberAndIndex",
42+
"eth_getBlockReceipts",
43+
"eth_getTransactionByHash",
44+
"eth_getTransactionByBlockHashAndIndex",
45+
"eth_getTransactionByBlockNumberAndIndex",
46+
"eth_getTransactionReceipt",
47+
"eth_getRawTransactionByHash",
48+
"eth_getRawTransactionByBlockHashAndIndex",
49+
"eth_getRawTransactionByBlockNumberAndIndex",
50+
"eth_getLogs",
51+
"eth_newFilter",
52+
"eth_newBlockFilter",
53+
"eth_newPendingTransactionFilter",
54+
"eth_getFilterChanges",
55+
"eth_getFilterLogs",
56+
"eth_uninstallFilter",
57+
"eth_call",
58+
"eth_estimateGas",
59+
"eth_createAccessList",
60+
"eth_sendRawTransaction",
61+
"eth_sendRawTransactionWithPreconf",
62+
"eth_estimateTotalFee",
63+
"eth_getProof",
64+
"debug_getRawBlock",
65+
"debug_getRawHeader",
66+
"debug_getRawReceipts",
67+
"debug_getRawTransaction",
68+
"debug_traceCall",
69+
"debug_traceTransaction",
70+
"debug_traceBlockByNumber",
71+
"debug_traceBlockByHash",
72+
"txpool_status",
73+
"txpool_content",
74+
"txpool_contentFrom",
75+
"txpool_inspect",
76+
]
77+
ws_backend_group = "main"
78+
79+
[server]
80+
rpc_host = "0.0.0.0"
81+
rpc_port = 8545
82+
ws_host = "0.0.0.0"
83+
ws_port = 8546
84+
max_body_size_bytes = 10485760
85+
max_concurrent_rpcs = 1000
86+
log_level = "info"
87+
88+
[metrics]
89+
enabled = true
90+
host = "0.0.0.0"
91+
port = 9761
92+
93+
[backends]
94+
[backends.local]
95+
# op-reth is the service name in docker-compose-sepolia-reth.yml
96+
rpc_url = "http://op-reth:8545"
97+
ws_url = "ws://op-reth:8546"
98+
max_rps = 100
99+
max_ws_conns = 50
100+
101+
[backends.fallback]
102+
rpc_url = "https://rpc.sepolia.mantle.xyz"
103+
max_rps = 20
104+
105+
[backend_groups]
106+
[backend_groups.main]
107+
backends = ["local", "fallback"]
108+
[backend_groups.main.height_based_routing]
109+
enabled = true
110+
# reth has no data below this height (see the init-state/import-op step) — anything
111+
# older is forwarded to the public RPC instead of erroring.
112+
cutoff_height = 36000000
113+
primary_backend = "local"
114+
fallback_backend = "fallback"
115+
[backend_groups.main.height_based_routing.method_config]
116+
eth_getBlockReceipts = 0 # first parameter is block number
117+
debug_traceBlockByNumber = 0
118+
debug_traceCall = 1
119+
debug_getRawBlock = 0
120+
debug_getRawHeader = 0
121+
debug_getRawReceipts = 0
122+
123+
[backend_groups.fallback_only]
124+
backends = ["fallback"]
125+
126+
# Mapping of methods to backend groups. Everything op-reth exposes (per its
127+
# --http.api=web3,eth,debug,txpool,net flag) is whitelisted here and defaults to
128+
# "main" (local reth, height-routed to fallback for pre-cutoff blocks);
129+
# eth_getProof/debug_trace* always go to fallback_only since reth is
130+
# unreliable/slow for these regardless of height. Nothing is blocked beyond that —
131+
# if op-reth doesn't support a method it'll error from reth itself, not proxyd.
132+
[rpc_method_mappings]
133+
eth_blockNumber = "main"
134+
eth_getBlockByNumber = "main"
135+
eth_getBlockByHash = "main"
136+
eth_getBlockTransactionCountByNumber = "main"
137+
eth_getBlockTransactionCountByHash = "main"
138+
eth_getUncleCountByBlockHash = "main"
139+
eth_getUncleCountByBlockNumber = "main"
140+
eth_getUncleByBlockHashAndIndex = "main"
141+
eth_getUncleByBlockNumberAndIndex = "main"
142+
eth_getBlockRange = "main"
143+
eth_getHeaderByNumber = "main"
144+
eth_getHeaderByHash = "main"
145+
eth_getBlockReceipts = "main"
146+
eth_getTransactionByBlockHashAndIndex = "main"
147+
eth_getTransactionByBlockNumberAndIndex = "main"
148+
eth_getTransactionCount = "main"
149+
eth_getTransactionByHash = "main"
150+
eth_getTransactionReceipt = "main"
151+
eth_getRawTransactionByHash = "main"
152+
eth_getRawTransactionByBlockHashAndIndex = "main"
153+
eth_getRawTransactionByBlockNumberAndIndex = "main"
154+
eth_call = "main"
155+
eth_createAccessList = "main"
156+
eth_sendRawTransaction = "main"
157+
eth_sendRawTransactionWithPreconf = "main"
158+
eth_estimateTotalFee = "main"
159+
eth_getBalance = "main"
160+
eth_getProof = "fallback_only"
161+
eth_getCode = "main"
162+
eth_getStorageAt = "main"
163+
eth_getLogs = "main"
164+
eth_newFilter = "main"
165+
eth_newBlockFilter = "main"
166+
eth_newPendingTransactionFilter = "main"
167+
eth_getFilterLogs = "main"
168+
eth_getFilterChanges = "main"
169+
eth_uninstallFilter = "main"
170+
eth_subscribe = "main"
171+
eth_unsubscribe = "main"
172+
eth_chainId = "main"
173+
net_listening = "main"
174+
net_peerCount = "main"
175+
eth_syncing = "main"
176+
net_version = "main"
177+
eth_estimateGas = "main"
178+
eth_gasPrice = "main"
179+
eth_maxPriorityFeePerGas = "main"
180+
eth_feeHistory = "main"
181+
web3_clientVersion = "main"
182+
web3_sha3 = "main"
183+
txpool_status = "main"
184+
txpool_content = "main"
185+
txpool_contentFrom = "main"
186+
txpool_inspect = "main"
187+
# JS tracer BigInteger.js polyfill gaps on reth — see docs/geth-fork-handling notes internally.
188+
debug_traceCall = "fallback_only"
189+
debug_traceTransaction = "fallback_only"
190+
debug_traceBlockByNumber = "fallback_only"
191+
debug_traceBlockByHash = "fallback_only"
192+
debug_getRawBlock = "main"
193+
debug_getRawHeader = "main"
194+
debug_getRawReceipts = "main"
195+
debug_getRawTransaction = "main"

0 commit comments

Comments
 (0)