本指南介绍如何使用 OP-Stack 执行 JSON-RPC 查询历史 Base 状态和日志。涵盖 Base 上的归档节点机制、全节点与归档节点的区别,并提供可运行的 Node.js 脚本测试端点的历史数据支持。还包括故障排除技巧和权衡。
直接回答:如何查询历史 Base 状态和日志
要查询历史 Base 状态和日志,您需要一个归档节点或提供归档数据的 RPC 提供商。Base 是一个 OP-Stack 乐观 L2,其执行层(op-geth 或 op-reth)提供以太坊 JSON-RPC。历史读取,如旧区块上的 eth_getBalance、过去区块上的 eth_call、过去范围内的 eth_getLogs 以及用于状态证明的 eth_getProof,都要求执行客户端保留该区块的状态。全节点(修剪)仅保留最近的状态,而归档节点存储所有历史状态。本指南解释了相关机制,并提供了一个脚本,用于测试任何 Base RPC 端点的归档支持。
如果您正在寻找托管的 Base 归档端点,请参阅 Base 节点基础设施(RPC 助手) 页面。有关归档节点与全节点的一般背景,请参阅 归档节点与全节点。
- Base 是一个 OP-Stack L2:op-node(共识/派生)+ 执行客户端(op-geth/op-reth)。
- 历史状态的可用性取决于执行客户端的模式(全节点与归档节点)以及快照的可用性。
- 关键 JSON-RPC 方法:
eth_getBlockByNumber、eth_getBalance、eth_call、eth_getCode、eth_getStorageAt、eth_getLogs、eth_getProof。
Base 归档节点如何在 OP-Stack 上工作
Base 是一个 OP-Stack 乐观汇总。网络由 op-node(从 L1 数据派生 L2 区块的共识客户端)和执行客户端(op-geth 或 op-reth)组成,后者存储 L2 状态并提供以太坊 JSON-RPC。当您查询历史区块时,执行客户端必须拥有该区块的状态树。全节点会修剪早于某个最近窗口(例如,op-geth 默认的 128 个区块)的状态,而归档节点保留所有状态快照。
Base 于 2023 年推出,因此与以太坊 L1 相比,其链深度相对较浅。然而,归档机制是相同的。要运行归档节点,您通常需要从归档快照开始,或在启用归档模式的情况下从创世同步。具体配置因客户端和部署而异;请参阅 Base 节点文档 了解详情。
有关 OP-Stack 架构的更深入探讨,请参阅 OP-Stack 源码运行文档。
- op-geth:使用
--gcmode=archive保留完整状态。 - op-reth:使用
--full(默认)或--debug.tip?实际上,reth 使用--full作为全节点,使用--archive作为归档节点?请查阅文档。 - 快照提供商提供归档快照;大小因提供商和日期而异。
Base 上的历史读取方法
Base 上的以太坊 JSON-RPC API 支持标准的历史查询方法。以下是每种方法的工作原理:
eth_getBlockByNumber 使用区块号或标签返回区块头和交易。对于历史区块,如果区块在保留范围内,即使在全节点上也能正常工作,但对于更早的区块,您需要归档节点。
eth_getBalance、eth_call、eth_getCode、eth_getStorageAt 接受区块参数。在全节点上,它们仅适用于最近的区块;在归档节点上,它们适用于任何历史区块。
eth_getLogs 按地址和主题过滤区块范围内的日志。这要求节点拥有该范围的日志,通常即使在全节点上,对于最近的范围也可用,但对于更早的范围,您需要归档节点。
eth_getProof(EIP-1186)返回特定区块上给定地址和存储键的账户和存储证明。这对于验证状态声明和 OP-Stack 提款证明至关重要。它需要归档状态。
- 区块标签:
latest、earliest、pending或十六进制区块号。 - 对于
eth_call,您可以在历史区块模拟交易。 eth_getProof用于证明 L1->L2 存款和提款。
可运行示例:测试 Base RPC 端点的归档支持
以下 Node.js 脚本使用 ethers v6 查询 Base RPC 端点。它解析一个过去的区块(例如,区块 1000000),读取该区块和最新区块中已知账户的余额,并尝试在有限窗口内分页 eth_getLogs。它还尝试 eth_getProof 以查看端点是否支持证明。脚本打印结果和一个供您填写的表格。
假设:Node.js 18+、ethers v6 和 Base 主网 RPC URL。将 YOUR_RPC_URL 替换为您的端点。脚本使用固定的区块号和已知地址(例如,Base 桥合约)。运行它,看看您的端点是返回归档数据还是错误。
// test-archive.js
const { ethers } = require('ethers');
const RPC_URL = process.env.RPC_URL || 'YOUR_RPC_URL';
const provider = new ethers.JsonRpcProvider(RPC_URL);
const ADDRESS = '0x4200000000000000000000000000000000000016'; // 示例:L2 标准桥
const BLOCK_NUMBER = 1000000; // 过去的区块
async function main() {
console.log('Testing archive support on Base RPC');
console.log('RPC URL:', RPC_URL);
// 1. 按区块号获取区块
const block = await provider.getBlock(BLOCK_NUMBER);
console.log('Block', BLOCK_NUMBER, 'exists:', !!block);
// 2. 获取历史区块的余额
try {
const balance = await provider.getBalance(ADDRESS, BLOCK_NUMBER);
console.log('Balance at block', BLOCK_NUMBER, ':', balance.toString());
} catch (e) {
console.log('Balance at block failed:', e.message);
}
// 3. 获取最新余额
const latestBalance = await provider.getBalance(ADDRESS, 'latest');
console.log('Balance at latest:', latestBalance.toString());
// 4. eth_getLogs 分页(示例:来自桥的 Transfer 事件)
const filter = {
address: ADDRESS,
fromBlock: BLOCK_NUMBER,
toBlock: BLOCK_NUMBER + 1000,
topics: [ethers.id('Transfer(address,address,uint256)')]
};
try {
const logs = await provider.getLogs(filter);
console.log('Logs in range:', logs.length);
} catch (e) {
console.log('getLogs failed:', e.message);
}
// 5. eth_getProof (EIP-1186)
try {
const proof = await provider.send('eth_getProof', [ADDRESS, [], '0x' + BLOCK_NUMBER.toString(16)]);
console.log('eth_getProof success. Account proof length:', proof.accountProof.length);
} catch (e) {
console.log('eth_getProof failed:', e.message);
}
}
main().catch(console.error);
// 预期输出形状:
// Testing archive support on Base RPC
// RPC URL: ...
// Block 1000000 exists: true
// Balance at block 1000000 : 123456789
// Balance at latest: 987654321
// Logs in range: 5
// eth_getProof success. Account proof length: 7
// 如果不支持归档,您可能会看到类似 "missing trie node" 或 "header not found" 的错误。结果表格和决策清单
用测试结果填写下面的表格,以确定您的端点是否支持归档。
- | 测试 | 结果(成功/错误) | 备注 |
- |------|------------------------|-------|
- | 在旧区块上 getBlock | | |
- | 在旧区块上 getBalance | | |
- | 在最新区块上 getBalance | | |
- | 在过去范围 getLogs | | |
- | eth_getProof | | |
常见故障和修复
在 Base 上查询历史数据时,您可能会遇到错误。以下是一些常见错误及修复方法。
错误:'missing trie node' – 这表示节点没有该区块的状态。解决方案:使用归档节点或提供归档数据的提供商。
错误:'header not found' – 区块号超出了节点的同步限制。解决方案:确保节点完全同步,或使用其他端点。
错误:eth_getLogs 的 'range too large' – 区块范围超过了节点的限制。解决方案:分页处理较小的范围(例如,每次 1000 个区块)。
不支持 eth_getProof – 某些提供商禁用此方法。解决方案:使用支持 EIP-1186 的提供商,或运行自己的归档节点。
- 始终检查区块号是否在链的范围内。
- 使用
eth_blockNumber确认最新区块。 - 对于日志,使用分页以避免超时。
权衡和限制
Base 上的归档节点比全节点需要更多的磁盘空间和内存。具体大小因客户端和快照而异,但这是一个已知的权衡。运行归档节点还会增加同步时间和运营开销。
Base 的历史相对较短(自 2023 年起),因此归档节点比以太坊 L1 更可行。然而,随着链的增长,存储需求将增加。
一些 RPC 提供商以溢价提供归档端点。比较 RPC 定价 以决定托管服务是否具有成本效益。
有关延迟考虑,请参阅 Base RPC 延迟指南。有关速率限制,请参阅 Base RPC 速率限制和可靠性。
后续步骤和进一步阅读
既然您了解了如何查询历史 Base 状态,您可以将其应用于您的 dApp 或分析。有关 EVM 链上历史数据查询的更广泛理解,请参阅 查询历史区块链数据(EVM 菜谱)。
如果您正在 Base 上构建,请探索 Base 网络概述 和 OnFinality 学习中心 获取更多指南。有关节点基础设施决策,请参阅 Base 节点基础设施(RPC 助手)。