Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
集成与开发阅读约 9 分钟

如何从 EVM 或 Solana RPC 获取当前区块号

一份可复现的指南,介绍如何从 RPC 端点读取最新区块号、验证其新鲜度,并诊断结果过期或不一致的问题。

TL;DR

区块号是区块在链历史中的规范位置,每个 JSON-RPC 提供商都通过一小组方法暴露它。在 EVM 链上调用 eth_blockNumber;在 Solana 上读取 getSlot 或 getBlockHeight;其他网络的方法名不同,但模式相同。本文展示可运行的调用,解释返回值实际代表什么,并给出确认所获数字新鲜且一致的测量流程。还涵盖区块号看似过期、跳变或在两个端点间不一致的常见原因。

区块号代表什么以及为何重要

区块号是一个单调递增的整数,标识区块在链中的位置。在 EVM 网络中,创世区块为区块 0,后续每个区块号递增 1。因此,最新区块号是链已推进多远以及你的 RPC 视图有多新的代理指标。

应用将区块号用于许多场景:通过特定区块上的 eth_call 将查询固定到一致状态、判断交易是否已包含、计算确认深度,或检测索引器是否落后。由于获取区块号成本低廉,它也是 RPC 连接的标准健康检查。

重要的细微之处在于,“最新区块号”在给定时刻并非单一的全局真相。不同节点获知新区块的时间略有差异,负载均衡端点可能将连续请求路由到不同后端。应将返回值视为采样观测,而非精确时钟。

  • EVM:eth_blockNumber 以十六进制数量返回最新区块高度。
  • Solana:getSlot 返回当前 slot;getBlockHeight 返回最后确认区块的高度。
  • 其他链:方法名各异,但概念是头部高度或 slot 编号。

前提条件与假设

你需要所查询网络的 HTTP 或 WebSocket RPC URL。本指南使用占位符 RPC_URL;请替换为你获得的端点。如需托管端点,请参阅 OnFinality API 服务 和 支持的网络列表。

示例假设可通过 HTTPS 访问 JSON-RPC 接口。EVM 示例使用标准 Ethereum JSON-RPC 方法,大多数 EVM 兼容链均实现这些方法。Solana 示例使用其 JSON-RPC API。读取区块号不需要私钥;这些是公开读取方法。

如果你是在选择提供商而非编写代码,具体的端点推荐应属于 RPC Assistant。本文侧重于方法、验证流程和故障模式。

使用 curl 在 EVM 链上获取区块号

最简单的 EVM 调用是 eth_blockNumber。它不接受参数,返回十六进制编码的数量。替换 RPC_URL 后,以下命令即可运行:

  • 成功响应形如 {"jsonrpc":"2.0","id":1,"result":"0x..."}。
  • result 字段是十六进制字符串;在比较或存储前将其转换为十进制。
  • 若返回 error 对象而非 result,通常意味着方法不受支持或请求格式错误。
curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'

在 JavaScript 和 Python 中获取区块号

在应用代码中,你通常会将调用包装成一个小辅助函数。下面的 JavaScript 示例使用现代 Node.js 和浏览器内置的 fetch,并将十六进制结果转换为数字:

const RPC_URL = process.env.RPC_URL;

async function getBlockNumber() {
  const res = await fetch(RPC_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      jsonrpc: '2.0',
      id: 1,
      method: 'eth_blockNumber',
      params: []
    })
  });
  const json = await res.json();
  if (json.error) throw new Error(json.error.message);
  return Number.parseInt(json.result, 16);
}

getBlockNumber().then(console.log).catch(console.error);

在 Solana 上获取区块号

Solana 不使用 eth_blockNumber。最接近的等价方法是 getSlot(返回节点正在处理的当前 slot)和 getBlockHeight(返回最后确认区块的高度)。Slot 和区块高度相关但不相同:slot 可能被跳过,因此区块高度增长比 slot 编号慢。

需要集群当前位置时使用 getSlot;需要适合索引或确认逻辑的已确认高度时使用 getBlockHeight。下面的 curl 调用使用 getSlot:

  • commitment 参数控制你观察到的集群状态;在分叉情况下,confirmed 和 finalized 行为不同。
  • getBlockHeight 接受相同的 commitment 选项,返回数字而非 slot。
  • 不要将 Solana slot 直接与 EVM 区块号比较;它们是不同的单位。
curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment":"confirmed"}]}'

验证区块号是否新鲜

返回的数字只有在当前时才有用。检查新鲜度的可靠方法是以已知间隔对同一端点采样两次,并将差值与该链的预期出块时间比较。以下流程生成一个结果表,你可以填入自己的观测值;不要预先假设任何数值。

对每个待评估端点同时运行采样脚本,持续相同时间。记录第一个区块号、最后一个区块号、经过的秒数以及计算出的每秒区块数。然后将该速率与网络文档中的目标出块时间比较。大幅不足表明节点滞后或端点被限流。

  • | 端点 | 首个区块 | 最后区块 | 经过时间(秒) | 区块/秒 | 备注 |
  • |----------|-------------|------------|-------------|----------|-------|
  • | RPC_URL A | | | | | |
  • | RPC_URL B | | | | | |
import os, time, requests

RPC_URL = os.environ["RPC_URL"]
INTERVAL = 5
SAMPLES = 12

def block_number():
    p = {"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}
    r = requests.post(RPC_URL, json=p, timeout=10).json()
    return int(r["result"], 16)

first = block_number()
start = time.time()
for _ in range(SAMPLES):
    time.sleep(INTERVAL)
    last = block_number()
elapsed = time.time() - start
print({"first": first, "last": last, "elapsed_s": round(elapsed, 1),
       "blocks_per_s": round((last - first) / elapsed, 3)})

交叉检查两个端点的一致性

单个端点可能内部一致,但相对于网络其余部分仍然错误。要检测这一点,在短时间窗口内查询两个独立端点并比较其区块号。小差异是正常的传播延迟;大差异或不断扩大的差异表明一个端点滞后。

对于 EVM 链,你还可以通过区块头确认区块号:使用 latest 标签调用 eth_getBlockByNumber,检查返回的 number 字段是否与 eth_blockNumber 报告的一致。若不一致,端点可能在跨不同高度的后端进行负载均衡。

  • 将区块对象中的 number 字段与 eth_blockNumber 结果比较。
  • 检查区块 timestamp 以估算头部有多旧。
  • 重复比较几次,观察差距是稳定还是扩大。
curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",false]}'

排查过期、缺失或不一致的区块号

当区块号看起来错误时,按可能性顺序排查原因。大多数事件是配置或速率限制问题,而非链问题。

如果 eth_blockNumber 返回错误,确认方法名以及端点是否对应正确的网络。在以太坊上有效的方法在非 EVM 链上可能不存在。如果调用成功但数字从不变化,端点可能返回缓存响应,或节点可能落后。如果数字以意外幅度跳变,你可能遇到将请求路由到不同后端的负载均衡器,或链可能经历了一段快速出块期。

  • HTTP 429 或提供商特定的速率限制错误:减慢请求速度或使用专用端点。
  • 超时:添加显式客户端超时和带退避的重试。
  • 十六进制解析错误:确保以 16 为基数转换,而非 10。
  • Solana slot 与区块高度混淆:选择与你的确认语义匹配的方法。
  • WebSocket 订阅:连接断开可能导致缓存数字过期;重新连接时重新订阅并重新获取。

区块号检查的局限性与权衡

区块号是粗略的健康信号。它告诉你链在推进,但不表示端点对其他方法正确、完整或快速。节点可能报告当前区块号,却在 eth_call 上失败或对归档查询返回不一致状态。

采样频率也是一种权衡。每秒轮询提供更细粒度,但消耗速率限制预算,并可能在受限端点上扭曲测量。对于生产监控,中等间隔结合持续滞后的告警通常比高频轮询更有用。

最后,区块号是链特定的。在一个网络上有效的数字在另一个网络上毫无意义,因此始终将值与网络标识符及获取方法配对。

生产使用的后续步骤

一旦你能读取并验证区块号,下一步是将其构建到应用的健康检查和索引逻辑中。将区块号与持久化的任何状态一起存储,以便日后检测缺口和重组。对于需要一致链头访问的工作负载,考虑使用 专用节点 而非共享公共端点。

如果你在比较提供商或需要特定网络的具体端点,使用 RPC Assistant 获取简短推荐,并将本文作为验证方法。关于容量规划和成本,请查看 RPC 定价 和更广泛的 RPC 端点指南。

  • 记录带时间戳的区块号以建立滞后基线。
  • 当观察到的速率低于你根据自身测量得出的阈值时告警。
  • 在任何提供商或网络变更后重新验证。

永远不用担心基础设施

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

开始