☰
Polkadot 网络类型全解:Validation/Collation 协议消息、通用类型与 Network Bridge 事件体系
2026/10/7 2:02:57 网站建设 项目流程
  • 区块链

【免费下载链接】polkadot

Polkadot Node Implementation

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

本文以 Polkadot 实现者指南(Implementers Guide)中的 Network Types 文档 为骨架,结合当前仓库的polkadot-node-network-protocol源码,系统讲解真正通过 P2P 网络传输的子系统消息类型、两大 peer-set 的线协议(Wire Protocol)封装、以及 Network Bridge 子系统向其他子系统广播的网络事件。读完本文,你将掌握View/ObservedRole等通用类型的设计语义、六大分发协议的 V1 消息变体、验证与收集两个 peer-set 的消息路由方式,以及NetworkBridgeEvent与 gossip 网格拓扑的完整交互模型。

一、为什么需要独立的网络消息类型

Polkadot 的平行链子系统(subsystem)之间通过 overseer 进行消息传递,但真正跨越节点边界、经 libp2p 网络传输的数据,必须被编码为专门的网络消息类型。这些类型与子系统内部使用的*Message类型是两套体系:网络类型承担**线格式(wire format)**职责,使用parity-scale-codec进行 SCALE 编码/解码,并在两端节点间传递。

从源码结构看,这套网络类型集中在 node/network/protocol/src/lib.rs 一个 crate 中,被命名为polkadot-node-network-protocol。所有分发类子系统(approval、availability、bitfield、statement 等)在向对端节点发送消息时,都必须把消息转换成对应的ValidationProtocol/CollationProtocol变体,再交给 Network Bridge 子系统统一收发。

另外,所有 gossip 类协议都遵循一条关键原则:以当前链头(chain heads)为数据依赖来消除 DoS。这意味着每个节点都需要持续维护"自己看到的链头"与"对端看到的链头",并把这些共享视图分发给各个子系统——这正是View类型和 Network Bridge 事件体系存在的意义。

二、通用类型(Universal Types)

网络层存在一批跨协议复用的基础类型,在 Network Types 文档 中以伪代码形式给出,其真实实现位于 node/network/protocol/src/lib.rs。

type RequestId = u64; type ProtocolVersion = u32; struct PeerId(...); // opaque, unique identifier of a peer. struct View { // Up to `N` (5?) chain heads. heads: Vec<Hash>, // The number of the finalized block. finalized_number: BlockNumber, } enum ObservedRole { Full, Light, }

2.1 View:对等节点的链视图快照

View是网络层最重要的共享状态之一,用于描述一个节点当前"看到了哪些链头、确认到了哪个最终化区块高度"。其实现要点(node/network/protocol/src/lib.rs):

  • heads: Vec<Hash>:有界的链头集合,注释明确要求保持有序(Invariant: Sorted),构造时通过View::new自动sort();
  • finalized_number: BlockNumber:该节点已知的最高最终化区块高度;
  • 文档中标注 "Up toN(5?)" 表示链头数量存在上限,源码并未硬编码具体数值,而是通过有界性约定约束 gossip 流量。

围绕View提供了一组集合运算辅助方法,是各分发子系统判断"是否需要对某对端发送某条消息"的核心工具:

方法语义
difference(&self, other)返回在self中存在但other中不存在的链头哈希
intersection(&self, other)返回两个视图共有的链头哈希
replace_difference(&mut self, new)用new替换自身,并产出新增的链头
contains(&hash)判断视图是否包含某链头
check_heads_eq(&self, other)忽略finalized_number,仅比较链头是否相等
with_finalized(number)构造一个不含链头、仅有最终化高度的视图

此外源码还定义了OurView包装类型(lib.rs):在View基础上为每个链头附带一个 jaeger 追踪 Span,用于分布式追踪各链头的处理耗时;OurView通过Deref透明暴露底层View,并实现了基于view == other的PartialEq。测试场景中可使用仓库提供的view!/our_view!宏快速构造视图(finalized_number默认为 0)。

2.2 ObservedRole:节点的观测角色

ObservedRole表示对端节点在网络中所扮演的角色。文档伪代码只列出Full与Light两个变体,而当前源码实现(lib.rs)实际包含三个:

pub enum ObservedRole { Light, // 轻节点 Full, // 全节点 Authority, // 自称权威节点(未认证) }

Authority变体对应验证人角色,但注释明确标注 "unauthenticated"——即该角色声明不经过认证,仅作为观测信息使用。该类型与sc_network::ObservedRole之间实现了双向From/Into转换,保证与 Substrate 网络层的角色体系无缝衔接。ObservedRole会在NetworkBridgeEvent::PeerConnected中随对端连接事件一并上报(详见第六节)。

2.3 其他通用类型

  • RequestId = u64:请求/响应式协议(如 Availability Recovery)中唯一标识一次请求的 ID,用于把响应匹配回发起方;
  • ProtocolVersion = u32:协议版本号,配合Versioned<V1, VStaging>包装类型支持线协议的版本协商(见第四节);
  • PeerId:对等节点的唯一不透明标识,直接复用sc_network::PeerId(lib.rs)。

三、V1 网络子系统消息类型

所有 V1 消息类型均定义在 node/network/protocol/src/lib.rs 的v1子模块中,均派生Encode/Decode,并通过#[codec(index = N)]为每个变体标注了稳定的 SCALE 编码索引——这意味着变体顺序在跨版本演进中必须保持兼容。

3.1 Approval Distribution V1:认证分配与批准投票

enum ApprovalDistributionV1Message { /// Assignments for candidates in recent, unfinalized blocks. /// /// The u32 is the claimed index of the candidate this assignment corresponds to. Assignments(Vec<(IndirectAssignmentCert, u32)>), /// Approvals for candidates in some recent, unfinalized block. Approvals(Vec<IndirectSignedApprovalVote>), }
  • Assignments:一批针对近期未最终化区块中候选(candidate)的认证分配证书。元组中的u32(源码中为CandidateIndex,见 lib.rs)是发送方声称的候选索引,但注释强调"实际校验分配时可能得到不同结果"——接收方必须重新验证IndirectAssignmentCert是否确实将验证人指派到该候选;
  • Approvals:一批已签名的批准投票。IndirectAssignmentCert与IndirectSignedApprovalVote定义在 node/primitives/src/approval.rs,采用"间接(Indirect)"形式,即证书/投票只携带紧凑的哈希引用,完整数据可通过后续请求/响应协议获取,从而压缩 gossip 带宽。

3.2 Availability Distribution V1:可用性分片分发

enum AvailabilityDistributionV1Message { /// An erasure chunk for a given candidate hash. Chunk(CandidateHash, ErasureChunk), }

可用性数据经 erasure-coding 纠删码切分成 N 个分片后,各验证人持有一片。Chunk消息把某个候选的一个ErasureChunk分发给对端,接收方(av-store 与 availability-recovery 配合)据此重建完整 PoV。该协议由 node/network/availability-distribution/src/lib.rs 对应的AvailabilityDistribution子系统处理。

3.3 Availability Recovery V1:可用性恢复请求/响应

enum AvailabilityRecoveryV1Message { RequestChunk(RequestId, CandidateHash, ValidatorIndex), Chunk(RequestId, Option<ErasureChunk>), RequestFullData(RequestId, CandidateHash), FullData(RequestId, Option<AvailableData>), }

这是典型的请求/响应式协议,通过RequestId把响应关联到请求:

  • RequestChunk:按(候选哈希, 验证人索引)请求某一片纠删分片;
  • Chunk:响应分片,Option为None表示请求方(requestee)不持有该分片;
  • RequestFullData:请求某个候选的完整可用数据;
  • FullData:响应完整数据,同样可能为None。

ErasureChunk与AvailableData是平行链可用性体系的核心数据对象,其恢复流程在 node/network/availability-recovery/src/lib.rs 中实现,仓库配套的 reconstruct 模糊测试 与 round_trip 模糊测试 覆盖了分片重建的正确性边界。

3.4 Bitfield Distribution V1:可用性位域分发

enum BitfieldDistributionV1Message { /// A signed availability bitfield for a given relay-parent hash. Bitfield(Hash, SignedAvailabilityBitfield), }

每个验证人对自己所在 backing 组的候选可用性生成位域,Bitfield(Hash, ...)把签名后的可用性位域广播出去。源码中第二个字段实际类型为UncheckedSignedAvailabilityBitfield(lib.rs),Unchecked前缀表示签名在分发前未逐一验证,接收方校验后才会纳入共识流程。

3.5 PoV Distribution V1:PoV 按需分发

enum PoVDistributionV1Message { /// Notification that we are awaiting the given PoVs (by hash) against a /// specific relay-parent hash. Awaiting(Hash, Vec<Hash>), /// Notification of an awaited PoV, in a given relay-parent context. /// (`relay_parent`, `pov_hash`, `pov`) SendPoV(Hash, Hash, PoV), }
  • Awaiting(relay_parent, pov_hashes):向对端声明"我在某个 relay-parent 下等待这些 PoV(以哈希标识)";
  • SendPoV(relay_parent, pov_hash, pov):应对方在收到Awaiting后回传实际的PoV数据。

该机制让 PoV 只在确有需求时传输,避免全量 gossip 大体积的验证数据。

3.6 Statement Distribution V1:语句分发

enum StatementDistributionV1Message { /// A signed full statement under a given relay-parent. Statement(Hash, SignedFullStatement) }

Statement(relay_parent_hash, signed_full_statement)广播某个 relay-parent 下已签名的完整语句(Seconded/Valid)。值得注意的源码差异:当前实现的v1::StatementDistributionMessage还额外包含LargeStatement(StatementMetadata)变体(lib.rs),用于携带大载荷语句(例如包含运行时升级的语句)——此时 gossip 只传StatementMetadata(含 relay_parent、candidate_hash、signed_by、signature),实际载荷通过请求/响应协议按需拉取,避免大消息污染 gossip 通道。StatementMetadata与get_fingerprint()/get_signature()等辅助方法共同支撑语句去重与签名校验。

3.7 Collator Protocol V1:收集人协议

enum CollatorProtocolV1Message { /// Declare the intent to advertise collations under a collator ID and `Para`, /// attaching a signature of the `PeerId` of the node using the given collator ID key. Declare(CollatorId, ParaId, CollatorSignature), /// Advertise a collation to a validator. Can only be sent once the peer has /// declared that they are a collator with given ID. AdvertiseCollation(Hash), /// A collation sent to a validator was seconded. CollationSeconded(SignedFullStatement), }

这是验证人—收集人双向交互的协议:

  • Declare(CollatorId, ParaId, CollatorSignature):收集人声明自己将在某个平行链ParaId下提供 collation。签名内容是对节点PeerId字节的签名,签名载荷由declare_signature_payload()生成——peer_id.to_bytes()后追加常量字节b"COLL"(lib.rs),以此证明该节点确实控制所声明的 collator 密钥;
  • AdvertiseCollation(Hash):收集人向已建立声明关系的验证人广播"我有新 collation",字段为 relay-parent 哈希(vstaging 版本扩展为relay_parent、candidate_hash、parent_head_data_hash三元组以支持异步 backing);
  • CollationSeconded:验证人告知收集人"你的 collation 已被 seconded",携带完整签名语句。

四、V1 线协议:两大 Peer-Set 的消息路由

网络类型最终被封装成两种**线协议(Wire Protocol)**枚举,分别对应 Polkadot 节点网络中的两个 peer-set(peer_set.rs 中的PeerSet::Validation与PeerSet::Collation):

enum ValidationProtocolV1 { ApprovalDistribution(ApprovalDistributionV1Message), AvailabilityDistribution(AvailabilityDistributionV1Message), AvailabilityRecovery(AvailabilityRecoveryV1Message), BitfieldDistribution(BitfieldDistributionV1Message), PoVDistribution(PoVDistributionV1Message), StatementDistribution(StatementDistributionV1Message), } enum CollationProtocolV1 { CollatorProtocol(CollatorProtocolV1Message), }
Peer-set承载的子系统消息协议名
Validation(验证集)Approval / Availability / Bitfield / PoV / Statement 分发ValidationVersion::V1与VStaging
Collation(收集集)Collator ProtocolCollationVersion::V1与VStaging

源码用Versioned<V1, VStaging>泛型包装每种消息(lib.rs),并提供预定义别名:

  • VersionedValidationProtocol/VersionedCollationProtocol:完整的版本化线协议;
  • ApprovalDistributionMessage、StatementDistributionMessage、BitfieldDistributionMessage、CollatorProtocolMessage:版本化后的单子系统消息类型。

通过impl_versioned_full_protocol_from!与impl_versioned_try_from!宏(lib.rs),各子系统消息可以便捷地在"版本化消息 ↔ 版本化线协议"之间转换,转换失败时返回WrongVariant错误类型。这一设计允许同一消息类型同时以 V1(稳定)与 VStaging(试验性)两种版本在网络中并存,由网络组件在连接建立时协商使用双方都支持的最高版本——这也是 peer_set.rs 中协议配置同时注册 V1/VStaging 两个版本、并由ProtocolVersion做版本协商的原因。

五、Network Bridge 事件:从网络到子系统的统一通道

线协议只解决"消息长什么样、走哪个 peer-set",而"对端连上了、断开了、视图变了、拓扑更新了"这类网络生命周期事件需要统一广播给各子系统。这就是 Network Bridge 子系统(Network Bridge 文档)的职责:它充当底层网络组件与子系统协议之间的桥梁,把网络事件转换为NetworkBridgeEvent<M>分发给注册的 Event Handler。

5.1 NetworkBridgeEvent 变体全景

enum NetworkBridgeEvent<M> { /// A peer with given ID is now connected. PeerConnected(PeerId, ObservedRole, ProtocolVersion, Option<HashSet<AuthorityDiscoveryId>>), /// A peer with given ID is now disconnected. PeerDisconnected(PeerId), /// Our neighbors in the new gossip topology. NewGossipTopology(NewGossipTopology), /// We received a message from the given peer. PeerMessage(PeerId, M), /// The given peer has updated its description of its view. PeerViewChange(PeerId, View), // guaranteed to come after peer connected event. /// We have posted the given view update to all connected peers. OurViewChange(View), }

各变体的语义与触发时机(结合 network-bridge.md):

变体内容触发时机
PeerConnected对端 ID、观测角色、协商协议版本、可选的权威发现 ID 集合对端在某个 peer-set 上建立连接(按 peer-set 与协议版本分发)
PeerDisconnected对端 ID对端断开连接
NewGossipTopology新的会话网格拓扑仅在 validation peer-set 上发布,用于会话切换
PeerMessage对端 ID + 协议消息收到对端发来的消息
PeerViewChange对端 ID + 新视图对端更新视图,注释保证"必然在连接事件之后到达"
OurViewChange本地最新视图本地视图更新已广播给所有已连接对端后

5.2 视图维护与 WireMessage 封装

Network Bridge 通过WireMessage<M>类型把"协议消息"与"视图更新"统一为一种线上消息(network-bridge.md):

enum WireMessage<M> { ProtocolMessage(M), ViewUpdate(View), }

并分别以ValidationProtocolV1与CollationProtocolV1实例化两次:

type ValidationV1Message = WireMessage<ValidationProtocolV1>; type CollationV1Message = WireMessage<CollationProtocolV1>;

Network Bridge 的主循环遵循以下规则:

  • ActiveLeavesUpdate(overseer 信号):根据activated/deactivated列表演进本地视图,向每个 peer-set 的已连接对端发送ViewUpdate,并向各 Event Handler 广播OurViewChange;只有完成主要区块链同步后才会发送真实视图,否则只发空视图;
  • BlockFinalized:更新View::finalized_number,视图广播推迟到下一次ActiveLeavesUpdate;
  • PeerConnected:下发PeerConnected事件,若已同步则同时下发PeerViewChange并回传本地视图;
  • ViewUpdate事件:校验新视图有效性,记录为该对端在该 peer-set 上的最新视图,并映射为PeerViewChange分发。

各分发子系统的 Event Handler 映射关系(见 network-bridge.md):

  • Validation peer-set:ApprovalDistributionV1Message→ApprovalDistributionMessage::NetworkBridgeUpdate;BitfieldDistributionV1Message→BitfieldDistributionMessage::NetworkBridgeUpdate;StatementDistributionV1Message→StatementDistributionMessage::NetworkBridgeUpdate;
  • Collation peer-set:CollatorProtocolV1Message→CollatorProtocolMessage::NetworkBridgeUpdate。

5.3 NewGossipTopology:网格拓扑的会话化广播

struct NewGossipTopology { /// The session index this topology corresponds to. session: SessionIndex, /// The topology itself. topology: SessionGridTopology, /// The local validator index, if any. local_index: Option<ValidatorIndex>, } struct SessionGridTopology { /// An array mapping validator indices to their indices in the /// shuffling itself. This has the same size as the number of validators /// in the session. shuffled_indices: Vec<usize>, /// The canonical shuffling of validators for the session. canonical_shuffling: Vec<TopologyPeerInfo>, } struct TopologyPeerInfo { /// The validator's known peer IDs. peer_ids: Vec<PeerId>, /// The index of the validator in the discovery keys of the corresponding /// `SessionInfo`. This can extend _beyond_ the set of active parachain validators. validator_index: ValidatorIndex, /// The authority discovery public key of the validator in the corresponding /// `SessionInfo`. discovery_id: AuthorityDiscoveryId, }
  • SessionGridTopology(grid_topology.rs):记录会话内验证人的权威洗牌(canonical shuffling)与洗牌索引映射(shuffled_indices),两者长度必须一致;
  • TopologyPeerInfo(grid_topology.rs):每个验证人的已知PeerId列表、在SessionInfodiscovery keys 中的索引(可能超出活跃验证人集合)、以及权威发现公钥;
  • NewGossipTopology还携带local_index: Option<ValidatorIndex>,标识本地验证人在拓扑中的位置(非验证人节点为None)。

网格拓扑是 Polkadot gossip 的"结构化随机"核心:SessionGridTopology::compute_grid_neighbors_for(v)基于洗牌索引在网格矩阵中计算某验证人的行/列邻居(grid_topology.rs),得到GridNeighbors(行邻居集合peers_x/validator_indices_x与列邻居集合peers_y/validator_indices_y)。gossip 消息在网格邻居间确定性传播,辅以随机传播补充:MIN_GOSSIP_PEERS = 25(lib.rs)作为随机采样的底限、DEFAULT_RANDOM_SAMPLE_RATE取该值、DEFAULT_RANDOM_CIRCULATION = 4(grid_topology.rs)作为随机传播目标数。

六、从文档到源码的对应关系速查

文档概念源码位置说明
View/ObservedRolenode/network/protocol/src/lib.rs含排序不变式、集合运算、OurView包装
Versioned版本化node/network/protocol/src/lib.rsV1/VStaging 双版本共存与协商
V1 消息变体lib.rsv1子模块#[codec(index)]保证编码稳定
两大 peer-setnode/network/protocol/src/peer_set.rsValidation/Collation,各注册 V1 与 VStaging
网格拓扑node/network/protocol/src/grid_topology.rscompute_grid_neighbors_for、采样常量
Network Bridge 语义roadmap/implementers-guide/src/node/utility/network-bridge.mdWireMessage、Event Handler 映射
认证/批准类型node/primitives/src/approval.rsIndirectAssignmentCert、IndirectSignedApprovalVote

七、小结

Polkadot 的网络层可以概括为三个层次:通用类型(View、ObservedRole、RequestId等)提供跨协议共享的状态模型;子系统消息类型(六个 V1 分发消息 + Collator Protocol)定义每种业务的线格式与语义;线协议与 Bridge 事件(ValidationProtocol/CollationProtocol与NetworkBridgeEvent)负责版本协商、peer-set 路由和生命周期事件分发。理解这三层,就能读懂任何 Polkadot 网络子系统的消息处理逻辑:子系统只关心NetworkBridgeUpdate变体中的网络消息与连接事件,而具体"发给谁、走哪条线、按哪个版本编码"全部由 Network Bridge 与协议层透明完成。

本文所引用的 Network Types 文档 位于实现者指南的 types 章节,与 Network Bridge 文档、Overseer 协议文档 相互呼应,建议结合阅读以形成完整图景;消息的实际编解码与转换逻辑则以 node/network/protocol 目录下的源码为准。

  • 区块链

【免费下载链接】polkadot

Polkadot Node Implementation

项目地址:https://gitcode.com/gh_mirrors/po/polkadot
点击查看免费下载
上一篇:为什么选择jeffding/opt-350m-instruct-openmind?350M参数模型的高效能优势深度测评
下一篇:Laravel MySQL Spatial高级查询指南:距离计算、空间关系与性能优化

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

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

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

立即咨询