Tendermint 轻客户端攻击者隔离(Light Client Attackers Isolation):三类攻击的链上举证与验证

发布时间:2026/10/12 2:19:26
Tendermint 轻客户端攻击者隔离(Light Client Attackers Isolation):三类攻击的链上举证与验证 区块链共识算法【免费下载链接】tendermint⟁ Tendermint Core (BFT Consensus) in Go项目地址https://gitcode.com/gh_mirrors/te/tendermint点击查看免费下载本文基于 Tendermint 规范 spec/light-client/attacks/isolate-attackers_002_reviewed.md系统讲解全节点full node如何利用轻客户端提交的攻击证据evidence通过isolateMisbehavingProcesses函数从链上隔离出实际的作恶验证人集合。文章覆盖问题定义、输出契约、隔离协议、三类攻击lunatic / equivocation / amnesia的判定逻辑、TLA 完整性论证并结合仓库 Go 实现light/detector.go、types/evidence.go、evidence/verify.go给出源码级印证。读完本文你将掌握攻击证据的数据结构、全节点验证路径、隔离算法的完整调用链以及攻击类型穷尽性的形式化论证方法。一、背景为什么需要隔离攻击者1.1 攻击的本质是偏离共识协议签名对抗性节点adversarial nodes有动机向轻客户端谎报 Tendermint 区块链的状态这种尝试被称为攻击。轻客户端验证依赖所谓的commit——一组在执行 Tendermint 共识时产生的签名消息。因此一次攻击本质上归结为偏离 Tendermint 共识算法规则去创建并签名共识消息见原规范第 3 行。由于 Tendermint 共识与轻客户端验证的安全性都建立在每个区块拥有超过 2/3 正确投票权的假设[[TMBC-FM-2THIRDS]]之上见 verification_002_draft.md 中[TMBC-FM-2THIRDS.1]要求任意相邻区块间有超过 2/3 投票权、时间位于信任期内的验证者持续在线且正确执行协议一旦发生攻击必然意味着该假设被违反。由此可推出关键事实某些验证者偏离了协议这些验证者在某一区块中代表的投票权超过 1/3。正是这超过 1/3 投票权的下界为攻击者隔离提供了可行性即便只有 1/3 的验证者作恶也足以产生两个互相冲突的合法签名集合而正确验证者不可能为非法区块签名因此交集必然命中作恶者。1.2 检测、证据与隔离的职责分工在轻客户端攻击检测机制detector检测到攻击后会计算被称为evidence的数据定义见[[LC-DATA-EVIDENCE.1]]其用途有二证明确实发生了攻击[[TMBC-LC-EVIDENCE-DATA.1]]作为找出实际偏离 Tendermint 协议节点的基础。本规范隔离规范考虑的正是第二步Tendermint 区块链上的全节点如何从证据中隔离出一组发动攻击的作恶验证者。隔离出的集合需要满足集合中不包含任何正确验证者集合中的验证者代表超过 1/3 的投票权且对应区块仍处于unbonding period解绑期内。这一约束非常关键只有仍在解绑期内的验证者才可被惩罚slash这也与全节点在链上证据处理时只向应用上报 bonded 验证者的要求一致。二、Part I问题定义与输出契约2.1 输入攻击证据检测机制规范定义了证据的数据格式[[LC-DATA-EVIDENCE.1]]type LightClientAttackEvidence struct { ConflictingBlock LightBlock CommonHeight int64 }ConflictingBlock与链上区块冲突的轻区块由攻击者构造、经检测机制确认可从公共高度验证。CommonHeight主链与冲突分支分叉前共同信任的高度。该结构的 Go 实现位于 types/evidence.go额外携带 ABCI 相关信息type LightClientAttackEvidence struct { ConflictingBlock *LightBlock CommonHeight int64 // abci specific information ByzantineValidators []*Validator // validators in the validator set that misbehaved in creating the conflicting block TotalVotingPower int64 // total voting power of the validator set at the common height Timestamp time.Time // timestamp of the block at the common height }注意Height()返回的是CommonHeight而非冲突高度因为作恶验证者在该高度必定处于 bonded 状态这对证据过期evidence expiry判断至关重要见 types/evidence.go 的注释。2.2 隔离函数的输入输出契约**isolator隔离器**是一个函数输入为证据ev和区块链前缀bc至少延伸到高度ev.ConflictingBlock.Header.Height 1输出为验证者的peerID 集合。规范假设全节点已与区块链同步并到达高度ev.ConflictingBlock.Header.Height 1。核心不变式[LCAI-INV-Output.1]定义了输出的合法条件若满足以下条件bc[CommonHeight].bfttime相对全节点当前时间仍在解绑期内ev.ConflictingBlock.Header ! bc[ev.ConflictingBlock.Header.Height]确实冲突ev.ConflictingBlock.Commit中的验证者在bc[ev.CommonHeight].NextValidators中代表超过 1/3 的投票权则输出必须是bc[CommonHeight].NextValidators的一个子集且该子集代表超过 1/3 的投票权确实在高度ev.ConflictingBlock.Header.Height签名了违反 Tendermint 共识协议的共识消息。否则输出空集。从实现看这一契约的 TLA 版本在 spec/light-client/attacks/Isolation_001_draft.tla 中被建模为两个不变式DetectionCompleteness攻击者投票权 1/3与DetectionAccuracy攻击者 ⊆ Faulty即不含正确验证者。三、Part II隔离协议3.1 主函数isolateMisbehavingProcesses规范的协议核心是主函数[LCAI-FUNC-MAIN.1]func isolateMisbehavingProcesses(ev LightClientAttackEvidence, bc Blockchain) []ValidatorAddress { reference : bc[ev.conflictingBlock.Header.Height].Header ev_header : ev.conflictingBlock.Header ref_commit : bc[ev.conflictingBlock.Header.Height 1].Header.LastCommit // 1 !! ev_commit : ev.conflictingBlock.Commit if violatesTMValidity(reference, ev_header) { // lunatic light client attack signatories : Signers(ev.ConflictingBlock.Commit) bonded_vals : Addresses(bc[ev.CommonHeight].NextValidators) return intersection(signatories, bonded_vals) } // If this point is reached the validator sets in reference and ev_header are identical else if RoundOf(ref_commit) RoundOf(ev_commit) { // equivocation light client attack return intersection(Signers(ref_commit), Signers(ev_commit)) } else { // amnesia light client attack return IsolateAmnesiaAttacker(ev, bc) } }整体逻辑分三步走规范中的 Outline先验证冲突区块能否从公共高度验证ValidAndVerifiedUnbonding见 3.3 节再判定攻击类型先检查是否为 lunatic违反有效性若不是检查是否为 equivocation同一轮次双重签名若都不是则进入链上accountability问责协议处理 amnesia 攻击。3.2 前置条件、后置条件与错误条件前置条件length(bc) ev.conflictingBlock.Header.HeightValidAndVerifiedUnbonding(bc[ev.CommonHeight], ev.ConflictingBlock) SUCCESS公共高度块未过期且冲突块可验证ev.ConflictingBlock.Header ! bc[ev.ConflictingBlock.Header.Height]ev.conflictingBlock通过基本校验尤其 commit 中所有签名消息必须来自同一轮次。后置条件[LCAI-INV-Output.1]成立。错误条件前置条件被违反时返回错误。3.3 辅助函数ValidAndVerifiedUnbonding(trusted, untrusted)[LCAI-FUNC-VVU.1]条件与验证规范的[LCV-FUNC-VALID.2]见 verification_002_draft.md 中ValidAndVerified完全一致唯一区别是把前置条件trusted.Header.Time now - trustingPeriod替换为trusted.Header.Time now - UnbondingPeriod也就是说全节点在受理证据时使用解绑期而非轻客户端的信任期作为时间窗口保证上报的作恶验证者仍在押金锁定范围内。violatesTMValidity(ref, ev)[LCAI-FUNC-NONVALID.1]检查证据头ev是否违反 Tendermint 共识的有效性属性。前置条件ref.Height ev.Height后置条件返回以下析取式[LCAI-NONVALID-OUTPUT.1]的求值结果ref.ValidatorsHash ! ev.ValidatorsHash or ref.NextValidatorsHash ! ev.NextValidatorsHash or ref.ConsensusHash ! ev.ConsensusHash or ref.AppHash ! ev.AppHash or ref.LastResultsHash ! ev.LastResultsHashIsolateAmnesiaAttacker(ev, bc)触发链上的query/response 协议on-chain accountability protocol后置条件为返回符合[LCAI-INV-Output.1]的攻击者集合。RoundOf(commit)前置条件commit 格式良好尤其所有投票来自同一轮次r后置条件返回 commit 中所有投票编码的轮次r前置条件被违反时报错。Signers(commit)返回 commit 中所有验证者地址。Addresses(vals)返回验证者列表中所有验证者地址。3.4 实现注释 1的含义代码中ref_commit取自bc[ev.conflictingBlock.Header.Height 1].Header.LastCommit注意 1。原因是全节点本地存储的、由正确验证者签名的高度H的 commit实际上是高度H1区块头中的LastCommit字段。若全节点只推进到高度ev.conflictingBlock.Header.Height则该字段引用的是本地存储的该高度 commit由length(bc)前置条件保证存在。这一点与检测机制中getSigners(trustedCommit)使用bc[conflictingBlock.Header.Height1].LastCommit的写法见 notes-on-evidence-handling.md完全一致。另外规范明确指出虽然前置条件已检查解绑期未过期但时间在流动因此在把验证者移交给 Cosmos SDK 之前需要再次检查时间以满足只上报 bonded 验证者的契约——这一移交动作不在本规范范围内。四、三类攻击的判定与源码印证4.1 攻击类型归纳规范将错误签名的消息归纳为三种类型类型含义判定条件Lunatic狂想签名了非法区块有效状态转换之外的内容violatesTMValidity为真Equivocation双重签名在同一共识轮次双重签名了不同合法区块violatesTMValidity为假且两 commit 轮次相同Amnesia失忆在不同共识轮次签名冲突区块却未见过允许其这样做的法定人数消息violatesTMValidity为假且两 commit 轮次不同4.2 Go 实现的对应逻辑规范中的violatesTMValidity在 types/evidence.go 中实现为ConflictingHeaderIsInvalidfunc (l *LightClientAttackEvidence) ConflictingHeaderIsInvalid(trustedHeader *Header) bool { return !bytes.Equal(trustedHeader.ValidatorsHash, l.ConflictingBlock.ValidatorsHash) || !bytes.Equal(trustedHeader.NextValidatorsHash, l.ConflictingBlock.NextValidatorsHash) || !bytes.Equal(trustedHeader.ConsensusHash, l.ConflictingBlock.ConsensusHash) || !bytes.Equal(trustedHeader.AppHash, l.ConflictingBlock.AppHash) || !bytes.Equal(trustedHeader.LastResultsHash, l.ConflictingBlock.LastResultsHash) }而isolateMisbehavingProcesses的三分支结构对应GetByzantineValidatorstypes/evidence.go注释与分支逻辑完全一致无效头 → lunatic取公共验证者集合中给冲突区块投票者轮次相同 → equivocation取两个 commit 都签名者轮次不同 → amnesia因无法仅凭证据推断返回空验证者集合。注意一个工程细节判定轮次时规范使用RoundOf(ref_commit)引用块 commit 编码的轮次Go 实现使用trusted.Commit.Round——两者语义相同因为bc[ConflictingHeight1].Header.LastCommit正是与冲突高度同高的被信任 commit。4.3 检测端轻客户端侧的证据生成隔离协议的输入端是检测机制的输出。在 light/detector.go 中newLightClientAttackEvidence生成证据时也会做同样的类型判定light/detector.gofunc newLightClientAttackEvidence(conflicted, trusted, common *types.LightBlock) *types.LightClientAttackEvidence { ev : types.LightClientAttackEvidence{ConflictingBlock: conflicted} // if this is an equivocation or amnesia attack, i.e. the validator sets are the same, then we // return the height of the conflicting block else if it is a lunatic attack and the validator sets // are not the same then we send the height of the common header. if ev.ConflictingHeaderIsInvalid(trusted.Header) { ev.CommonHeight common.Height ev.Timestamp common.Time ev.TotalVotingPower common.ValidatorSet.TotalVotingPower() } else { ev.CommonHeight trusted.Height ev.Timestamp trusted.Time ev.TotalVotingPower trusted.ValidatorSet.TotalVotingPower() } ev.ByzantineValidators ev.GetByzantineValidators(common.ValidatorSet, trusted.SignedHeader) return ev }关键点CommonHeight 的取值本身携带了攻击类型信息。若CommonHeight ! ConflictingBlock.Height则按定义是 lunatic 攻击因为验证者集合不同只能从公共高度验证冲突块若相等则是 equivocation/amnesia。这与检测规范CreateEvidenceForPeer中的注释一致detection_003_reviewed.md。4.4 全节点侧的链上验证全节点收到证据后在 evidence/verify.go 的VerifyLightClientAttack中执行完整验证对应规范的前置条件func VerifyLightClientAttack(e *types.LightClientAttackEvidence, commonHeader, trustedHeader *types.SignedHeader, commonVals *types.ValidatorSet, now time.Time, trustPeriod time.Duration) error { // In the case of lunatic attack there will be a different commonHeader height. Therefore the node perform a single // verification jump between the common header and the conflicting one if commonHeader.Height ! e.ConflictingBlock.Height { err : commonVals.VerifyCommitLightTrusting(trustedHeader.ChainID, e.ConflictingBlock.Commit, light.DefaultTrustLevel) ... } else if e.ConflictingHeaderIsInvalid(trustedHeader.Header) { return errors.New(common height is the same as conflicting block height so expected the conflicting block to be correctly derived yet it wasnt) } ... }随后验证冲突验证者集合对冲突块的 2/3 提交、投票权一致、以及前向 lunatic 攻击的时间单调性检查。证据池入口Pool.verifyevidence/verify.go还会先做过期检查只有当ageDuration MaxAgeDuration ageNumBlocks MaxAgeNumBlocks时才判定过期evidence/verify.go。默认证据参数MaxAgeNumBlocks: 100000、MaxAgeDuration: 48 * time.Hour定义在 types/params.go——这正是解绑期窗口在工程上的落地形态。4.5 amnesia 攻击为何需要链上问责协议从 types/evidence.go 的注释可以看到amnesia 攻击无法仅凭证据数据推断作恶者因为两个 commit 轮次不同签名者集合相同也不能说明谁违规——违规的判定标准是在未见过允许其这样做的法定人数消息的情况下跨轮次签名见 notes-on-evidence-handling.md 中的 amnesia 处理协议。因此 amnesia 分支必须触发链上 query/response 协议监控者monitor可在分布式环境中以链上模块实现向冲突高度的验证者请求 votesets验证者在超时内发送各自收到的投票集超时未响应者判为 faulty预处理每个合法投票被归入其发送者的 voteset确保被至少一个正确验证者观察到的恶意投票不会被排除独立分析每个验证者的 voteset判定其是否出现非法状态转换例如同一轮次发送多于一条 PREVOTE 或 PRECOMMIT未收到 2/3 投票权对应的 PREVOTE 就发送 PRECOMMIT在轮次r发送 PREVOTE(V) 之前曾在轮次rr r发送过 PRECOMMIT(V)且缺乏vrvr ≥ 0 且 r vr r轮次的 2/3 PREVOTE(vr, V) 作为依据。这也解释了为什么 amnesia 攻击只在多轮次高度commit round 0才可能发生——单一轮次内不存在跨轮次的非法转换空间。五、Part III完整性论证为什么三类攻击是穷尽的5.1 归约到固定成员资格下的二元共识如文档开头所述攻击归结为偏离共识规则签名消息。主函数区分的三种错误签名类型是否覆盖所有攻击论证如下第一个检查violatesTMValidity处理 lunatic 攻击。若该检查通过返回 FALSE则[LCAI-NONVALID-OUTPUT.1]为假意味着ref.ValidatorsHash ev.ValidatorsHash即冲突区块的验证者集合与链上一致因此只需分析**固定成员资格固定验证者集合**的单实例 Tendermint 共识又因为同一高度存在两个不同区块只需考虑两个不同的共识值——即二元共识binary consensus。5.2 TLA 与 Ivy 的交叉验证对于固定成员资格作者使用 Tendermint 共识的TLA 规范对应仓库 spec/light-client/accountability 中的TendermintAcc_004_draft.tla及其不变式TendermintAccInv_004_draft.tla进行了分析检查确认唯一可能导致 agreement 违反的场景就是 equivocation 和 amnesia。Galois 基于 Ivy 证明spec/ivy-proofs的独立研究得出相同结论。Synopsis.md 总结了问责 TLA 模型的要点简化模型假设单高度一次性共识、只关注安全性、时间用非确定性建模、每个进程投票权为 1、哈希为恒等映射核心结论是在集体证据下至少f1个拜占庭进程必然表现出 equivocation同一轮次发送两个不同值或 amnesia锁定了过去锁定过的另一个值。5.3 隔离模型的机械化验证攻击隔离逻辑本身也有 TLA 模型 spec/light-client/attacks/Isolation_001_draft.tla。该模型用 Apalache 检查器验证两个不变式注释中标注为[LCAI-INV-Output.1::TLA-DETECTION-COMPLETENESS.1]与[LCAI-INV-Output.1::TLA-DETECTION-ACCURACY.1]DetectionCompleteness state / init 3 * Cardinality(attackers) Cardinality(blockchain[CONFLICT_HEIGHT].VS) DetectionAccuracy attackers \subseteq Faulty其中Next动作正是isolateMisbehavingProcesses的机械化版本ViolatesValidity时取NextVS ∩ evidenceCommitlunatic否则轮次相同取referenceCommit ∩ evidenceCommitequivocation轮次不同则进入 amnesia 分支并存在一个满足 1/3 投票权的攻击者子集该属性由TendermintAcc的 Accountability 性质保证。这为本文第 2.2 节的输出契约提供了自动化验证依据。六、端到端流程与工程落地点综合规范与代码完整的攻击处理链路如下检测轻客户端以 primary 验证目标头再用 witness 交叉比对light/detector.go 的detectDivergence发现冲突后examineConflictingHeaderAgainstTrace定位分叉点生成证据newLightClientAttackEvidence判定攻击类型并填充CommonHeight、ByzantineValidators等字段对 primary/witness 双向生成证据并发送handleConflictingHeaderslight/detector.go链上受理全节点经证据池Pool.verify做基础与过期校验evidence/verify.goVerifyLightClientAttack完成轻信任验证与类型一致性检查隔离GetByzantineValidators依据类型计算作恶验证者types/evidence.goamnesia 场景则通过链上问责协议在后续区块中确定当前实现中 amnesia 证据的ByzantineValidators为空见 evidence/verify.go 的校验逻辑上报应用ABCI()将每个作恶验证者转换为abci.Evidence类型LIGHT_CLIENT_ATTACKtypes/evidence.go供应用层实施惩罚slash。相关测试可参考 evidence/verify_test.goTestVerifyLightClientAttack_Amnesia等用例与 evidence/pool_test.goTestLightClientAttackEvidenceLifecycle它们验证了本文所述各类型攻击的隔离结果与生命周期。七、关键要点总结攻击即偏离共识协议的签名攻击能成立的前提是超过 1/3 投票权偏离协议这保证了隔离集合的下界证据是常量大小的二元组ConflictingBlock CommonHeight同时满足轻客户端带宽约束与全节点可验证性三类攻击穷尽lunatic非法块、equivocation同轮双签、amnesia跨轮无依据签名其穷尽性由 TLA 分析与 Ivy 证明双重背书隔离的输出契约不含正确验证者、代表超过 1/3 投票权、且区块仍处于解绑期内三者缺一不可amnesia 最复杂无法仅凭证据定位作恶者需链上 query/response 问责协议结合验证者本地投票集判定工程实现完全对齐规范ConflictingHeaderIsInvalid↔violatesTMValidityGetByzantineValidators↔isolateMisbehavingProcesses三分支EvidenceParams.MaxAgeDuration↔ unbonding period 窗口。赞分享区块链共识算法【免费下载链接】tendermint⟁ Tendermint Core (BFT Consensus) in Go项目地址https://gitcode.com/gh_mirrors/te/tendermint点击查看免费下载相关推荐Tendermint 轻客户端Light Client协议规范解析提交验证、攻击检测与问责机制Tendermint 轻客户端Light Client协议规范解析提交验证、攻击检测与问责机制 Tendermint 轻客户端协议允许资源受限设备如智能区块链共识算法Tendermint 分叉问责Fork Accountability规范与实现从攻击模型到链上证据Tendermint 分叉问责Fork Accountability规范与实现从攻击模型到链上证据 导读 本文围绕 Tendermint Core 的《F区块链共识算法Tendermint轻客户端快速验证区块链状态的技术实现Tendermint轻客户端快速验证区块链状态的技术实现 Tendermint轻客户端是区块链技术中的一项重要创新它允许用户在 无需下载完整区块链数据 的情区块链共识算法上一篇CANN Runtime ACL 错误码 EH0002 排查指南Argument must not be null 空指针参数报错的定位与处理下一篇ESP32 BLE Object Transfer ServiceOTS服务端示例详解基于 esp-iot-solution 实现对象传输服务的 GATT 服务器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询