如何在Substrate平行链Pallet中获取所连接中继链的区块号
Cumulus平行链Pallet获取中继链区块号实现方案
Cumulus平行链的共识层已经内置了经过验证的中继链状态同步逻辑,不需要额外引入第三方组件或跨链调用,直接通过核心的平行链系统Pallet就能拿到可信的中继链区块号,具体实现如下:
前置依赖确认
- 首先确认你的平行链Runtime已经标准集成
cumulus_pallet_parachain_system,这是所有Cumulus平行链的必装核心Pallet,默认会维护经过共识校验的中继链状态数据,不需要额外新增依赖。 - 注意:不要尝试在Pallet内直接通过RPC请求中继链节点拿区块号,这类链下获取的数据没有经过平行链全网共识验证,直接使用会导致链上逻辑出现共识分叉、数据伪造等严重安全问题。
具体实现步骤
- 首先在你自定义Pallet的Config配置trait中,添加对平行链系统Pallet的类型约束:
pub trait Config: frame_system::Config { // 绑定Cumulus平行链系统Pallet的配置类型 type ParachainSystem: cumulus_pallet_parachain_system::Config; }
- 在Pallet的业务逻辑(可调用extrinsic、
on_initialize/on_finalize等生命周期钩子)中,根据你使用的Cumulus版本选择对应方法获取即可:
- 新版本Cumulus(对应Polkadot 1.0+ 稳定版本)直接调用状态提供者接口:
// 获取经过共识验证的最新中继链最终确认区块号 let relay_block_num = <<T as Config>::ParachainSystem as cumulus_pallet_parachain_system::Config>::RelayChainStateProvider::current_relay_chain_block_number();
- 旧版本Cumulus(对应Polkadot 0.9.x 系列版本)通过持久化验证数据获取:
use cumulus_primitives_core::PersistedValidationData; // 平行链区块执行时必然附带验证通过的中继链验证数据,该取值在共识规则下必然存在 let validation_data: PersistedValidationData = cumulus_pallet_parachain_system::Pallet::<T>::validation_data() .expect("验证数据随平行链区块共识同步,必然存在"); let relay_block_num = validation_data.relay_parent_number;
注意事项
- 上述方法拿到的中继链区块号是为当前平行链区块提供背书的中继父区块高度,是经过全网共识验证的可信值。因为平行链和中继链出块存在同步延迟,这个值会比中继链实时最新区块号晚1-2个中继块(约6-12秒),属于共识机制设计下的正常现象。
- 这个区块号和平行链本地区块号没有固定的线性映射关系,如果业务需要严格的时间锚定,直接使用这个可信的中继区块号即可,不要尝试自行计算两个链的区块高度映射。
- 如果业务需要获取中继链上特定合约、特定Pallet的最新状态,不能直接在本地读取,需要通过XCMP跨链消息传递从中继链对应模块获取经过共识证明的状态数据。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

