ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Polkadot 争议解决协议(Disputes)全解析:从链上罚没到节点参与机制

Polkadot 争议解决协议(Disputes)全解析:从链上罚没到节点参与机制 区块链【免费下载链接】polkadotPolkadot Node Implementation项目地址https://gitcode.com/gh_mirrors/po/polkadot点击查看免费下载本文聚焦 Polkadot 中继链的争议解决Disputes协议这是与 Approval Checking审批检查并列的第二道防无效区块进入最终化链的防线。文章以 implementers-guide 中的 Disputes 协议说明 为骨架结合争议流程Disputes Flows、争议协调器Dispute Coordinator、争议分发Dispute Distribution 等设计文档以及node/core/dispute-coordinator、node/network/dispute-distribution等子系统源码系统讲解争议的动机、发起、参与、结论、惩罚机制与 DoS 防护设计。读完本文你将掌握 Polkadot 争议协议的完整工作流理解 local/remote 争议的区别、⅔ 绝对多数的结论规则、垃圾争议spam防护的工程手段以及争议如何在所有链分支间“移植”以保证作恶者必被罚没。一、动机与背景为什么需要独立于分叉的争议协议在 Polkadot 的安全性模型中进入最终化finalized中继链的所有平行链区块都必须是有效的这个约束不适用于“仅被 backing担保但未被包含included”的区块。系统用两大组件共同保证这一性质审批检查Approval Checking详见 审批协议 及其子系统 Approval Voting。该协议能够在“尝试次数有限”的前提下证明无效区块无法进入最终化链。争议解决Disputes即本文主题确保每一次把坏东西包含进链的尝试都会被抓住并惩罚作恶验证人。争议与 backing、approval 的本质区别在于backing 和 approval 都作用于特定分叉而争议独立于特定分叉。这一区别至关重要当一条替代分叉可能不含当前已批准候选区块被最终化时approval 投票会停止——这对 approval 而言完全合理因为它的唯一目的是保证无效区块不被最终化但对争议而言即使“危险”已经过去、攻击者没能让无效区块获批我们仍然要对他们进行罚没slash。否则攻击者等于获得了一次“免费尝试”。这违背了 Polkadot 安全模型的基本假设——该模型建立在“无效区块被最终化的概率极低攻击者在尝试足够多次之前就会破产”gamblers ruin赌徒破产性质之上。关注的攻击场景协议明确要识别并威慑的攻击场景为场景一核心中继链某一分支上被包含的平行链区块是坏的场景二附加中继链某一分支上被 backing 的平行链区块是坏的场景三附加在某条分支上被 seconded第二签字但从未被 backing 的区块是坏的。对后两个场景的惩罚不会影响安全保证却会引入大量技术挑战详见 Dispute Coordinator 文档 中 “No Disputes for Non Included Candidates” 一节。因此协议主动搁置punt后两类争议以换取协议简化——只惩罚第一个场景。数据可用性要求如协议总览所述检查一个平行链区块需要三份数据平行链校验代码Validation Code链上可用、提前发布保证中继链任何两条分支对某平行链的校验代码视图一致AvailableData可用数据CandidateReceipt候选收据。注意只有场景一区块已在某分支被包含才保证数据必然可用。因此争议流程应从可用性availability过程开始确保拿到AvailableData。若数据已可用该过程会迅速结束若不可用则必须由争议发起者提供。链上与链下双组件、Local 与 Remote 争议争议同时有链上和链下两部分罚没与惩罚在链上处理因此争议双方的验证人投票必须上链一条分支上的争议应移植transpose到中继链的所有其他活跃分支。“在所有历史中发生罚没”对威慑至关重要——攻击者不能因为网络已转向另一条未发生攻击的分支而携款逃脱。由此引入local本地与 remote远程争议的区分——相对于某条特定分支而言Local 争议处理场景一即平行链区块在“我们正查看的这条分支”上被包含。此时这条链自该区块被 backing 的位置起已腐化必须被丢弃Remote 争议除此之外的所有争议。在链上处理一个“未在当前分叉中被包含”的区块时无法区分三种攻击场景可能在别处被包含、被 backing、或从未被 backing链上处理逻辑完全相同。二、争议发起Initiation争议由任何发现自己对区块有效性的判断与另一份已发布声明相悖的验证人发起。由于中继链收集的所有声明backing、approval都隐含“有效”含义争议只可能由“认为区块是坏的”的节点发起。发起过程始于链下验证人签署一条声明自己质疑该平行链区块有效性的消息并通过链下通道通知所有其他验证人自己已知的与该区块相关的全部声明可能是 backing 声明或审批检查声明。值得注意的是没有专门的“发起争议”消息类型——发起与参与争议、投反对票使用的是同一条消息。因此共识不要求“谁发起了争议”只要求“存在一个进行中的争议”。在实际中发起者通常是该区块的backer担保者或 approval checker审批检查者若执行结果被判定无效验证人按上述方式发起争议若争议发生在backing 阶段发起者必须让数据对其他验证人可用若争议发生在approval checking 阶段数据已经可用。关于 backing 阶段争议的 DoS 风险当数据尚未在所有验证人间可用时攻击者可能对少数正在检查区块的验证人发起 DoS阻止他们把数据分发给参与争议的其他验证人。但这种攻击只可能在“包含前”pre-inclusion发生危害有限不构成安全关键问题。协议对此的假设是攻击者只能限制验证人在有限时间内无法发出消息存在一个侧信道中继链的治理机制可以通过手动在链上提供完整 PoVProof of Validity有效性证明和候选收据来触发争议。三、争议参与Dispute Participation一旦得知争议存在所有验证人都有义务参与。具体职责包括流通所有已知的关于该候选区块的声明——backing 声明、approval checking 声明、争议声明若我们已经就该候选区块发出过任何类型的声明则不再继续下载AvailableData优先从其他争议参与者或 backing 验证人处获取其次通过 erasure-coding纠删码恢复 从所有验证人处获取提取校验代码从任意最近的recent中继链区块提取。代码保证始终在链上可用因此无需下载特定分叉执行区块校验在校验代码下、用AvailableData执行该区块检查所有输出是否正确包括CandidateReceipt中的erasure-root发出争议参与声明表明候选区块的有效性判断。结论条件当任意一方达到⅔ 绝对多数supermajority时争议结束。链上组件的行为争议的链上组件具有以下行为可被任意两条冲突的投票触发启动同样等待任意一方达到 ⅔ 绝对多数跟踪哪些平行链区块已被争议过同一区块在任意特定分支上只能被争议一次跟踪当前分支上已被包含的区块当某平行链的争议被发起后该平行链的包含inclusion被暂停直到争议结束。中继链区块作者应通过**内在函数inherents**为所有链尚未知晓的争议启动链上组件并同时把所有相关声明提交给链上组件。验证人获取争议声明的两条途径**通过 gossip闲聊协议**从其他验证人处接收从已导入的中继链区块中抓取scraping——这一途径同样用于跟踪 backing 等其它类型声明。验证人为向链提供声明以及参与争议无论哪一方获得奖励而争议的失败方将被罚没。四、争议结论Dispute Conclusion争议大致在一方达到 ⅔ 绝对多数时结束也可能永远不结束——仅当大多数验证人因某种原因无法投票时才会发生链上争议即使在结论后也会保持开放一段时间以接收新投票迟到的投票在争议已达到 ⅔ 绝对多数之后才到达也必须获得奖励只是金额更少。在 disputes-flow.md 中这些规则以 if-then 条件形式被精确定义并包含了几张状态机图。以下关键规则直接来自该文档投票资格集合在 backing 时刻负有职责的验证人集合加上 backing 验证人的 backing 投票验证人收到初始争议消息包含至少两条对立投票的声明集合、且本地无法重建 PoV 或代码时必须向对等节点请求数据争议可用性消息必须包含代码、持久化验证数据与有效性证明PoV只向已经投票的对等节点查询争议可用性数据被查询的对等节点必须随机挑选验证人必须保留代码、持久化验证数据和 PoV直到包含争议决议的区块被最终化后再额外保留 24 小时争议可用性 gossip 必须持续到争议决议之后直到“决议后超时”等同于接受额外迟到投票的超时时间到期远程争议定义为与“不在本地验证人活跃头部active heads中的链”相关的争议所有收到的投票必须持久化持久化投票保留N个 session并逐 session 清理投票必须可按签名公钥标识的验证人查询也必须可按session index该 session 内的验证人 index查询若某区块同时存在反对票与赞成票则检测到争议一旦检测到争议必须 gossip 该区块当前所有可用投票收到争议投票后验证人必须用自己的验证结果投票——用 backing 时刻的代码对 PoV 进行校验来决定若验证人本人是 backer则跳过重复校验与投票赞成或反对票数含 backing 投票达到⅔ 绝对多数时必须在链上记录结论并对失败方与未投票者no-shows进行相应罚没若争议决议判定区块无效必须将该区块列入黑名单避免在存在其他可用链时重新同步或继续在其上构建细节见 GRANDPA 分叉选择规则争议在决议后继续接受投票 1 天决议后收到的投票仍会记录进状态根只是奖励更少状态根记录可以批量在超时到期时执行若出现新的活跃头/链且该链尚未记录争议决议必须把争议决议或进行中的争议也记录/移植到该链——争议必须在所有链上存在以确保作恶者被惩罚验证人在两个对立方向上投票构成双重投票double vote与 backing、approval 情形相同若争议未在规定时间内解决所有验证人被罚少量金额且进入治理模式由人工裁决验证人意外重启后争议应基于持久存储中的已投投票继续。争议判定阶段状态机文档用 Mermaid 状态图描述了争议从开启到结论的完整状态流转校验与投票阶段的状态机五、节点侧实现Dispute Coordinator 子系统Dispute Coordinator 文档 定义的协调器是节点侧参与争议的中央子系统其核心实现在 node/core/dispute-coordinator/src/lib.rs。它封装了一个数据库用于跟踪所有验证人在某个 session 窗口内观察到的声明早于该窗口的投票被剪枝prune。在源码层面该子系统结构如下node/core/dispute-coordinator/src/lib.rsDisputeCoordinatorSubsystem持有config数据列col_dispute_data、storeKV 数据库、keystore与metrics内部模块包括backend数据库后端抽象、db版本化存储、import投票导入的纯处理逻辑、participation参与队列、scraping链上声明抓取、spam_slots垃圾争议防护、status争议状态跟踪与initialized收到第一个活跃叶子后的初始化。协调器的主要职责确保节点能在审批检查发现无效候选时提出争议approval-voting子系统会发送DisputeCoordinatorMessage::IssueLocalStatement指示投显式无效票协调器负责创建并签名该显式无效票并在该候选尚无进行中争议时触发争议确保 backing 与 approval 投票被记录上链只有被协调器记录的投票才会被用于罚没上链的投票保证已结论争议有可用的罚没目标同时抓取这些投票对垃圾防护至关重要确保 backing 投票永远不会被显式投票覆盖协调实际争议参与确保节点以能推动网络争议解决的方式参与任何合理争议即使在大量争议并发flood/DoS时也能逐个解决确保争议即使在废弃分叉abandoned forks上的候选也能尽可能解决以排除“免费尝试”、保证赌徒破产性质为链选择chain selection提供 API防止任何包含“争议进行中或已判定无效候选”的链被最终化避免在含无效候选的链上继续构建提供获取已解决争议及其全部投票隐式的 approval/backing 与显式争议投票的 API使验证人能相应获得奖励或被罚没。通过链抓取保证争议可被提出提出争议要求节点能提供两条对立的投票。由于 backing 阶段的目的是让验证人“有切身利益skin in the game”对立的有效票很可能就是 backing 投票也可能是已投出的 approval 投票。关键点在于只要 backing 投票可用任何节点都能提出争议。因此协调器的一项核心职责是确保“所有可能被争议的候选”的 backing 投票都可用实现方式是链抓取chain scraping每当候选在链上被 backing就把该区块导入的 backing 投票记录到链存储中协调器为所有未最终化区块查询这些投票漏块时做必要的链回溯。链抓取的高效性体现在两点投票已批量一个候选的全部可用 backing 投票一次性导入若像 candidate-backing 那样逐票导入在当时的协调器实现下会退化为二次方复杂度总量更少避免了为“从未在任何链上成功 backing 的候选”导入声明。它在安全上也是成立的争议只在 approval 阶段提出节点只有在某链上看到候选被包含后才开始审批流程而被包含的前提是曾被 backing——因此那时 backing 投票必然可用。信号按序处理即使跳过一个区块、只在包含区块时才导入 backing 投票在处理 approval 消息前也必然已看到它们。这意味着记录链上 backing 投票足以支撑争议提出无需预防性导入 approval 投票后者被证明是极低效的过程——每候选约 35 票二次方复杂度会累积。确保 approval 投票被记录防止“懒惰的审批检查者”只有协调器记录的投票会被用于罚没。虽然无需预防性记录 approval 投票但协议仍努力在争议实际发生时记录 approval 阶段收到的投票这不是结论争议所必需的节点反正会发出自己的投票无论是显式有效票还是已有 approval 票真正的原因是防止**“懒惰审批检查者”**若审批检查者能轻松地在争议发生后改投显式无效票且只有这一票被记录就能规避罚没这样他们就没有动力真正运行校验函数永远无风险地投“有效”票。设计取舍与实现要求只在有争议时导入 approval 投票否则日常开销浪费在例外情况上尽量批量导入避免二次方复杂度考虑审批与争议并发进行争议进行中 approval 投票仍在零星到达。因此由协调器主动向 approval-voting 索取争议候选的投票而非让 approval-voting 感知争议后转发。索取时机的结论是在争议结论的那一刻查询同时为缓解 approval-voting 过早删除投票的竞态在争议发起时和结论时各导入一次 approval 投票发起时导入尽量覆盖废弃分叉上的投票结论时导入最大化恶意 approval 投票的记录量。诚实验证人可能因此校验两次一次在 approval、一次在争议参与但这在争议这种例外场景下是值得的。确保链上导入跨 session 边界的罚没可达性Dispute Distribution 保证所有显式争议投票分发给当前出块者当前权威集合这对跨 erasession变更很重要若争议跨越验证人集合换届新集合必须知道争议与投票才能上链但分发只保证至少一条 backing/approval 票到达出块者不保证所有 backer 的票都到达approval 检查者的票更无保证——因为 approval 投票与最终化完全是链下过程只在与最终化相关节点间传播era 变更后新权威集合未必能见到上一 era 的 approval 投票系统关键性质仍然成立分发至少把一条“有效”票送到当前权威集合故判定“无效”时至少有一个节点会被罚没且现实中验证人集合很少 100% 更换新旧集合常有重叠。文档同时指出为保证最大程度的可追责上一权威集合向下一集合传递投票不依赖任何链的能力仍在规划中。争议参与协调与双队列设计协调器通过链抓取或dispute-distribution导入投票得知争议发现对立投票后记录争议存在若本地尚无该争议的投票则触发参与恢复可用性并重新校验 PoV结果成为节点的投票交 dispute-distribution 分发。参与决策并不是“盲目参与一切”只对真实争议投入大量工作防止廉价 DoS 放大攻击——单条消息触发全网大规模校验与网络流量使争议系统极易成为 DoS 放大器提出争议本身是昂贵的若你声称候选无效而它实际有效你将被罚没——但这只在争议对象真实存在时才成立不存在候选的争议永不结论、无人被罚没好在参与这种争议相对便宜各节点只发出数百条微小的可用性块请求换来 “NoSuchChunk” 小响应。触发参与的前提任一成立看到争议候选被包含在至少一条链的未最终化区块中看到争议候选被 backing 在至少一条链的未最终化区块中至少说明候选不是凭空捏造争议已被确认confirmed已有 1/31 节点参与——按威胁模型至少有一个诚实节点已投票争议必然真实。注意节点可能暂时落后于链、先知道争议后才知道包含区块因此必须在区块导入时重新评估参与决策。处理顺序参与需要大致全局有序使多数验证人按相近顺序逐个解决争议优先级队列priority queue对“已见被包含”的候选按候选的 relay parent 区块号排序同高度再按CandidateHash排序。此顺序全局唯一且优先处理更老的候选——若老候选无效可一次回滚整条链若先解决新争议再回滚则可能需回滚多次。这也让攻击者无法通过不断对新候选提争议来阻止回滚老候选尽力队列best-effort queue对“未包含但已 backing 或 1/31 已参与确认争议”的候选使用与优先级队列相同排序的尽力而为队列一旦得知包含区块会把相应参与请求提升到优先级队列该提升机制在文档中标注为进行中工作。废弃分叉与最终化深度被争议的链不会最终化但文档强调仍要关注“落后于最终化链的分叉”上的候选否则攻击者得知审批检查者后制造更优分叉即可逃脱罚没同时也关注最终化链本身到一定深度为止。深度必须明显大于 approval-voting 的执行超时否则在执行完成前信息已被丢弃争议无法结论。垃圾投票防护Spam Slots即使延迟参与也不应盲目把到达的投票全量导入数据库可能慢慢耗尽磁盘。因此协调器实现了spam slots机制源码见 node/core/dispute-coordinator/src/spam_slots.rs 所在目录每次导入含无效票、且无法判断是否垃圾的投票时为每个显式invalid投票签名参与者递增计数器。计为潜在垃圾potential spam的条件全部满足才递增被争议候选在任何链上既未被包含也未被 backing争议未被确认我们尚未为该争议投票。每当导入任何争议投票时检查这些条件若发现争议并非潜在垃圾则清除该争议候选哈希的 spam slots为每个投过 invalid 的验证人递减计数候选被 backing/包含时也会自然清除链上 backing 投票导入时处理。此设计的合理性在于真正需要担心的只有实际争议投票——backing 投票导入本身有速率限制且只针对真实候选approval 投票要到争议结论才导入而真实争议投票必须包含显式invalid票恶意节点至多占验证人的 1/3因此垃圾磁盘占用上限为2 * vote_size * n/3 * NUM_SPAM_SLOTSn为验证人数。特殊的 Backing 投票Backing 投票有两重特殊性它是任何有效争议能发起时唯一保证存在的有效票它是唯一承诺更短执行超时的投票BACKING_EXECUTION_TIMEOUT——相比 approval 投票更宽松的超时。为妥善处理跨机器执行时间差异罚没可能对 backing 投票比其他valid投票更激进。因此导入时绝不能用另一张有效票覆盖 backing 票——它们不可互换。源码中 node/core/candidate-validation/src/lib.rs 定义了DEFAULT_BACKING_EXECUTION_TIMEOUT Duration::from_secs(2)即 backing 阶段默认 2 秒的执行时限从代码层面印证了这一差异。数据库 Schema 与运行逻辑Dispute Coordinator 文档 定义了基于 KV 数据库提供write、read、iter_with_prefix操作的存储结构(candidate-votes, SessionIndex, CandidateHash) - OptionCandidateVotes recent-disputes - RecentDisputes earliest-session - OptionSessionIndex每候选跟踪的元信息为CandidateVotes结构对应 types/disputes.md 中的争议声明类型源码实现在 node/primitives/src/disputes/mod.rs/// Tracked votes on candidates, for the purposes of dispute resolution. pub struct CandidateVotes { /// The receipt of the candidate itself. pub candidate_receipt: CandidateReceipt, /// Votes of validity, sorted by validator index. pub valid: Vec(ValidDisputeStatementKind, ValidatorIndex, ValidatorSignature), /// Votes of invalidity, sorted by validator index. pub invalid: Vec(InvalidDisputeStatementKind, ValidatorIndex, ValidatorSignature), } /// The mapping for recent disputes; any which have not yet been pruned for being ancient. pub type RecentDisputes std::collections::BTreeMap(SessionIndex, CandidateHash), DisputeStatus; /// The status of dispute. This is a state machine which can be altered by the /// helper methods. pub enum DisputeStatus { /// The dispute is active and unconcluded. Active, /// The dispute has been concluded in favor of the candidate /// since the given timestamp. ConcludedFor(Timestamp), /// The dispute has been concluded against the candidate /// since the given timestamp. ConcludedAgainst(Timestamp), /// Dispute has been confirmed (more than byzantine_threshold have already participated/ or /// we have seen the candidate included already/participated successfully ourselves). Confirmed, }DisputeStatus的源码实现在 node/primitives/src/disputes/status.rs其迁移方法confirm、conclude_for、conclude_against、is_possibly_invalid体现了“结论优先于确认、反对结论优先于赞成结论”的状态机语义ConcludedAgainst会覆盖ConcludedFor除非大量验证人在双方同时参与这被认为是不可达的。关键常量源码可查DISPUTE_WINDOW: SessionWindowSize 6node/primitives/src/lib.rs——争议投票的 session 窗口文档要求对应至少 1 天RuntimeInfo的 session 缓存 LRU 大小与之对齐node/core/dispute-coordinator/src/lib.rsACTIVE_DURATION_SECS: Timestamp 180node/primitives/src/disputes/status.rs——ActiveDisputes查询返回“最近ACTIVE_DURATION_SECS秒内结论的争议”MAX_PARALLEL_PARTICIPATIONSnode/core/dispute-coordinator/src/participation/mod.rs——同时进行的参与任务数上限测试配置下为 1、常规为 3防止参与管线被并发争议压垮。主循环与消息处理对应 Dispute Coordinator 文档 的 Functionality 一节启动时等待第一个OverseerSignal::ActiveLeaves初始化RollingSessionWindow含叶子哈希与DISPUTE_WINDOW从 DB 加载活跃争议并初始化 spam slots对每个加载的争议若有本地投票则发DisputeDistribution::SendDispute否则视情况入队参与主循环run_until_error持续运行直到收到OverseerSignal::ConcludeActiveLeaves把ActiveLeavesUpdate交给 ordering provider、更新 session 信息缓存与highest_session、session 窗口推进时剪枝 spam slots、抓取链上投票ImportStatements三个主要职责——发起争议参与并发送已有本地 approval 票、把全部新投票持久化到 DB、对全部DisputeStatement::Invalid投票做垃圾防护RecentDisputes/ActiveDisputes返回 DB 中全部近期争议 / 最近ACTIVE_DURATION_SECS内结论的争议QueryCandidateVotes按(SessionIndex, CandidateHash)查询candidate-votesIssueLocalStatement构造DisputeStatementValid/Invalid→ 用 keystore 中 session 的平行链验证密钥签名跳过voted_indices中的索引→ 写入 DB → 发送DisputeDistributionMessage::SendDisputeDetermineUndisputedChain从block_descriptions起始逐一检查RecentDisputes遇到进行中或结论为负的争议即停止返回可视为“无争议”的最长链前缀。六、网络层Dispute Distribution 子系统Dispute Distribution 文档 负责确保所有相关验证人知晓争议并持有相关投票核心实现在 node/network/dispute-distribution/src/lib.rs。设计目标对节点暂时不可用具有韧性、快速传播、网络开销合理、对垃圾具有韧性并且“简单无聊”——争议真正发生时必须可靠工作。关键设计选择不是 gossip而是请求/响应协议。为确保投票被可靠投递到所有相关验证人该子系统采用请求/响应协议请求为实际投票负载响应为确认获得应用层确认。线上格式Wire Format争议协议标识/genesis_hash/fork_id/send_dispute/1请求包含struct DisputeRequest { /// The candidate being disputed. pub candidate_receipt: CandidateReceipt, /// The session the candidate appears in. pub session_index: SessionIndex, /// The invalid vote data that makes up this dispute. pub invalid_vote: InvalidDisputeVote, /// The valid vote that makes this dispute request valid. pub valid_vote: ValidDisputeVote, } /// Any invalid vote (currently only explicit). pub struct InvalidDisputeVote { pub validator_index: ValidatorIndex, pub signature: ValidatorSignature, pub kind: InvalidDisputeStatementKind, } /// Any valid vote (backing, approval, explicit). pub struct ValidDisputeVote { pub validator_index: ValidatorIndex, pub signature: ValidatorSignature, pub kind: ValidDisputeStatementKind, }响应仅为enum DisputeResponse { Confirmed }。投票恢复Vote Recovery协议/genesis_hash/fork_id/req_votes/1struct IHaveVotesRequest { candidate_hash: CandidateHash, session: SessionIndex, valid_votes: Bitfield, invalid_votes: Bitfield, } struct VotesResponse { /// All votes we have, but the requester was missing. missing: Vec(DisputeStatement, ValidatorIndex, ValidatorSignature), }发起与参与发起节点发出第一条DisputeRequest即视为发起争议消息必须同时包含一条invalid 票与一条 valid 票。SendDispute指令由协调器发出携带本地节点的 invalid 票和某条 valid 票如 backing 声明。包含 valid 票是为了让任何节点无论是否与链同步、是否见过 backing/approval 票都能看出存在冲突投票、即存在有效争议——节点仍需检查争议投票是否当前有效而非过期参与收到DisputeRequest后dispute-distribution 通过ImportStatements触发协调器导入投票协调器决定是否参与并发出自己的SendDispute。若本地判定候选有效SendDispute将携带本地签名的 valid 票与最初收到的 invalid 票。垃圾防护的有效性检查依赖dispute-coordinator完成。发送、可靠性与速率限制目标节点消息发送给争议发生 session 的全部平行链验证人他们要参与争议外加当前 session 的全部权威他们不参与但需要把声明写进区块可靠性只有收到确认才认为消息已送达否则只要争议仍存活就持续重试每次重试前通过ActiveDisputes询问协调器争议是否仍活跃顺序SendDispute消息按重要性顺序发送重试时保持同序速率限制源码常量接收侧RECEIVE_RATE_LIMIT 100ms发送侧SEND_RATE_LIMIT 150ms多 50ms 安全边际以避免触发接收侧限制导致消息被丢弃、声誉下降见 node/network/dispute-distribution/src/lib.rs。接收侧防垃圾与批处理接收侧的目标尽快把新争议交给协调器以便优先级排序、尽量按争议批量投票导入性能、防止恶意节点耗尽资源、防止恶意节点阻止好争议结论、限制恶意节点通过批处理逻辑延迟投票导入。即时导入 批处理折中新争议的首条投票立即导入让协调器即时知晓并反馈有效性确认有效后后续投票批量收集再整体提交批收集条件直到最近BATCH_COLLECTING_INTERVAL内收到的唯一投票数少于MIN_KEEP_BATCH_ALIVE_VOTES才关闭批次发送兼顾延迟与批量目标诚实行为推断诚实验证人每候选/争议只发一条消息且投票前必须完整恢复可用性并校验候选因此发送频率天然不高可施加保守速率限制攻击成本分析文档给出的量化示例以 1000 验证人为例、1/3 恶意约 330 个每人每 100ms 可发一条消息若MIN_KEEP_BATCH_ALIVE_VOTES 10、BATCH_COLLECTING_INTERVAL 500ms、RATE_LIMIT 100ms则首批可开约 3300 个批次每批 2 票但为维持每批存活每 500ms 需 10 条新票流入即每批需 10 个攻击者批次数量被压制到约 330下一秒所有消息都用于维持批次因此内存硬上限约为330 批 × 330 票 × 100 字节/签名 ≈ 10 MiB。若验证人规模达到 10,000最坏情况进入 GB 级需更严格速率限制或提高批存活所需投票率。对千级验证人约 1000 的批上限在实践中不会触及从而几乎不会因资源限制丢弃有效争议启动节点启动无需特殊处理协调器会通过SendDispute告知进行中的争议。韧性Resiliency针对三类缺口——非验证人节点可能对未上链投票感兴趣、节点可能错过 backing/approval 投票从链上恢复因 runtime 升级与无类型 extrinsics 而困难昂贵、era 变更后新权威集合看不到旧 approval 投票——引入低优先级的req_votes请求/响应协议接收方看发送方缺哪些已知投票并回复若发送方有己方没有的投票则回发IHaveVotesRequest并记录对方的知识发送时机收到FetchMissingVotes指令时或争议活跃期间约每区块一次向某个随机验证人发送垃圾防护每验证人每 slot 接受一次此类请求更频繁的请求或陈旧数据请求可丢弃非验证人节点的请求按尽力而为处理。七、争议声明类型链上类型层争议的链上数据模型定义在 roadmap/implementers-guide/src/types/disputes.md/// A set of statements about a specific candidate. struct DisputeStatementSet { candidate_hash: CandidateHash, session: SessionIndex, statements: Vec(DisputeStatement, ValidatorIndex, ValidatorSignature), } /// A statement about a candidate, to be used within some dispute resolution process. enum DisputeStatement { /// A valid statement, of the given kind Valid(ValidDisputeStatementKind), /// An invalid statement, of the given kind. Invalid(InvalidDisputeStatementKind), } /// 各类声明与候选哈希、session 索引、验证人公钥与签名组合即可复现并校验原始声明。 enum ValidDisputeStatementKind { Explicit, BackingSeconded(Hash), BackingValid(Hash), ApprovalChecking, } enum InvalidDisputeStatementKind { Explicit, }这解释了“发起与参与共用同一消息”的设计DisputeStatement只有Valid/Invalid两个方向有效票内部再细分Explicit显式争议票、BackingSeconded/BackingValidbacking 阶段的两种 attestation与ApprovalChecking审批检查票无效票目前只有Explicit一种——这与“只有投显式无效票才可能构成垃圾”的 spam slot 设计相呼应。DisputeStatevalidators_for/validators_against位图、start、concluded_at与ScrapedOnChainVotes含 session、各候选的 backing 验证人列表、链上内在函数记录的已结论争议集合则定义了链上状态与链下协调器之间的桥接数据结构。八、与最终化GRANDPA的联动及范围外设计审批协议中明确要求对 GRANDPA 投票策略做配套修改见 protocol-approval.md 的 “Finality GRANDPA Voting Rule” 一节诚实节点只投票给所有平行链候选都已获批的链且不投票给存在进行中争议、或争议已判定候选无效的链。这样最终化链只包含“多数人认为其内每个区块都得到充分批准”的区块。明确不做的事Out of Scope见 Dispute Coordinator 文档不对未包含候选发起争议只关心已在至少某条链上包含即可用性达成的候选。可用性系统就是为“可靠检查并罚没恶意 backer”设计的未包含候选不构成威胁对其争议会非常脆弱无可用性保障且垃圾防护远更难——所有上文策略都会失效。可能提出此类争议的也只有诚实 backing 节点或 collatorcollator 数量无限、无法对其收费垃圾问题更严重而诚实 backer 等可用性达成后再争议也更有意义不对已最终化区块发起争议对最终化区块争议为时已晚桥已处理该区块、损害已成事实只能靠治理善后。允许这种争议只带来两个价值——至少仍能罚没攻击者、以及冻结链到治理模式但两者都收益有限且会引入巨大的 DoS 面。禁止争议已最终化区块极大减少了可被争议的候选数量是 DoS 防护的基石它配合“争议负载高时限制包含”“最终性滞后时出块自然减速”等措施保证系统能跟上争议处理。结语Polkadot 的争议协议是“检测—升级—后果”三段式安全链的收尾环节检测与升级由 Approval 协议完成争议则确保每一次作恶尝试都被记账并受到罚没。它的关键设计——分叉无关性、local/remote 争议区分、所有历史罚没、⅔ 绝对多数结论、垃圾争议多重防护spam slots、速率限制、批处理上限、双参与队列——共同保证了“无效区块永远无法免费进入最终化链攻击者在赌徒破产之前无法积累足够尝试”。读者可以进一步在源码中追踪本文提到的各个组件协调器主循环见 node/core/dispute-coordinator/src/lib.rs争议状态机见 node/primitives/src/disputes/status.rs分发协议与速率限制见 node/network/dispute-distribution/src/lib.rs声明类型见 types/disputes.md完整流程条件化描述见 disputes-flow.md。赞分享区块链【免费下载链接】polkadotPolkadot Node Implementation项目地址https://gitcode.com/gh_mirrors/po/polkadot点击查看免费下载相关推荐Textual DirectoryTree 详解在终端中构建文件系统导航树Textual DirectoryTree 详解在终端中构建文件系统导航树 DirectoryTree 是 Textual 内置的树形控件专门用于在终端及区块链memcached网络协议全解析从ASCII到二进制协议memcached网络协议全解析从ASCII到二进制协议 本文全面解析Memcached的网络协议体系从基础的ASCII文本协议到高性能的二进制协议深入探缓存后端高可用Polkadot 节点 Runtime API 子系统解析协议、请求处理与结果缓存Polkadot 节点 Runtime API 子系统解析协议、请求处理与结果缓存 导读 本文以 Polkadot 实现者指南Implementers G区块链上一篇Vitis AI量化工具使用指南提升模型性能的关键步骤下一篇Playwright-Skill 战略指南AI驱动的浏览器自动化架构深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表