# Tendermint中的evidence机制

By [CaseyLuo](https://paragraph.com/@luoyx) · 2022-10-29

---

在之前介绍过的tendermint共识机制中提到过，共识协议能够容忍小于1/3的byzantine节点。但是即使在>=1/3的节点出现byzantine问题后，tendermint依然提供了一个尽力而为的安全机制-evidence，用于找出系统中存在的byzantine节点并通知其他正常的节点，避免系统出现问题。需要说明的是，被发现的byzantine节点可能会受到没收stake的惩罚，但是evidence机制本身并不执行惩罚，它只是在链上提交evidence，并通知上层的应用。

首先，来介绍一下evidence的检测和产生机制。在tendermint中当前存在两类evidence，分别为DuplicateVoteEvidence和LightClientAttackEvidence。

当byzantine节点控制+1/3的投票权后，可以成功发起重复投票攻击，在同一个height的同一个round内对两个不同的block同时确认并投票，并分别与网络中其他的剩余正常节点达成+2/3共识，就可以导致tendermint网络出现不一致的确认状态。但是DuplicateVoteEvidence机制的存在，有机会可以发现并解决这类攻击。例如当一个节点发现来自同一个节点的矛盾的投票（同一个height的同一个round内对两个不同的block同时确认并投票），就可以构造一个DuplicateVoteEvidence并广播。DuplicateVoteEvidence结构如下：

    type DuplicateVoteEvidence struct {
      VoteA *Vote
      VoteB *Vote
    
      // abci specific information
      TotalVotingPower int64
      ValidatorPower   int64
      Timestamp        time.Time
    }
    

其中，VoteA和VoteB就是受到的来自同一个节点的矛盾的两个投票。

light client节点没有足够的资源来验证并执行交易，只是简单向正常节点拉取所需的状态，并对header做轻量的验证工作。light client会连上全节点中的若干集合，选取一个节点作为primary，其他节点作为witnesses，向primary拉取所需状态和header，并同时向witnesses拉取header作为对比验证。这里有两种机制，一种是primary+witnesses需要包含+2/3的投票权，另一种是只需包含+1/3的投票权。第二种是默认的执行机制，因为所需资源更少，而且一般情况下集群中不会出现+1/3的byzantine节点。但是如果出现+1/3点byzantine节点，就有可能对light client节点进行欺骗。如下图所示，light client在height 11时，从primary收到了'A，但从witness收到了'B，存在矛盾。

![](https://storage.googleapis.com/papyrus_images/443da520537c99acf35905cb0270de464c2a36eecfd4c0ea44d122b505f33592.png)

light client在验证header的过程中，一旦发现不一致的header，就会向双方各自发送LightClientAttackEvidence，LightClientAttackEvidence中记录了矛盾的block：

    type LightClientAttackEvidence struct {
      ConflictingBlock *LightBlock
      CommonHeight     int64
    
      // abci specific information
      ByzantineValidators []*Validator
      TotalVotingPower    int64       
      Timestamp           time.Time 
    }
    

其中ConflictingBlock为与消息接收节点矛盾的block。如上图中，light client会向primary发送包含'B的LightClientAttackEvidence，向witness发送包含'A的LightClientAttackEvidence。

上面介绍了DuplicateVoteEvidence和LightClientAttackEvidence的检测和产生机制。接下来介绍一下evidence的执行机制。首先，节点在收到evidence消息后，会验证evidence是否合法以及是否超时。合法且未超时的evidence会持续在全网广播，确保全部节点都收到了该evidence或者evidence超时为止。evidence有两个超时参数：MaxAgeNumBlocks和MaxAgeDuration，超时的evidence将会被忽略。由于stake的质押撤回是需要时间的，因此只要evidence的超时时间小于质押撤回时间，就可以有机会惩罚恶意节点。同时节点中也记录了evidence pool，用于evidence的去重。evidence是在链上被提交的，proposer会优先打包evidence到block上，节点在验证完evidence的合法性之后，就可以对该block进行prevote和precommit的投票，从而最终提交该evidence。

---

*Originally published on [CaseyLuo](https://paragraph.com/@luoyx/tendermint-evidence)*
