☰
Polkadot Validators 运行时 API 详解:验证者集合的查询语义与实现原理
2026/10/7 2:05:34 网站建设 项目流程
  • 区块链

【免费下载链接】polkadot

Polkadot Node Implementation

项目地址:https://gitcode.com/gh_mirrors/po/polkadot
点击查看免费下载

导读

validators是 Polkadot 中继链ParachainHost运行时 API 家族中最基础、使用频率最高的一员:它从指定区块的状态中取出该区块之后一个区块(child block)负责平行链背书(backing)的验证者集合,并以Vec<ValidatorId>的形式返回给节点侧(Node-side)代码。本文以 implementers-guide 中 validators.md 为核心,结合仓库源码逐层拆解其 API 定义、类型系统、状态来源与真实调用链,帮助读者理解"查询某一区块的验证者集合"这条链路在 Polkadot 中的完整实现。

一、API 定义与核心语义

1.1 接口签名

文档给出的接口签名如下:

fn validators(at: Block) -> Vec<ValidatorId>;

对应到当前仓库的稳定实现(primitives最新版本 v5),该接口被声明在ParachainHosttrait 中,签名略有演进——at参数不再显式传入,而是由运行时 API 的调用约定(基于at区块状态执行)隐式提供:

/// Get the current validators. fn validators() -> Vec<ValidatorId>;

见 primitives/src/runtime_api.rs。整个 trait 通过sp_api::decl_runtime_apis!宏声明,并标注#[api_version(5)],说明validators属于v5 稳定版本的运行时 API。

1.2 返回值的语义:ValidatorId

  • 返回值类型为Vec<ValidatorId>,即验证者身份公钥的列表;
  • ValidatorId在仓库中定义于 primitives/src/v5/mod.rs:
mod validator_app { use application_crypto::{app_crypto, sr25519}; app_crypto!(sr25519, super::PARACHAIN_KEY_TYPE_ID); } pub type ValidatorId = validator_app::Public;

也就是说,ValidatorId是基于sr25519 签名算法、以PARACHAIN_KEY_TYPE_ID作为密钥类型 ID 的 application-crypto 公钥。与之配套的还有ValidatorPair(私钥/密钥对)与ValidatorSignature(签名)类型,共同构成平行链共识中的背书签名密钥体系(区别于 BABE 出块密钥、GRANDPA 最终性密钥等其他会话密钥)。

1.3 核心语义:永远面向 "child block"

文档强调了一个极易被忽略的细节:

This validator set is always the one responsible for backing parachains in the child of the provided block.

即在查询at区块的状态时,返回的验证者集合是为at的子块(child block)进行平行链背书而生效的那一批验证者。之所以存在这种"面向下一个区块"的语义,是因为节点侧在构建新块时,需要基于父块(relay parent)的稳定状态提前得知自己应当与哪些验证者协作:背书、可用性分发、语句分发等子系统都必须围绕即将产生的下一个区块组织网络连接与消息传递。这一点与同一家族中的validator_groupsAPI 完全一致——后者也明确"假定查询结果对应所查询区块的 child block",见 validator-groups.md。

二、从 API 声明到具体 Runtime:实现链路

validators的运行时实现遵循 "trait 声明 → 各 Runtime 实现 → 共享的 runtime-api-impl 模块" 的清晰分层。

2.1 各链 Runtime 的入口实现

Polkadot、Kusama、Westend、Rococo以及测试运行时都在各自的impl ParachainHost块中实现了validators,且实现逻辑完全一致——委托给共享的parachains_runtime_api_impl::validators::<Runtime>():

impl primitives::runtime_api::ParachainHost<Block, Hash, BlockNumber> for Runtime { fn validators() -> Vec<ValidatorId> { parachains_runtime_api_impl::validators::<Runtime>() } // ... }

对应实现文件包括:

  • runtime/polkadot/src/lib.rs
  • runtime/kusama/src/lib.rs
  • runtime/westend/src/lib.rs
  • runtime/rococo/src/lib.rs
  • runtime/test-runtime/src/lib.rs

2.2 共享实现:读 Shared 模块的状态

真正的实现位于 runtime/parachains/src/runtime_api_impl/v5.rs:

/// Implementation for the `validators` function of the runtime API. pub fn validators<T: initializer::Config>() -> Vec<ValidatorId> { <shared::Pallet<T>>::active_validator_keys() }

这里直接读取的是Shared(Parachain Shared)模块的存储项ActiveValidatorKeys。该存储项在 runtime/parachains/src/shared.rs 中定义为:

/// The parachain attestation keys of the validators actively participating in parachain /// consensus. This should be the same length as `ActiveValidatorIndices`. #[pallet::storage] #[pallet::getter(fn active_validator_keys)] pub(super) type ActiveValidatorKeys<T: Config> = StorageValue<_, Vec<ValidatorId>, ValueQuery>;

由此可以梳理出validatorsAPI 的数据流:

  1. 会话变化时:Shared 模块从 Initializer 模块接收当前 Session Index 与更广泛的验证者集合(详见 runtime/shared.md);
  2. Shared 模块按照链的随机种子先洗牌(shuffle)、再截断(truncate),得出参与平行链共识的活跃验证者子集,写入ActiveValidatorKeys与ActiveValidatorIndices;
  3. 查询时:validatorsAPI 直接返回ActiveValidatorKeys的当前值。

2.3 会话机制对返回结果的影响

验证者集合是随**会话(session)**周期性变化的。Runtime 文档 runtime/README.md 明确指出:Parachain Host 运行在一组会变化的验证者之上,时间被划分为周期性会话,且会话是"缓冲一阶"的——下一会话(n+1)的验证者在会话 n-1 结束时即已确定。因此:

  • 在同一会话内,不同区块上查询validators得到的结果基本稳定;
  • 跨会话查询,结果会随会话切换而更新;
  • 由于 API 面向 child block,会话边界附近查询时需注意返回值代表的是"下一个区块生效的集合"。

三、验证者集合与兄弟 API 的关系

validators是理解其余运行时 API 的索引基础。它返回的验证者列表是"有序的"——列表中的位置即ValidatorIndex。这一约定贯穿整个平行链协议:

兄弟 API与validators的关系
validator_groups将验证者按ValidatorIndex分组,返回(Vec<Vec<ValidatorIndex>>, GroupRotationInfo),分组中的成员以validators返回列表中的下标引用(见 validator-groups.md)
SessionInfo运行时类型 SessionInfo 中的validators: IndexedVec<ValidatorIndex, ValidatorId>与该 API 语义一致,且受配置max_validators限制,可能少于当前会话的全部 authorities(见 runtime/session_info.md)
availability_cores/persisted_validation_data等均以验证者分配与背书为前提展开计算

从实现角度看,validator_groups与validators在 v5.rs 中是相邻实现:前者从scheduler模块读取分组、并用frame_system的当前区块号加一(block_number() + One::one())计算组轮换信息,再次印证了"面向 child block"的约定。

四、节点侧消费场景与测试验证

4.1 节点侧如何使用

节点侧通过运行时 API 提取状态信息(runtime-api/README.md 指出 Runtime API 是节点侧代码从运行时状态中提取信息的通道)。验证者集合的具体消费方包括:

  • Candidate Backing 子系统:校验来自验证者的语句签名是否来自当前集合内的合法验证者;
  • Statement / Bitfield Distribution 子系统:按验证者集合确定网络上的对等节点(Peer),构建分发拓扑;
  • Collator Protocol:collator 节点向"当前组"的验证者请求背书;
  • Approval 与 Dispute 子系统:基于ValidatorId ↔ ValidatorIndex的对应关系验证批准投票、争议投票的签名归属(如 types/approval.md 所述,approval 投票必须能以会话对应ValidatorIndex的ValidatorId验证)。

节点侧的一个典型用法模式是:以某 relay-parent 的 hash 调用validators获得集合,再配合validator_groups获得分组与轮换信息,从而确定"当前核心上应当与哪些验证者通信"。

4.2 测试中的体现

运行时测试环境提供了MockValidatorSet(runtime/parachains/src/mock.rs),它实现ValidatorSettrait,其中的validators()在单测中返回空集合。这说明validators背后依赖的验证者集合由会话/staking 层供给,测试时通过 mock 隔离,从而让平行链各 pallet 的单测可以独立验证其逻辑。

五、小结与阅读延伸

validators虽然只返回一行Vec<ValidatorId>,却是 Polkadot 平行链共识体系中"身份与索引"的源头:它定义了当前生效的背书验证者集合,是分组、分配、背书验证、可用性保证与争议处理的共同前提。其实现链路可总结为:

ParachainHost::validators (trait 声明) ↓ 各 Runtime impl parachains_runtime_api_impl::validators::<T> (runtime/parachains/src/runtime_api_impl/v5.rs) ↓ 读取存储 shared::Pallet<T>::active_validator_keys() (runtime/parachains/src/shared.rs, ActiveValidatorKeys) ↑ 由会话机制洗牌 + 截断产生

建议按以下顺序继续阅读本仓库的相关文档与代码:

  • 家族 API 总览:runtime-api/README.md
  • 兄弟 API:validator-groups.md、session-index.md
  • 运行时模块:runtime/shared.md、runtime/session_info.md、runtime/initializer.md
  • 类型定义:primitives/src/v5/mod.rs、API trait:primitives/src/runtime_api.rs
  • 共享实现:runtime/parachains/src/runtime_api_impl/v5.rs、存储定义:runtime/parachains/src/shared.rs
  • 区块链

【免费下载链接】polkadot

Polkadot Node Implementation

项目地址:https://gitcode.com/gh_mirrors/po/polkadot
点击查看免费下载
上一篇:终极指南:如何通过Falco与Darktrace集成构建AI驱动的云原生安全防护体系
下一篇:Ascend C L1 3D边界设置

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询