Sui 通过 JSON-RPC 方法(如 suix_getLatestSuiSystemState 和 sui_getLatestCheckpointSequenceNumber)暴露协议级系统状态。这些读取操作会返回当前纪元、其起始时间戳和持续时间、协议版本、参考 Gas 价格,以及带有质押量和投票权的活跃验证者集合。运维人员和索引器使用它们进行健康检查、延迟检测和检查点对账。本文解释了纪元模型、请求封装、负载精简策略,并提供了一个可运行的 Node.js 示例。文中还包含可复现的结果表格以及常见问题的排查指南。
Sui RPC 中的用户状态与系统状态
Sui 的 JSON-RPC 接口分为两大类:用户状态和系统状态。用户状态涵盖对象、代币、交易和事件——即应用程序和最终用户直接交互的数据。系统状态涵盖协议级参数:当前纪元、验证者委员会、质押池、参考 Gas 价格和协议版本。这些并非用户拥有的对象;它们描述的是网络的运行上下文。
这一区分很重要,因为这两类数据的读取模式和成本不同。用户状态读取通常是针对地址或对象 ID 的点查询或分页查询。相比之下,系统状态读取会返回一个包含完整验证者集合的大型对象。该负载更重且变化频率较低,因此缓存和摘要字段变得很重要。
对于运维人员和索引器而言,系统状态是健康检查和对账的权威来源。如果你的索引器记录了交易却没有记录交易发生的纪元,那么之后就无法根据委员会轮换或 Gas 价格变化来对账数据。Sui RPC 指南涵盖了更广泛的方法范围,而本文则专门聚焦于系统状态读取路径。
- 用户状态:对象、代币、交易、事件——以地址或 ID 为范围。
- 系统状态:纪元、委员会、质押、Gas 价格、协议版本——网络范围。
- 系统状态读取更重,应尽可能缓存或摘要化。
Sui 纪元模型及其对长时间运行任务的重要性
Sui 以纪元为单位推进,纪元是由起始时间戳和持续时间定义的有限周期。在每个纪元边界,验证者委员会可能轮换,质押奖励会被分配,参考 Gas 价格也可能变化。Sui 纪元概念文档描述了纪元持续时间如何设定以及委员会轮换如何运作。
对于任何长时间运行的任务——索引器、监控代理或对账脚本——纪元都是关键的元数据。如果你记录了交易的效果却没有记录纪元,就会失去将该数据与处理它的委员会或当时生效的 Gas 价格关联起来的能力。这对于需要审计质押变化或 Gas 成本随时间变化的金融应用尤为重要。
纪元起始时间戳和持续时间在系统状态对象中以 epochStartTimestampMs 和 epochDurationMs 返回。这些字段让你可以计算当前纪元的剩余时间,这对于安排维护或预判委员会变化很有用。不过,这些时间戳由节点生成,可能相对于你的客户端存在时钟偏差。
- 纪元限定了委员会轮换、质押奖励和 Gas 价格变化。
- 在索引数据时一并记录纪元,以便后续对账。
- epochStartTimestampMs 和 epochDurationMs 可用于计算纪元剩余时间。
使用 suix_getLatestSuiSystemState 读取系统状态
方法 suix_getLatestSuiSystemState 返回最新的 SUI 系统状态对象。根据 Sui JSON-RPC API 参考,该对象包含当前纪元、epochStartTimestampMs、epochDurationMs、safeMode、protocolVersion、referenceGasPrice 以及活跃验证者集合。每个验证者条目包含 name、stakingPoolId、votingPower、stake 和 gasPrice 等字段。
这是读取协议级状态的主要方法。它是一次调用返回大型负载,因此不应高频轮询。对于监控而言,每个纪元一次或每几分钟一次的频率通常就足够了。Sui 验证者与质押概念解释了投票权和质押池与委员会的关系。
由于验证者列表很大,一些提供商提供摘要字段或返回精简视图的替代方法。这些优化措施的可用性因提供商而异,并有相应文档说明。在支持的情况下,轻量监控优先使用摘要读取,将完整系统状态保留用于对账或详细分析。
- 返回纪元、时间戳、协议版本、Gas 价格和验证者集合。
- 验证者条目包含 name、stakingPoolId、votingPower、stake 和 gasPrice。
- 负载较重;避免高频轮询,并在可用时优先使用摘要字段。
使用 sui_getLatestCheckpointSequenceNumber 进行轻量存活检测
方法 sui_getLatestCheckpointSequenceNumber 仅返回最新的已认证检查点序列号。与获取完整系统状态相比,这是一个开销很小的调用。它可用作存活探针:如果序列号在推进,说明节点正在产生或接收检查点。如果停滞,节点可能落后或已断开连接。
将此方法与系统状态结合使用,可以获得延迟信号。系统状态告诉你网络当前的纪元和委员会;检查点序列号告诉你节点的检查点尖端已推进到何处。如果将节点的尖端与来自另一个端点的参考尖端进行比较,就可以检测出落后于网络的节点。
关于检查点消费的更深入讨论,请参阅检查点流与账本服务一文。那篇文章涵盖流式检查点,而本文则聚焦于将序列号作为轻量探针使用。
- 仅返回最新的已认证检查点序列号——开销小且速度快。
- 用作存活探针,并针对参考尖端进行延迟检测。
- 与系统状态配合,将检查点进度与纪元边界关联起来。
JSON-RPC 请求封装与成本考量
所有 Sui JSON-RPC 调用都使用标准的 JSON-RPC 2.0 封装:jsonrpc 字段设为 "2.0",id 用于请求关联,method 字符串,以及 params 数组或对象。JSON-RPC 2.0 规范定义了此结构。Sui 的方法遵循这一约定,方法名如 suix_getLatestSuiSystemState 和 sui_getLatestCheckpointSequenceNumber。
成本方面的注意事项是,系统状态读取比点查询更重。调用 suix_getLatestSuiSystemState 会返回完整的验证者集合,可能包含数百个条目。这比简单的对象查询消耗更多带宽和处理时间。对于高频监控,请改用 sui_getLatestCheckpointSequenceNumber,或检查你的提供商是否提供摘要方法。
在构建监控循环时,应将频率分开:频繁轮询检查点序列号以检测存活,较少获取完整系统状态以获取纪元和委员会数据。这可以减轻客户端和节点的负载。
- 封装:jsonrpc、id、method、params——遵循 JSON-RPC 2.0。
- 系统状态读取比点查询更重;相应调整轮询频率。
- 使用检查点序列进行频繁存活检测;使用系统状态进行定期对账。
可运行的 Node.js 示例:获取并汇总系统状态
以下示例使用 @mysten/sui 客户端获取最新的系统状态和检查点序列号,计算当前纪元的剩余时间,并打印一份简洁的健康摘要。它假定你有一个 Sui RPC 端点 URL。请将占位符替换为你的提供商端点。
该脚本会打印 epoch、epochStartTimestampMs、epochDurationMs、protocolVersion、referenceGasPrice 以及活跃验证者数量。然后获取最新的检查点序列号,并以毫秒为单位计算纪元剩余时间。最后打印一行健康摘要。
此示例刻意保持精简。在生产环境中,你会添加错误处理、重试,并可能添加与参考端点的比较以进行延迟检测。
import { SuiClient } from '@mysten/sui/client';
const client = new SuiClient({ url: 'https://your-sui-rpc-endpoint.example' });
async function main() {
const systemState = await client.getLatestSuiSystemState();
const epoch = systemState.epoch;
const epochStart = Number(systemState.epochStartTimestampMs);
const epochDuration = Number(systemState.epochDurationMs);
const protocolVersion = systemState.protocolVersion;
const referenceGasPrice = systemState.referenceGasPrice;
const activeValidators = systemState.activeValidators.length;
const checkpointSeq = await client.getLatestCheckpointSequenceNumber();
const now = Date.now();
const elapsed = now - epochStart;
const remaining = Math.max(0, epochDuration - elapsed);
console.log('Epoch:', epoch);
console.log('Epoch start (ms):', epochStart);
console.log('Epoch duration (ms):', epochDuration);
console.log('Protocol version:', protocolVersion);
console.log('Reference gas price:', referenceGasPrice);
console.log('Active validators:', activeValidators);
console.log('Latest checkpoint seq:', checkpointSeq);
console.log('Remaining epoch time (ms):', remaining);
console.log('Health: epoch', epoch, '| validators', activeValidators, '| checkpoint', checkpointSeq, '| remaining', remaining, 'ms');
}
main().catch(console.error);使用 curl 的原始 JSON-RPC 示例
如果你不想使用 SDK,可以直接用 curl 调用这些方法。以下示例发送一个 JSON-RPC 请求以获取最新系统状态,并使用 jq 提取纪元和验证者数量。请将端点 URL 替换为你的提供商端点。
这种方法适用于快速检查或集成到 shell 脚本中。请注意响应很大;通过 jq 管道只提取所需字段可以减少噪音。
对于检查点序列号,展示了单独的调用。你可以在脚本中组合这两个调用,以计算延迟或纪元剩余时间。
curl -s -X POST https://your-sui-rpc-endpoint.example \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"suix_getLatestSuiSystemState","params":[]}' \
| jq '{epoch: .result.epoch, protocolVersion: .result.protocolVersion, referenceGasPrice: .result.referenceGasPrice, validatorCount: (.result.activeValidators | length)}'
curl -s -X POST https://your-sui-rpc-endpoint.example \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"sui_getLatestCheckpointSequenceNumber","params":[]}' \
| jq '{latestCheckpointSeq: .result}'针对你的端点的可复现结果表格
要衡量你自己端点的行为,请填写下表。针对你的端点运行 Node.js 或 curl 示例并记录数值。在不同时间重复运行,以观察纪元变化和检查点推进。
表格列捕获关键字段:端点、纪元、protocolVersion、referenceGasPrice、活跃验证者数量、最新检查点序列号、节点尖端序列号(如果你有参考),以及延迟信号。延迟信号可以计算为你的节点检查点序列号与来自另一个端点的参考尖端之间的差值。
此表是一个模板。你记录的数值是你自己的测量结果;此处不提供这些数值。用它来建立基线并随时间检测异常。
- Endpoint:你正在测试的 RPC URL。
- Epoch:来自系统状态的当前纪元编号。
- ProtocolVersion:节点报告的协议版本。
- ReferenceGasPrice:当前参考 Gas 价格。
- ActiveValidatorCount:委员会中活跃验证者的数量。
- LatestCheckpointSeq:节点最新的已认证检查点序列号。
- NodeTipSeq:来自另一个端点的参考尖端(如果可用)。
- LagSignal:NodeTipSeq 减去 LatestCheckpointSeq(正值表示你的节点落后)。
系统状态读取的局限性与权衡
验证者列表很大,可以精简。一些提供商提供摘要字段或返回精简视图的替代方法。这些优化措施的可用性因提供商而异,并有相应文档说明。如果你的提供商不支持它们,你就必须获取完整负载并提取所需内容。
纪元时间字段具有参考价值,但会受到节点与客户端之间时钟偏差的影响。epochStartTimestampMs 由节点生成;如果你的客户端时钟不同,计算出的剩余时间可能会有偏差。应将其视为估计值,而非精确倒计时。
safeMode 和 protocolVersion 可能在升级时发生变化。处于安全模式的节点可能会暂停某些操作,而协议版本会随网络升级而递增。你的监控应将它们视为动态字段,并对意外变化发出警报。方法可用性也因提供商而异,并有相应文档说明;并非所有端点都暴露每个方法。
- 验证者列表较重;摘要字段取决于提供商。
- 纪元时间戳受时钟偏差影响;将剩余时间视为估计值。
- safeMode 和 protocolVersion 可能在升级时变化;监控意外值。
- 方法可用性因提供商而异;在依赖某个方法前请先确认。
排查常见的系统状态 RPC 问题
方法未找到:如果 suix_getLatestSuiSystemState 或 sui_getLatestCheckpointSequenceNumber 返回方法未找到错误,该端点可能不支持该方法。请查阅你的提供商文档。一些提供商只暴露 Sui JSON-RPC 接口的一个子集。
负载过重:如果响应缓慢或超时,完整的验证者列表可能对你的客户端或网络来说太大。如果可用,尝试摘要方法,或增加超时时间并降低轮询频率。对于存活检测,请改用 sui_getLatestCheckpointSequenceNumber。
纪元混淆:如果纪元编号似乎与你的预期不一致,请确认你查询的是正确的网络(主网还是测试网)。同时检查节点是否处于安全模式或落后。纪元在边界处推进;如果你频繁轮询,可能会看到它在循环中途变化。在每个数据点记录纪元,以避免混合来自不同纪元的数据。
- 方法未找到:确认提供商对该方法的支持。
- 负载过重:使用摘要字段,或改用检查点序列进行存活检测。
- 纪元混淆:确认网络、检查安全模式,并在记录数据时一并记录纪元。
监控与对账的后续步骤
要构建稳健的监控设置,请将系统状态读取与检查点序列探针结合使用。使用 Sui 网络页面查找端点,并考虑使用 API 服务进行托管访问。有关定价和速率限制,请参阅 RPC 定价。
如需深入了解相关主题,请探索 OnFinality Learn 中心。关于 queryTransactionBlocks 游标分页的文章涵盖交易分页,而读取 Sui 代币余额和元数据则涵盖用户状态读取。关于对象版本控制,请参阅 Sui 对象版本与 Lamport 排序。
最后,将纪元跟踪集成到你的索引器或监控代理中。在每个数据点旁边记录纪元,并对纪元变化、安全模式或协议版本变化发出警报。这可以确保你的数据在委员会轮换和 Gas 价格更新期间保持可对账。
- 将系统状态读取与检查点序列探针结合,用于延迟检测。
- 在每个数据点记录纪元以便对账。
- 对纪元变化、安全模式和协议版本变化发出警报。