双签(equivocation)
双签(equivocation)是指一个出块者在同一个父区块上签署了两个不同的区块。这样一来,不同节点可能先看到不同的区块,网络可能在一段时间内分裂。ZooBC 从三个方面处理这一问题:诚实节点即使在崩溃之后也绝不会这样做;任何看到这样两个区块的已注册节点都可以用一份 EquivocationReport 在链上证明它;而该出块者会被记一次错过轮次,并随之损失收入和分数。
什么算作双签
当一个节点被抽中出块时,它会在当前链顶(即它的父区块)之上构建一个区块。双签是指在同一个父区块上签署两个区块头不同的区块。迟到的区块不算双签:它只是为其分支增加较少的权重(见 分叉选择与累计难度)。在不同高度出块也不算双签;每个高度都有自己的父区块。
诚实的出块者绝不双签
出块者会记住它针对每个父区块签署过的区块,并把这条记录也保存在磁盘上,因此重启不会让它忘记。如果它针对同一个父区块再次被抽中,它会重新发送已经签署过的区块,而不是产出一个新区块。
有一个有意设置的例外。超过恢复限制,即父区块之后 3,600 秒,已经停滞的链必须能够重新启动。此时出块者可以为该父区块签署一个新的区块,这不会被记罚,之后它会重新发送这个区块。同理,如果一对区块的时间戳跨越恢复限制(恰好其中一个比父区块晚 3,600 秒以上),这是停滞链的恢复,而不是双签。
检测
一个节点若从同一个已注册出块者那里收到同一父区块上的两个有效签名的区块头,就把它们视为证据:
- 它将该出块者记录为已证实的撒谎者,从而把它列入对等节点黑名单并断开连接,除非这样做会使本节点与网络隔绝;
- 它针对每个父区块和出块者提交一份 EquivocationReport;
- 它仍照常把两个区块都交给验证;由分叉选择决定留下哪一个,在完全平局时,链顶哈希较小的分支在每个节点上都会胜出。
EquivocationReport
这份报告(交易类型 60)携带证据本身:两个已签名的区块头,每个后面跟着出块者的 64 字节签名。区块头为 284 字节时,交易体为 704 字节:4 字节长度、区块头 1、签名 1、4 字节长度、区块头 2、签名 2。
链会按以下顺序进行十三项检查:
- 报告类型处于启用状态;
- 手续费恰好为 0,因为举报是已注册节点的职责;
- 交易体可以解析,并且每个区块头的大小都是已签名区块头的大小:204 字节,带种子证明时为 284 字节;
- 两个区块头彼此不同;
- 字节偏移量 76 处的出块者密钥在两者中相同;
- 偏移量 172 处的父区块哈希在两者中相同;
- 两个签名在该出块者密钥下都能验证通过;
- 父区块是本链上的区块;
- 这一对区块头没有跨越一小时的恢复限制;
- 报告到达的时间不晚于双签高度之后 720 个区块;
- 出块者是已注册节点;
- 举报者是已注册节点;
- 该出块者尚未因该高度被记罚。
仅仅声称看到了第二个区块证明不了任何事;两个签名才能证明。这不需要席位投票,因为任何人都可以检查签名。
代价
一份有效的报告会给该出块者记一次错过轮次,每个出块者每个高度只记一次。根据为 0.5.8 版本确定的规则,被证实的双签还会使该节点在其下一个自己的区块之前处于缺席状态:没有 coinbase、手续费或长效池份额,参与分数也会下降。连续错过四个轮次会使节点被暂停。见 错过轮次、暂停与除名。
没有任何余额变动。举报者不会获得报酬,出块者的质押也不会被拿走任何东西:ZBC 从不销毁(见 ZBC 从不销毁)。