Solana 区块确认机制剖析:从链上投票设计难题到 Tower BFT 最终性
Solana 区块确认机制剖析从链上投票设计难题到 Tower BFT 最终性【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solanaSolana 的“确认”Confirmation回答的是一个根本问题一个节点说“我执行到了这里”其他节点凭什么相信它执行得既完整又无双重支付本文围绕docs/src/proposals/block-confirmation.md这一设计提案展开完整梳理区块确认机制中投票的双重语义、当前设计的三大缺陷、基于NewBlock交易的链上投票方案以及最终由 Tower BFT 实现的最终性与奖励发放逻辑并结合仓库中 vote 程序与共识模块的实际源码帮助读者理解这套机制从提案到落地的完整脉络。投票的双重语义合法性证明与分叉选择理解区块确认的前提是理解 Solana 中一次投票vote同时承担的两个职责。根据提案文档 block-confirmation.md合法性证明投票表示节点认为账本ledger从创世到所投 PoH hash 为止的内容是有效的分叉选择由于同一高度可能存在多个合法分叉fork投票同时也是对特定分叉的排他性支持。提案文档明确声明前者是“区块确认”主题后者分叉选择则交由 Tower BFT 描述。这个分工很重要——读后续内容时应始终记住确认机制关心的是“我如何证明我执行过这段账本”而共识关心的是“全网如何收敛到同一条链”。当前设计链下投票与 Vote 账户提案文档描述了“Current Design”——即文档撰写时的投票形态验证者validator首先注册一个账户之后把投票发送到该账户投票包含所投区块的tick 高度tick height账户内存储最近32 个最高高度的投票记录。这里有一个值得注意的演进痕迹早期投票只携带高度而非完整 PoH hash这与后文“Problems”一节中“投票选票不包含 PoH hash”的批评直接对应——提案正是在推动投票从“我观测到了某高度”升级为“我验证到了某个具体的 PoH hash”。从源码结构看这一设计在今天的仓库中已经演进为成熟的 vote 程序账户状态定义在 vote_state其中MAX_RECENT_VOTES常量将最近投票数固化为 16 条第 1211 行附近即“账户存储最近 N 条投票”这一核心数据结构只是 N 从提案阶段的 32 收敛到了 16。投票事务的构造逻辑位于 vote_transaction.rs投票指令的执行与 lockout 更新则集中在 vote_processor.rs。当前设计的三大缺陷为什么需要重构提案文档的 “Problems” 一节是全文的技术核心之一它指出了旧式投票无法构成“确认证据”的三个原因投票不可被外部发现。只有验证者自己知道自己的投票存在哪个账户。任何需要投票数据的组件——例如计算确认时间confirmation time的模块——都不得不“烘焙”进验证者代码内部验证者代码需要向 bank 查询所有由 vote 程序拥有的账户来遍历投票。这意味着链上数据实际上“链下化”了外部审计者无法独立复核。投票选票不包含 PoH hash。验证者只是在声明“我在某个高度观测到了一个区块”但没有指明是哪个区块。多个分叉可以在同一高度并存没有 hash 就没有唯一指向。投票选票不包含 bank 状态哈希。缺少状态哈希就没有证据表明该验证者真正执行过这些交易、验证过不存在双重支付。这恰恰是“确认”一词的实质含义不只是“我看到了区块”而是“我计算并验证了账本状态”。这三条批评共同指向同一个目标投票必须成为链上可发现、包含 PoH hash 与状态证据、可被独立审计的数据。后面的新设计全部围绕这个目标展开。提议设计以 NewBlock 交易为载体的链上投票无跨区块状态的最初版本提案的 “Proposed Design” 给出了一个不依赖跨区块状态No Cross-block State的最初方案其工作流程如下区块产生时刻leader 向账本写入一笔NewBlock交易其中附带一定数量的 token代表验证奖励。从本质上说这是一笔“增量式多签交易”incremental multisigtoken 从矿池mining pool流向各验证者只有凑齐足够签名投票才会最终分发账户空间预分配NewBlock账户只分配恰好容纳“达成超级多数supermajority所需票数”的空间验证者观察到NewBlock交易后可选择提交一笔投票投票中包含自己账本状态bank state的 hash——这就补上了第三节缺失的“执行证据”当账户集齐足够票数vote 程序将 token 分发给各验证者该账户随后被删除余额为零、可回收。这个设计有两个精巧之处其一投票与奖励发放绑定在同一账户生命周期内投票既是确认凭证又是奖励凭证其二账户“凑齐超级多数即销毁”的特性让每个区块的确认状态天然自包含不需要额外的全局状态。记录确认时间提案指出bank 需要感知 vote 程序的存在在每笔交易执行后检查它是否为投票交易若是则检查对应账户状态如果该笔交易使账户达到超级多数bank 应当记录自NewBlock交易提交以来经过的时间——这就是“确认时间”confirmation time的度量方式从区块诞生到达成超级多数之间的时延。从源码结构看确认时间度量在今天依然存在于验证者的承诺服务中commitment_service.rs 负责基于观察到的投票持续更新最终性统计commitment相关逻辑还下沉到了 runtime/src/commitment.rs 与 SDK 层的 commitment_config.rs形成从“投票达到超级多数”到“对外报告最终性”的完整链路。提案中“bank 感知 vote 程序”的设想可以推断已在实现中演化为这套更模块化的承诺追踪机制。最终性与奖励发放交给 Tower BFT提案的 “Finality and Payouts” 一节做了一个关键决策奖励发放不与单个区块的超级多数绑定而是推迟到投票栈达到一定深度、回滚在经济上不再可行之时。这一决策直接引出了 Tower BFT——Solana 实际采用的分叉选择算法。Tower BFT 的核心参数与机制恰好为区块确认提供了“可计算的回滚成本”Lockout 指数增长投票塔Vote Tower中每次新投票都会使栈内既有投票的 lockout 翻倍起始 lockout 为 2 个 slot每加一层深度 lockout 乘以 2到 32 层达到132后从队列尾部FIFO出队——出队即触发奖励发放。这与提案中“账户集齐超级多数即分发 token”的设想形成呼应奖励由“深度”而非“单点多数”触发回滚成本可计算Economic Finality 定义为回滚某分叉将损失的全部奖励加上 lockout 指数增长带来的机会成本。这满足提案对“确认证据”的隐含要求——确认强度是可以量化的ASIC 抗性投票与 lockout 按指数增长而 PoH ASIC 加速只是线性的。10 层投票对应 1024 slot 的 lockout攻击者需要约 102 倍的 ASIC 速度20 层则需要超过 5 万倍。这从经济上解释了为什么“达到一定深度后回滚不可行”——提案中“postponed until rollback is not economically feasible”这句话的工程依据Threshold Check为避免验证者在网络分区时把自己锁死在错误分叉上投票前需模拟投票塔状态检查阈值深度硬编码为 8处的投票块T若T及其后代集合上的投票 stake 总和达到全网 2/3 以上才提交投票。这正是“超级多数”概念在验证者本地的落地形式。提案最后指出一个实现后果由于 Tower BFT 需要追踪投票塔这一跨区块状态vote 程序必须引用一个全局 Tower 账户。也就是说最初的“NewBlock 无跨区块状态”方案最终被“全局 Tower 每区块投票账户”的混合形态取代——这解释了为何现代实现中既有 per-validator 的 vote 账户存储近期投票与 lockout又有共识层维护的投票进度结构。仓库中 progress_map.rs 与 vote_stake_tracker.rs 维护的全网投票权重追踪正是“各分叉上投票 stake 加权”这一 Tower BFT 分叉选择规则的实现载体。设计挑战链上投票的两难提案的 “Challenges” 一节诚实地记录了两个未决难题它们是理解整个设计取舍的关键NewBlock 账户空间分配难题链上投票最难的部分是预先计算NewBlock账户需要多大空间决定因素是两个变量活跃验证者集合active set及其 stake。文档给出两条路径若以NewBlock提交时刻计算活跃集合则需容纳的验证者数量已知空间可静态分配若允许新加入的验证者对旧区块投票则需要动态分配空间——链上存储无法轻松支持这是被放弃的方向。由此可以推断最终实现选择了“冻结活跃集合”的路线奖励只发放给区块产生时的在册验证者。Stake 的取值时点同理若 leader 在NewBlock时刻缓存各验证者的 stakevote 程序处理投票时就不必再访问 bank否则 stake 将“浮动”到投票提交时刻。文档指出了一个微妙问题验证者甚至可以引用自己的质押账户但那样拿到的是当前账户值而非最近一个已最终化 bank 状态中的账户值——而 bank 当时并不提供按时间点查询历史账户状态的能力。投票对历史区块的蕴含文档最后提出一个语义问题对某一高度的投票是否蕴含对该分叉上所有更低高度区块的投票若是则需要一种机制去查找所有尚未达到超级多数的区块账户并逐一补票若否验证者必须对每个想拿奖励的区块显式发送投票——交易开销线性膨胀。这个问题在 Tower BFT 中得到了优雅的消解投票塔天然是“祖先链式”的——新投票隐含确认其所有祖先lockout 沿祖先链向上叠加因此无需逐区块显式补票。这也体现了从 block-confirmation 提案到 Tower BFT 的实现演化最初试图用“每区块一个自包含账户”解决确认问题最终收敛为“每验证者一个投票塔 全局 stake 加权”的架构。关键参数速查综合提案文档与 Tower BFT 设计文档区块确认相关的关键参数如下便于检索引用参数取值来源旧式设计账户存储的投票高度数32block-confirmation.md现行 vote 账户MAX_RECENT_VOTES16vote_stateTower 起始 lockout2 个 slottower-bft.mdlockout 增长速度每层翻倍2x同上出队深度触发奖励32 层同上Threshold check 深度8同上阈值处所需集群承诺≥ 2/3 stake同上分叉切换阈值其他分叉投票 38%同上小结block-confirmation.md 的价值在于它完整记录了 Solana 确认机制的设计推理链旧式链下投票无法提供“执行证据”NewBlock多签交易方案把确认与奖励绑定在单一账户生命周期中而 Tower BFT 最终以指数增长的 lockout 把“确认强度”变成了可计算的经济学量——达到足够投票深度后回滚的代价超过收益区块即被视为最终。对于想要深入源码的读者建议沿 programs/vote/src/vote_state/mod.rs账户状态与指令处理、core/src/consensus投票塔与分叉选择、core/src/commitment_service.rs确认时间度量三条线索继续阅读。【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solana创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考