要通过 RPC 查询历史区块链数据,你需要一个归档节点来获取过去区块的状态(eth_call、eth_getBalance、eth_getCode、eth_getStorageAt),或者一个全节点来获取历史区块和日志(eth_getBlockByNumber、eth_getLogs)。对于大规模扫描,请使用索引器或追踪 API。本指南解释了这些差异并提供了可运行的示例。
简要回答:全节点 vs 归档节点 vs 追踪节点
当你需要通过 RPC 获取历史区块链数据时,首先要决定使用哪种节点类型。全节点存储所有区块和交易,但只保留最新状态(账户余额、合约存储)。归档节点存储所有历史状态快照,支持诸如“这个地址在区块 10,000,000 时的余额是多少?”之类的查询。追踪节点额外存储执行追踪,支持深度重放交易和状态差异。对于大多数历史查询,你需要归档节点;对于区块和日志数据,全节点就足够了。
这种区别至关重要,因为像 eth_getBalance 和 eth_call 这样的 RPC 方法接受区块参数。在全节点上,传入过去的区块会返回错误或不正确的数据,因为状态已被修剪。在归档节点上,同样的调用会返回准确的历史值。请参阅我们的归档节点与全节点指南以深入了解。
- 全节点:存储所有区块、交易、收据,但仅存储最新状态。
- 归档节点:存储所有历史状态快照,支持在任何区块进行状态查询。
- 追踪节点:存储执行追踪,支持重放和深度分析(例如 Parity trace 模块)。
理解节点修剪和状态可用性
以太坊客户端如 Geth 和 Nethermind 默认修剪历史状态。它们只保留最新的状态树和有限数量的近期状态(例如 128 个区块)。这意味着在全节点上,使用过去的区块参数调用 eth_getBalance 会失败。具体错误因客户端而异:Geth 返回 "missing trie node" 或 "header not found",而 Nethermind 可能返回 "Cannot read state at block ..."。
归档节点禁用修剪,存储每个状态快照。这需要大量磁盘空间——数百 GB 到 TB 级。例如,截至 2026 年,以太坊归档节点可能超过 2 TB。像 OnFinality 的 RPC 服务 这样的提供商为以太坊和其他网络提供归档端点,因此你不必自己运行。
当你查询公共 RPC 端点时,你不知道它是归档还是全节点。始终检查文档或使用已知的历史状态进行测试。例如,查询一个知名地址在旧区块的余额,并与区块浏览器进行比较。
curl -X POST https://eth-mainnet.public.blastapi.io -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "0x5F5E100"],"id":1}'查询历史区块和交易
历史区块和交易数据在任何全节点上都是可用的。eth_getBlockByNumber 返回区块头、交易以及可选的完整交易对象。eth_getTransactionByHash 和 eth_getTransactionReceipt 适用于任何过去的交易。这些方法不需要归档状态。
例如,获取区块 15,000,000(0xE4E1C0)及其完整交易:
这对于审计、分析和同步应用很有用。然而,对于大规模扫描(例如代币的所有转账),使用 eth_getLogs 比遍历区块更高效。
curl -X POST https://eth-mainnet.public.blastapi.io -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0xE4E1C0", true],"id":1}'查询历史状态:eth_call、eth_getBalance、eth_getCode、eth_getStorageAt
要查询过去区块的状态,你需要一个归档节点。关键方法有:
eth_getBalance(address, block)– 在给定区块的余额。
eth_getCode(address, block)– 在给定区块的合约字节码。
eth_getStorageAt(address, slot, block)– 在给定槽位的存储值。
eth_call({to, data}, block)– 在过去的区块模拟调用,用于历史合约读取。
这些方法接受区块参数,可以是十六进制数字、标签("latest"、"earliest"、"pending")或区块哈希。在归档节点上,它们返回准确的历史值。
示例:获取以太坊基金会钱包在区块 10,000,000(0x989680)的余额:
如果你遇到类似 "missing trie node" 的错误,说明该节点不是归档节点。你需要切换到归档端点。OnFinality 为以太坊和其他网络提供归档端点;详情请参阅我们的以太坊网络页面。
curl -X POST https://eth-mainnet.public.blastapi.io -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae", "0x989680"],"id":1}'使用 eth_getLogs 查询历史事件数据
eth_getLogs 是查询历史事件日志(例如代币转账、DEX 交易)的主力工具。它适用于全节点,因为日志存储在收据中,而收据会无限期保留。你可以按地址、主题和区块范围进行过滤。
示例:获取从区块 15,000,000 到 15,000,100 的所有 USDT 转账事件(合约 0xdAC17F958D2ee523a2206206994597C13D831ec7):
请注意,eth_getLogs 有局限性:大多数提供商限制区块范围(例如 10,000 个区块)和响应大小。对于大规模历史扫描,请使用像 The Graph 这样的索引器或专门的数据服务。请参阅我们的多链 RPC 端点指南了解提供商选项。
curl -X POST https://eth-mainnet.public.blastapi.io -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0xE4E1C0","toBlock":"0xE4E1C4","address":"0xdAC17F958D2ee523a2206206994597C13D831ec7","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]}],"id":1}'用于深度历史分析的追踪 API
对于交易级重放、状态差异和内部调用,你需要一个带有 trace_ 模块(Parity/OpenEthereum)或 debug_ 模块(Geth)的追踪节点。这些不是标准的 JSON-RPC 方法,但一些提供商提供。
示例:trace_replayTransaction 返回交易的所有子调用和状态更改。这对于重建历史状态更改很有用,但计算成本高,且经常受到速率限制。
追踪数据对于索引器和分析平台至关重要。如果你需要这些,请确保你的 RPC 提供商支持追踪方法。OnFinality 的 API 服务 为支持的网络提供追踪端点。
curl -X POST https://rpc.trace.example.com -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"trace_replayTransaction","params":["0xhash", ["trace", "stateDiff"]],"id":1}'常见错误和故障排除
查询历史数据时,你可能会遇到特定错误。以下是一个检查清单:
"missing trie node"或"header not found"– 节点不是归档节点。请使用归档端点。
"block not found"– 区块号超出范围或节点未同步。
"execution reverted"– 调用在该区块回滚;请检查合约逻辑。
"query returned more than 10000 results"– 减少eth_getLogs中的区块范围。
"rate limit exceeded"– 你达到了提供商限制;请考虑批量请求或使用专用端点。
为了性能,请使用 JSON-RPC 批量请求最佳实践 将多个查询合并为一个请求。
- 始终使用已知的历史值进行测试,以验证归档支持。
- 使用区块号而不是时间戳以确保精确性。
- 对于大规模扫描,请使用索引器或通过数据服务导出数据。
权衡:全节点 vs 归档节点 vs 索引器
选择合适的工具取决于你的用例:
- 全节点:最便宜,适合当前状态和近期历史,但没有历史状态。
- 归档节点:昂贵,是历史状态查询所必需的,但受 RPC 速率限制和区块范围上限的限制。
- 索引器(The Graph、SubQuery):最适合大规模历史查询,但需要设置和索引时间。
对于偶尔的历史查询,归档 RPC 端点就足够了。对于生产级分析,请考虑索引器。如果你想运行自己的节点,请参阅我们的区块链节点托管指南。
- 归档节点比全节点大 10-100 倍。
- RPC 提供商通常对归档访问收取更高费用。
- 索引器提供 GraphQL API 用于复杂查询。
后续步骤和进一步阅读
现在你已经了解了如何查询历史数据,可以开始构建了。对于以太坊,请使用公共归档端点进行测试,或使用 OnFinality 的以太坊 RPC。对于 Polkadot,历史查询的工作方式不同;请参阅我们的Polkadot 网络页面。
如果你正在构建需要可靠历史数据的应用程序,请考虑使用托管 RPC 服务以避免节点维护。查看我们的定价了解归档计划。