Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
网络与协议指南约 12 分钟

如何通过 RPC 查询历史区块链数据

了解全节点、归档节点和追踪节点之间的区别,以及如何使用 eth_getBlockByNumber、eth_call、eth_getCode 和 eth_getStorageAt 查询过去的状态。

TL;DR

要通过 RPC 查询历史区块链数据,你需要一个归档节点来获取过去区块的状态(eth_call、eth_getBalance、eth_getCode、eth_getStorageAt),或者一个全节点来获取历史区块和日志(eth_getBlockByNumber、eth_getLogs)。对于大规模扫描,请使用索引器或追踪 API。本指南解释了这些差异并提供了可运行的示例。

简要回答:全节点 vs 归档节点 vs 追踪节点

当你需要通过 RPC 获取历史区块链数据时,首先要决定使用哪种节点类型。全节点存储所有区块和交易,但只保留最新状态(账户余额、合约存储)。归档节点存储所有历史状态快照,支持诸如“这个地址在区块 10,000,000 时的余额是多少?”之类的查询。追踪节点额外存储执行追踪,支持深度重放交易和状态差异。对于大多数历史查询,你需要归档节点;对于区块和日志数据,全节点就足够了。

这种区别至关重要,因为像 eth_getBalanceeth_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_getTransactionByHasheth_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 服务以避免节点维护。查看我们的定价了解归档计划。

有关更多 RPC 最佳实践,请阅读我们的 RPC 端点指南监控 RPC 端点

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始