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

通过 RPC 读取 Bittensor 质押状态:委托、Alpha 质押与池状态

了解如何从 Subtensor 节点正确读取 Bittensor 质押与委托状态,包括 alpha 质押、池储备以及热键关系。

TL;DR

要正确读取 Bittensor 委托人的持仓,必须理解质押不是一个单一余额,而是一个向量:根网络 TAO 质押、每个子网的 alpha 质押、质押所委托到的热键,以及决定 alpha 兑换 TAO 汇率的子网池储备。本指南讲解 Subtensor 存储读取路径、如何根据运行时元数据解析存储键,以及如何从池储备计算隐含 alpha 价格。文中提供一个使用官方 Subtensor 接口的可运行 Python 示例、一份故障排查清单,以及一张供读者测量自己端点行为的结果表。所有经济参数均为文档记载值,必须在链上确认,因为子网代币经济模型已随运行时升级发生变化。

为什么单一质押数字会误导:Bittensor 质押的向量模型

在 Bittensor 中,委托人的持仓不是一个标量余额,而是一个向量:以 TAO 计价的根网络质押、按子网持有的 alpha 质押、质押所委托到的热键(验证者),以及决定 alpha 持仓当前价值多少 TAO 的子网池状态(TAO 储备与 alpha 储备)。把“我的质押”当作一个数字,会导致仪表盘、验证者工具和审计脚本产生错误结果。

委托是委托给某个热键,而热键是验证者冷热键对的一部分。同一个冷键可以在多个子网和多个热键上持有质押。要报告用户的真实持仓,必须分别读取每一条质押记录,并对每个子网的池应用正确的换算。

这条读取路径与读取元图权重和排放不同,后者跟踪的是奖励流而非质押与持仓状态。如需深入了解奖励流,请参阅读取 Bittensor 元图状态、权重与排放

  • 根网络质押:委托给根网络(netuid 0)的 TAO。
  • Alpha 质押:按子网持有的子网专属代币,不能与 TAO 互换。
  • 热键:质押所委托到的验证者身份;一个冷键可以委托给多个热键。
  • 池储备:每个子网都有一个 TAO 储备和一个 alpha 储备,决定 alpha 兑换 TAO 的汇率。

Subtensor 存储布局:质押状态存放的位置

质押状态存放在 Substrate 存储中,通常位于以冷键/热键和子网为键的映射中。具体的 pallet 和存储项名称由你所检查区块的运行时元数据定义。你使用由当前元数据推导出的存储键,通过 state_getStorage 在特定区块哈希处读取该状态。

或者,你可以使用 polkadot.js API 或 Python Subtensor 接口,它们会替你处理键推导和 SCALE 解码。对于大多数用例,推荐使用这些库,因为它们抽象掉了底层存储键的构造与解码。

池状态(TAO 储备和 alpha 储备)也存放在存储中。alpha 兑换 TAO 必须根据两个储备计算,而不能假设。换算公式在 Bittensor 质押与池文档中有记载,但当前参数和池机制必须在链上确认,因为子网代币经济模型已随运行时升级发生变化。Bittensor 官方文档涵盖质押与池机制,而 Subtensor 节点与质押运行时参考是运行时实现的权威来源。

  • 使用 state_getRuntimeVersion 或所检查区块处的元数据,了解适用的存储布局和 pallet 名称。
  • 运行时升级可能会重命名或重构存储项,因此硬编码的键可能静默解码为空。
  • 如果需要可复现的结果,请始终在特定区块哈希处读取,而不是“latest”。

根据运行时元数据解析存储键

在读取任何存储之前,先获取你要查询区块的运行时元数据。元数据描述了所有 pallet、存储项及其键类型。你可以用 state_getMetadata 或通过 polkadot.js API 获取它。关于读取运行时元数据的详细指南,请参阅使用 state_getMetadata 读取运行时元数据

拿到元数据后,推导 stake-info 映射的存储键。该键通常是冷键、热键和 netuid 组成的元组,按 SCALE 编解码器编码。Python Subtensor 接口提供了构造这些键并解码结果的辅助函数。

如果你使用原始 JSON-RPC,则必须手动编码键。这容易出错,除非你在构建自定义客户端,否则不推荐。官方 Substrate JSON-RPC 规范和 SCALE 编解码器文档是此编码的权威一手资料。Subtensor 节点与质押运行时参考记录了运行时存储项及其键类型。

  • 在目标区块哈希处获取元数据以确保一致性。
  • 使用 Subtensor 接口或 polkadot.js 以避免手动 SCALE 编码。
  • 查询前确认存储项存在于元数据中;缺失的项表明运行时发生了变化。

可运行的 Python 示例:读取质押、池储备与委托

以下 Python 示例使用官方 Subtensor 接口连接到 Bittensor 端点,解码元数据,读取某个冷键在根网络和一个指定子网上的质押,读取子网池储备,计算隐含 alpha 价格,并读取委托关系以识别热键。

此示例假设你已安装 bittensor Python 包并能访问 Subtensor RPC 端点。请将端点 URL 和冷键/热键值替换为你自己的。输出形状是一个字典,包含根网络质押、子网质押、池储备、隐含 alpha 价格以及与委托关联的热键。Bittensor 官方文档和 Subtensor 节点与质押运行时参考描述了此处使用的质押与池接口。

import bittensor as bt

# Connect to a Subtensor endpoint
subtensor = bt.subtensor(network='finney')

# Define the coldkey and hotkey to inspect
coldkey_ss58 = '5F...'  # replace with actual coldkey
hotkey_ss58 = '5G...'   # replace with actual hotkey
netuid = 1  # example subnet

# Read stake for the coldkey on root (netuid 0) and the specified subnet
stake_root = subtensor.get_stake(coldkey_ss58, hotkey_ss58, netuid=0)
stake_subnet = subtensor.get_stake(coldkey_ss58, hotkey_ss58, netuid=netuid)

# Read pool reserves for the subnet
pool = subtensor.get_subnet_pool(netuid)
tao_reserve = pool.tao_reserve
alpha_reserve = pool.alpha_reserve

# Compute implied alpha price in TAO
implied_alpha_price = tao_reserve / alpha_reserve if alpha_reserve else 0

# Read delegation relationship (hotkey associated with the coldkey's stake)
delegation = subtensor.get_delegation(coldkey_ss58, netuid)

print({
    'root_stake_tao': stake_root,
    'subnet_stake_alpha': stake_subnet,
    'tao_reserve': tao_reserve,
    'alpha_reserve': alpha_reserve,
    'implied_alpha_price_tao': implied_alpha_price,
    'delegated_hotkey': delegation.hotkey if delegation else None
})

独立验证 Alpha 兑换 TAO 的换算

从池储备计算出的隐含 alpha 价格,应与 Subtensor 接口在报告 TAO 计价质押时使用的换算一致。要验证,可将脚本输出与第二个来源(如区块浏览器或另一个 RPC 端点)进行比较。或者,使用文档记载的公式从储备重新推导换算,并检查是否一致。Bittensor 官方文档记载了池换算公式。

如果数字出现偏差,请检查你是否在同一区块高度读取储备和质押。在“latest”读取质押、在历史区块读取储备,会产生不一致的结果。在一次验证中,始终为所有读取固定同一个区块哈希。

  • 将你计算出的 alpha 价格与 Subtensor 接口的质押转 TAO 换算返回值进行比较。
  • 用第二个 RPC 端点或显示池储备的区块浏览器交叉核对。
  • 确保所有读取使用相同的区块哈希,以避免时间不一致。

读取 Bittensor 质押状态时的常见失败

若干陷阱可能导致你的仪表盘或审计脚本报告错误的持仓。最常见的是把 alpha 当作与 TAO 1:1。Alpha 代币是子网专属的,其 TAO 价值由池储备决定。另一个常见错误是在“latest”读取质押,然后将其与历史区块对照报告,从而混合了不同时间的状态。

使用从旧运行时复制的存储键可能会静默解码为空,因为运行时升级可能重命名或重构存储项。把一个冷键在各子网的质押汇总成一个数字也具有误导性,因为每个子网都有自己的 alpha 代币和换算率。把验证者自身质押与委托质押混淆是另一个常见错误:验证者可能有自己的质押,而委托人的质押是分开的。

最后,用逐冷键循环猛击公共端点可能触发速率限制或超时。尽可能使用批量读取或范围读取。关于超时错误的更多内容,请参阅 Subtensor 上的 Bittensor RPC 超时错误

  • 不要假设 alpha 等于 TAO;始终应用池换算。
  • 在单份报告中为所有读取固定一个区块哈希。
  • 根据当前运行时元数据验证存储键。
  • 按子网和热键分别报告质押,而不是一个总和。
  • 区分验证者自身质押与委托质押。
  • 使用批量或范围读取以避免速率限制。

结果表:测量你的端点行为

使用下表记录你自己端点观察到的行为。通过针对你的端点运行 Python 示例或你自己的脚本来填写这些值。这将帮助你了解延迟、一致性以及任何速率限制特征。

该表有意留空,供你填写。不要依赖通用基准;测量你自己的设置。

  • 端点 URL:[你的端点]
  • 使用的区块哈希:[哈希]
  • 根网络质押(TAO):[值]
  • 子网质押(alpha):[值]
  • TAO 储备:[值]
  • Alpha 储备:[值]
  • 隐含 alpha 价格(TAO):[值]
  • 委托热键:[热键]
  • 响应时间(毫秒):[值]
  • 任何错误或速率限制:[备注]

质押状态读取的故障排查清单

如果你的读取失败或返回意外值,请逐项检查此清单。首先确认你的端点已同步,并且你查询的区块存在。然后验证该区块处的运行时元数据包含你尝试读取的存储项。

检查你的存储键是否针对当前运行时正确编码。如果你使用库,请确保它已更新到最新运行时。如果你使用原始 RPC,请仔细检查键的 SCALE 编码。Subtensor 节点与质押运行时参考是运行时存储项及其编码的权威来源。

最后,确保你没有混合区块高度。单份报告的所有读取都应使用相同的区块哈希。如果遇到超时,考虑使用专用端点或降低请求频率。关于 RPC 访问选项,请参阅 Bittensor RPC 访问与端点(RPC Assistant)

  • 端点是否已同步,区块哈希是否有效?
  • 该区块处的元数据是否包含预期的存储项?
  • 存储键是否针对当前运行时正确编码?
  • 所有读取是否都固定到同一个区块哈希?
  • 你是否触发了速率限制或超时?
  • 你的库版本是否与运行时兼容?

局限与假设:不断变化的子网经济模型

子网代币经济模型已随运行时升级发生变化,并可能继续演变。本文描述的公式和存储布局基于撰写时的文档记载行为,但你必须确认链上的当前参数。不要硬编码经济参数;始终从运行时读取它们。Bittensor 官方文档和 Subtensor 节点与质押运行时参考是当前参数和运行时行为的主要来源。

Python 示例假设 Subtensor 接口提供质押和池读取的辅助方法。如果这些方法发生变化,你可能需要调整代码。该示例还假设只有一个子网;对于多个子网,请遍历 netuid 并应用相同逻辑。

本指南不涵盖质押交易(add_stake、remove_stake)或委托管理。它只关注读取路径。关于节点访问和网络详情,请参阅 Finney 上的 Bittensor RPC 与节点访问Bittensor Finney 网络

  • 经济参数是文档记载值;请在链上确认。
  • 运行时升级可能改变存储布局和 pallet 名称。
  • 读取路径与交易构造是分开的。
  • 尽可能始终对照第二个来源进行验证。

后续步骤:构建可靠的质押仪表盘与审计

要构建可靠的质押仪表盘或审计脚本,首先使用 Subtensor 接口或 polkadot.js 来抽象存储键推导。为每份报告固定一个区块哈希,按子网和热键读取质押,并从池储备计算 alpha 兑换 TAO。用第二个端点或浏览器交叉核对结果。

对于生产用途,考虑使用专用 RPC 端点以避免速率限制并确保性能一致。探索 RPC 定价API 服务以了解选项。更多指南请访问 OnFinality Learn 中心

请记住,Bittensor 的质押状态是一个向量,而不是标量。正确报告它需要理解池机制和委托关系。借助本指南中的方法,你可以避开常见陷阱,产出准确、可验证的结果。

  • 使用库进行键推导和解码。
  • 固定区块哈希以确保可复现性。
  • 从储备计算换算,而不是假设。
  • 用独立来源交叉验证。
  • 生产环境考虑使用专用 RPC 端点。

永远不用担心基础设施

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

开始