跳到主要内容

容错性与最终确定性

BFT 保证

Savitri 共识采用 BFT(拜占庭容错)投票协议,法定人数阈值为 2f+1(67%)。

容错能力

总节点数(n)最大拜占庭节点数(f)所需法定人数
302
514
725
1037
15411

公式:f = floor((n-1) / 3),法定人数 = 2f + 1

安全性

只有当产生包含 2f+1 个验证者签名的区块接受证书(BAC)时,区块才会被最终确定。这保证了:

  • 同一高度不会存在冲突区块被最终确定
  • 一旦颁发 BAC,不会发生回滚(确定性最终性,非概率性)
  • 拜占庭节点无法在没有法定人数参与的情况下伪造证书

活性

只要有 n - f 个诚实节点在线,网络便可持续生产区块:

  • 提议者轮换:每生产 50 个区块后,提议者退位,防止单点故障
  • 选举看门狗:若 60 秒内无区块进展,重新触发选举
  • 渐进式法定人数放宽:连续选举失败 3 次以上后,最低候选人数降至 2

DAG 结构

BlockHeader 支持多父节点 DAG 结构,以实现并发区块生产:

pub struct BlockHeader {
pub parent_hash: Vec<u8>, // 主父节点(向后兼容)
pub parent_hashes: Vec<Vec<u8>>, // DAG 的额外父节点
// ...
}

冲突检测

ConflictDetector 负责识别:

  • 双花冲突:同一 UTXO 在多个分支中被引用
  • 状态冲突:冲突的状态转换
  • 分叉检测:不同提议者在同一高度生产多个区块

冲突解决

检测到冲突时:

  1. 选择具有更高累计 PoU 分数的分支
  2. 回滚冲突交易
  3. 重新应用失败分支中的非冲突交易

感知群组的共识

群组构成

主节点将轻节点组织为群组:

  1. 按 PoU 分数对轻节点排序
  2. 分配至大小为 group_size 的群组(开发环境 3,生产环境 7)
  3. 通过 gossipsub 发布群组分配
  4. 基于纪元(而非系统时钟)的确定性群组 ID

群组内选举

在每个群组内:

  1. 成员共享 PoU 分数
  2. PoU 分数最高者成为提议者(peer_id 作为平局打破者)
  3. 至少需要 (total+1)/2 个候选人
  4. 失败 3 次以上后:放宽至最少 2 个候选人

区块接受

  1. 群组提议者生产区块
  2. 群组成员验证并签名
  3. 产生包含 2f+1 个签名的 BAC
  4. 主节点验证 BAC 并最终确定

恢复机制

选举恢复

机制触发条件操作
看门狗定时器60 秒无区块重新触发 PoU + 选举
渐进式放宽失败 3 次以上降低法定人数至 2
提议者轮换50 个区块退位,重新选举
立即重新选举群组重新初始化启动 PoU + 选举任务

节点恢复

机制触发条件操作
Gossipsub 保活60 秒间隔发布 PoU 分数
网格恢复看门狗60 秒无网格重新拨号群组节点
SlowPeer 断开队列已满断开并重连
Nonce 重置本地 > 存储 + 200重置为存储 nonce

群组恢复

群组重新初始化时:

  1. 保留持续成员的 PoU 分数
  2. 新成员以默认分数起步
  3. 重置 intra_group_started 标志
  4. 立即启动 PoU + 选举(不等待定时器)

罚没(生产环境)

违规行为处罚冷却期
双重投票50% 质押
下线10% 质押逐步
无效提案25% 质押

罚没在开发网络禁用,在主网启用config/production.toml)。

共识配置

参数开发环境生产环境
超时时间15 秒10 秒
最大轮数510
法定人数阈值0.670.67
BFT 优化禁用启用
罚没禁用启用
出块时间2 秒5 秒
群组大小37