Arbitrum Nitro 归档节点保留完整的 L2 历史状态以及重建该状态所需的 L1 派生批次数据,从而支持历史 eth_call、eth_getBalance 和 eth_getLogs 查询。与修剪旧 trie 节点的全节点不同,归档节点在启用 archive 标志的情况下运行,并存储所有状态历史。从创世块同步虽然忠实但速度慢;从已发布的快照引导启动更快,但需要信任快照来源并验证链头。运行 Nitro 归档节点需要健康的以太坊 L1 RPC 端点和正确配置的数据目录。本文解释其机制,提供可运行的验证示例,并概述权衡取舍和常见故障。
Arbitrum Nitro 节点模型与归档要求
Arbitrum One 是一个乐观 rollup,其 Nitro 节点从两个输入派生 L2 状态:用于排序批次的 L1(以太坊)收件箱以及 L2 执行本身。这与通用的以太坊 L1 节点不同,后者仅从自身链派生状态。因此,归档节点必须同时保留完整的 L2 状态历史和 L1 派生的批次数据,以便重建任何历史状态。
节点角色包括全节点(保留近期状态)和归档节点(保留整条链的历史状态)。归档节点用于针对旧区块的 eth_call 和 eth_getBalance、历史 eth_getLogs 以及 trace 式重放。两种角色在存储策略和同步时间上不同,而非 API 接口。更广泛的比较请参阅归档节点与全节点对比。
- 全节点:修剪旧 trie 节点,同步更快,存储更低。
- 归档节点:保留所有 trie 节点,同步更慢,存储更高。
- 两者暴露相同的 JSON-RPC API;归档节点提供历史查询服务。
Nitro 状态存储与 archive 标志
Nitro 将状态存储在通过 WAVM/AEVM 生成的状态根提交的 Merkle 化 trie 中,使用源自 go-ethereum 的持久状态数据库。该状态存储可以运行在“full”或“archive”保留模式下。archive 标志决定是否修剪旧 trie 节点;启用后,节点保留所有历史状态。
archive 标志在节点启动时设置,不重新同步或迁移数据库就无法更改。根据 Arbitrum 关于运行归档节点的文档,必须使用适当的标志配置节点以启用归档模式。这确保历史状态查询不会因“missing trie node”错误而失败。
- 状态根由 Nitro 的执行引擎(WAVM/AEVM)生成。
- 持久状态数据库使用源自 go-ethereum 的存储。
- 归档模式禁用旧 trie 节点的修剪。
同步路径:创世重放、快照引导和托管端点
Arbitrum Nitro 归档节点有三种主要同步路径。第一,通过重放收件箱从创世块同步,虽然忠实但速度慢且受 IO 限制,因为它处理来自 L1 的每个批次。第二,从已发布的快照引导启动,复制已知良好的状态数据库,然后追赶剩余的收件箱,这要快得多,但需要信任快照来源并在之后验证链头。第三,依赖托管归档端点可消除运维负担;关于该选择,请参阅 Arbitrum RPC 端点(RPC Assistant)。
快照流程记录在 Arbitrum Nitro Docker 指南中。它涉及下载快照归档、将其解压到数据目录,并使用 archive 标志启动节点。然后节点将从 L1 同步剩余的批次。此方法比创世同步快得多,但引入了对快照提供者的信任假设。
- 创世同步:无需信任,速度慢,高 IO。
- 快照引导:快速,需要信任快照来源。
- 托管端点:无需运维,但依赖外部。
使用 Docker 运行 Nitro 归档节点
文档化的容器部署针对 L1 以太坊端点运行 Nitro 节点。节点从 L1 读取批次和延迟收件箱,因此除了 L2 数据目录外,还必须提供健康的以太坊 L1 RPC。必须设置 archive 标志,以免状态被修剪。Arbitrum Nitro Docker 指南提供了规范的 Docker 命令和配置。
典型的 Docker 调用包括 L1 端点、L2 链 ID 和 archive 标志的环境变量。数据目录应挂载在具有高耐久性的快速 NVMe 存储上,因为归档存储会持续增长。启动容器后,监控日志以了解同步进度,并确保节点在消耗 L1 收件箱时没有节流。
docker run -d --name nitro-archive \
-v /path/to/data:/home/user/.arbitrum \
-p 8547:8547 -p 8548:8548 \
offchainlabs/nitro-node:v3.0.0 \
--l1.url=https://eth-mainnet.example.com \
--l2.chain-id=42161 \
--node.archive=true \
--http.addr=0.0.0.0 \
--http.port=8547 \
--http.api=eth,net,web3,debug通过历史 RPC 调用验证归档行为
要验证归档节点是否提供历史状态服务,请使用显式的旧区块号(远早于节点近期窗口的区块)调用 eth_getBalance 或 eth_call,并确认它返回值而不是修剪状态错误。然后比较 eth_getBlockByNumber 链头推进与排序器或 L1,以确认节点是活跃的。Arbitrum 关于排序器 feed 的文档解释了如何监控链头进展。
使用以下 curl 示例查询历史余额。将端点和区块号替换为您自己的。区块号应远早于节点的近期窗口(例如 Arbitrum One 上的区块 1000000)。如果节点处于归档模式,它将返回余额;否则,它将返回指示缺少 trie 节点的错误。
curl -X POST https://your-archive-node.example.com \
-H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x0000000000000000000000000000000000000000","0xF4240"],"id":1}'可运行的历史查询 Node.js 示例
以下 Node.js 片段发出历史 eth_call、eth_getBalance 和 eth_getLogs 请求,并打印使用的区块号。它使用内置的 fetch API(Node.js 18+)。将端点和区块号替换为您自己的。此示例帮助您以编程方式验证归档行为。
脚本首先获取当前区块号以建立参考,然后查询历史区块。它打印使用的区块号和结果。如果节点未处于归档模式,历史查询将失败并报错。
const endpoint = 'https://your-archive-node.example.com';
const historicalBlock = 1000000; // Arbitrum One block number
async function rpcCall(method, params) {
const res = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', method, params, id: 1 })
});
return res.json();
}
(async () => {
const head = await rpcCall('eth_blockNumber', []);
console.log('Current head block:', parseInt(head.result, 16));
const balance = await rpcCall('eth_getBalance', ['0x0000000000000000000000000000000000000000', '0x' + historicalBlock.toString(16)]);
console.log(`Balance at block ${historicalBlock}:`, balance.result);
const call = await rpcCall('eth_call', [{ to: '0x0000000000000000000000000000000000000000', data: '0x' }, '0x' + historicalBlock.toString(16)]);
console.log(`eth_call at block ${historicalBlock}:`, call.result);
const logs = await rpcCall('eth_getLogs', [{ fromBlock: '0x' + historicalBlock.toString(16), toBlock: '0x' + historicalBlock.toString(16) }]);
console.log(`Logs at block ${historicalBlock}:`, logs.result.length);
})();可复现验证的结果表
为了使您的验证可复现而不编造数字,请用您自己的端点测量值填写下表。使用远早于节点近期窗口的历史区块号。记录归档调用结果、当前链头区块以及同步延迟(链头区块减去排序器已知的最新区块)。此表帮助您比较不同端点或跟踪节点随时间的健康状况。
该表应填写您自己的数据。不要依赖预填数字。要深入了解历史数据访问,请参阅访问历史区块链数据。
- 端点 URL:[您的端点]
- 使用的历史区块号:[例如 1000000]
- eth_getBalance 结果:[值或错误]
- eth_call 结果:[值或错误]
- eth_getLogs 结果:[数量或错误]
- 当前链头区块:[数字]
- 同步延迟(链头与排序器):[数字]
常见故障与故障排除
常见故障包括“missing trie node”或“historical state unavailable”错误,这意味着 archive 标志关闭或节点仍在回填。快照不匹配可能导致状态根与收件箱不一致,导致节点停滞或拒绝区块。L1 端点节流可能停滞收件箱消耗,阻止节点推进。要诊断,请检查节点日志中的错误并验证 L1 端点的健康状况。
如果遇到“missing trie node”,请确保节点在启动时启用了 archive 标志,并且数据目录包含完整的状态历史。如果使用了快照,请验证其完整性以及是否与预期的状态根匹配。对于 L1 节流,考虑使用专用的 L1 RPC 提供者或提高速率限制。有关同步状态监控,请参阅通过 Engine API 监控 OP Stack 节点同步状态,其中涵盖了 OP Stack 链的类似概念。
- 缺少 trie 节点:archive 标志关闭或正在回填。
- 快照不匹配:状态根与收件箱不一致。
- L1 节流:收件箱消耗停滞。
自托管归档节点的权衡与限制
归档存储持续增长,需要具有高耐久性的快速 NVMe。快照信任是一个真实的安全决策:您信任快照提供者不会包含恶意状态。仅当查询量、数据本地性或合规性超过托管端点的成本时,自托管归档节点才合理。对于许多用例,托管归档端点更具成本效益,且运维开销更少。
考虑总拥有成本:硬件、带宽、监控和升级。如果您的查询量低或间歇性,托管端点可能更便宜。如果您需要保证数据本地性或具有合规要求,自托管可能是必要的。有关定价考虑,请参阅 RPC 定价。
- 存储:持续增长,高耐久性 NVMe。
- 安全:快照信任假设。
- 成本:自托管与托管端点的权衡。
下一步:选择端点与进一步阅读
验证归档节点后,您可能想探索用于生产环境的托管端点。Arbitrum RPC 端点(RPC Assistant)页面提供了提供者列表。要更广泛地了解归档节点,请参阅归档节点与全节点对比和访问历史区块链数据。
要了解 OnFinality 的 API 服务,请访问 API 服务。更多教程,请探索 OnFinality Learn 中心。如果您正在使用其他网络,请参阅 Base 归档节点与历史 RPC 和 Arbitrum 网络页面。
- 托管端点:Arbitrum RPC 端点(RPC Assistant)
- 进一步阅读:归档节点与全节点对比
- OnFinality 服务:API 服务、RPC 定价