基于DAG的共识(Narwhal/Bullshark)核心技术疑问
背景回顾
在Tendermint类BFT共识中,每轮仅由指定领导者提议单块,节点无需处理重复交易问题;但传统区块链内存池存在核心问题:
提交至某一验证节点的交易会被gossip至所有其他节点,这会导致细粒度的重复传输:多数交易先由内存池共享,随后矿工/领导者创建块时会再次共享这些交易。
Narwhal为解决该问题,采用广播块而非单交易的优化:领导者仅提议块哈希,内存池层提供完整性保护的块内容。而Bullshark这类共识中,领导者块仅作为锚点,还需通过确定性规则提交锚点外的其他块。
1. 如何避免同轮不同块中的重复交易?
首先,所有交易通过唯一哈希标识,验证节点会维护一个全局的「已确认/已打包交易集合」,在打包块前,节点会过滤掉内存池中已被其他节点块包含的交易。
针对恶意节点提交重复交易的情况:
- 节点在接收块时,会验证块内交易的哈希是否已存在于已确认集合,若存在则标记该块为无效,不会纳入共识流程;
- 若恶意节点持续打包重复交易,在PoS机制下,其stake会被削减(Slashing),以此形成威慑;
- Narwhal的内存池层会通过轻量gossip同步「已打包交易哈希列表」,节点打包前会基于该列表做前置过滤,从源头减少重复交易的块生成。
即便有漏网的重复交易块被提交,执行层在执行交易时也会再次去重,仅执行一次重复交易,避免状态不一致,但确实会浪费少量块空间——不过这种情况在有Slashing机制约束下会被有效抑制。
2. 锚点间块的确定性排序规则示例
以Bullshark的实际规则为例,假设锚点为轮次N的领导者块A和轮次N+3的领导者块B,中间有4个非领导者块:Block X(节点ID:0x05,引用块A)、Block Y(节点ID:0x02,无引用)、Block Z(节点ID:0x05,引用Block X)、Block W(节点ID:0x03,引用块A)。
排序规则分为两步:
- 拓扑排序保证依赖顺序:先处理有依赖关系的块,比如Block X依赖A,Z依赖X,所以顺序为A → X → Z;Block W依赖A,所以A → W;Block Y无依赖,直接排在锚点A之后。
- 无依赖块按确定性规则排序:对于无依赖或同层级的块,按节点ID的字典序排列。因此Block Y(0x02)先于W(0x03),W先于X(0x05)。
最终锚点A到B之间的块排序为:A → Y → W → X → Z → B
另一种常见规则是节点权重(Stake占比)+ 块哈希字典序:无依赖块先按节点Stake占比从高到低排,占比相同则按块哈希升序排,确保所有节点得到完全一致的排序结果。
3. 验证节点越多,系统吞吐量越高吗?
并非如此,吞吐量的提升存在边际瓶颈:
- 并行打包的收益上限:更多节点确实能在每轮生成更多块,但当节点数量超过阈值后,网络带宽开销会急剧上升——每个节点需要接收并验证其他所有节点的块,带宽会成为核心瓶颈;
- 计算与共识开销:节点越多,共识阶段需要处理的块验证、排序逻辑越复杂,计算资源的消耗会抵消并行打包的收益;
- 交易重复率上升:节点数量增加,恶意节点打包重复交易的概率提升,即便有去重机制,也会浪费系统资源;
- 最优节点规模:存在一个最优节点数量区间,在该区间内,并行打包的收益大于网络、计算开销,吞吐量随节点数量上升而提升;超过该区间后,吞吐量反而会下降。
Narwhal/Bullshark的吞吐量提升核心是块的并行打包与流水线处理,而非单纯依赖节点数量的增加。
内容的提问来源于stack exchange,提问作者Fieldza555

