cloud-sre
Lighthouse 报 InvalidToken,但 Erigon 实际返回 Forbidden
一次 Gnosis Erigon 和 Lighthouse Engine API 连接问题的处理记录:看起来像 JWT 错误,实际卡在 authrpc vhost。
一台 Gnosis 归档节点使用 Erigon 做 execution layer,Lighthouse 做 consensus layer。Erigon 日志一直刷:
flag --externalcl was provided, but no CL requests to engine-api in 22h...
Lighthouse 容器也在跑,但日志反复出现:
Failed jwt authorization error: InvalidToken
Execution engine call failed error: Auth(InvalidToken)
HTTP status client error (403 Forbidden) for url (http://gnosis:8551/)
第一眼很像 JWT secret 不一致。实际不是。最后真正需要补的是 Erigon Engine API 的 vhost:
--authrpc.vhosts=gnosis,localhost,127.0.0.1
文中用语说明
| 用语 | 含义 |
|---|---|
| Execution layer | 执行区块、保存执行层数据的客户端。这里是 Erigon。 |
| Consensus layer | 跟随 PoS 共识链、驱动 fork choice 的 beacon client。这里是 Lighthouse。 |
| Engine API | 共识客户端和执行客户端之间的认证 API,常见端口是 8551。 |
| JWT secret | 共识客户端访问 Engine API 时使用的共享密钥文件。 |
| authrpc vhost | Erigon 对认证 RPC 请求的 Host allowlist。JWT 正确,不代表 Host 一定被允许。 |
| Checkpoint sync | Lighthouse 从最近 finalized checkpoint 启动的同步方式,比从 genesis 追 beacon chain 快很多。 |
日志先指向了哪里
Erigon 是用外部 consensus layer 模式启动的:
--externalcl
--authrpc.addr=0.0.0.0
--authrpc.port=8551
--authrpc.jwtsecret=/jwt/jwt.hex
这个方向本身没问题。Erigon README 里说明,Gnosis 需要在 Erigon 旁边跑一个 consensus layer client;如果 consensus client 不在本机 localhost 访问,还需要配置 --authrpc.addr 0.0.0.0 和 --authrpc.vhosts <CL host> [1]。
Lighthouse 访问的是 Docker service name:
--execution-endpoint http://gnosis:8551
--execution-jwt /jwt/jwt.hex
所以这不是单纯“带 JWT 的请求”。它还是一个 Host 为 gnosis:8551 的 HTTP 请求。
先排除 JWT
最直观的可能性是密钥不一致,所以先检查共享文件:
sha256sum /data/jwt/jwt.hex
docker exec gnosis sha256sum /jwt/jwt.hex
docker exec gnosis-lighthouse sha256sum /jwt/jwt.hex
宿主机文件、Erigon 容器挂载、Lighthouse 容器挂载都一致。
我又用同一个文件生成临时 JWT,直接调用 Erigon 的 engine_exchangeCapabilities。请求返回 HTTP 200。这个检查把范围缩小了:Erigon 能验证这个 token,Engine API 也能访问。Lighthouse 里看到的 InvalidToken,背后其实还有一层 HTTP 403。
更新 Lighthouse 时暴露出的两个小问题
当时运行的 Lighthouse 镜像比较旧,所以改成固定版本,而不是继续依赖 floating tag:
sigp/lighthouse:v8.2.0
Lighthouse v8.2.0 当时是当前 release,官方标记为 high-priority [2]。
升级后先遇到旧数据库打不开:
Unable to open database: LoadConfig(ConfigError(InvalidVersionByte(Some(0))))
执行层数据在 Erigon 的 datadir 里,没有动。旧的 Lighthouse datadir 只是改名备份,然后用 Gnosis 的 checkpoint sync 重新启动 Lighthouse:
--checkpoint-sync-url https://checkpoint.gnosischain.com
Gnosis 文档给出了这个 checkpoint sync server;Lighthouse 文档也建议使用 checkpoint sync,因为它比从 genesis 开始同步快很多,同时提供同样的 beacon node 功能 [3][4]。
还有一个旧参数需要去掉。新版 Lighthouse 不接受下面两个参数同时出现:
--checkpoint-sync-url ...
--allow-insecure-genesis-sync
既然用了 checkpoint sync,就不再需要 genesis sync 的旧参数。
真正让连接恢复的改动
Lighthouse v8.2.0 正常启动后,仍然报:
InvalidToken("HTTP status client error (403 Forbidden) for url (http://gnosis:8551/)")
这里最有用的是 403 Forbidden。
Lighthouse 的 endpoint 是 http://gnosis:8551,也就是 Docker 网络里的服务名。Erigon 已经监听 0.0.0.0:8551,但 authrpc vhost 没有允许 gnosis 这个 Host。于是把 Erigon 启动参数改成:
--authrpc.addr=0.0.0.0
--authrpc.port=8551
--authrpc.vhosts=gnosis,localhost,127.0.0.1
--authrpc.jwtsecret=/jwt/jwt.hex
然后只重启 Erigon 容器,复用原来的 /data/erigon 和同一个 JWT 文件。
最后的启动形态
Erigon 侧:
erigon
--chain=gnosis
--datadir=/data
--externalcl
--authrpc.addr=0.0.0.0
--authrpc.port=8551
--authrpc.vhosts=gnosis,localhost,127.0.0.1
--authrpc.jwtsecret=/jwt/jwt.hex
--prune.mode=archive
Lighthouse 侧:
lighthouse bn
--network gnosis
--datadir /data
--execution-endpoint http://gnosis:8551
--execution-jwt /jwt/jwt.hex
--checkpoint-sync-url https://checkpoint.gnosischain.com
最后的检查
Erigon 重启后,日志里出现了关键行:
[GetClientVersionV1] Received request fromClientCode: LH, Lighthouse-v8.2.0...
Lighthouse 的日志也从 JWT 错误变成正常的 Engine API 流程:
Execution engine online
Issuing forkchoiceUpdated
Synced ... exec_hash: ... (unverified)
Head is optimistic
最近日志里的错误计数也变成了 0:
docker logs --since 2m gnosis-lighthouse 2>&1 | grep -c 'InvalidToken'
# 0
这里的 Head is optimistic 是可以接受的中间状态。它表示 Lighthouse 已跟上 consensus head,但 execution layer 还在验证对应 payload。Erigon 日志里还能看到 Execution stage 在继续执行区块,所以剩下的是执行层追块,不是 Engine API 认证失败。
这次最值得记住的一点是:Lighthouse 日志写 InvalidToken 时,要继续看里面包着的 HTTP status。Erigon 返回 403 时,JWT 文件可能完全没问题,真正卡住的是 authrpc host allowlist。
参考
[1] Erigon README: Beacon Chain / Consensus Layer
[2] Lighthouse v8.2.0 release notes