ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Solana 乐观交易传播信号(Optimistic Transaction Propagation Signal)提案解析:确定性 Turbine 重传树的设计、接收端验证与攻击模型

Solana 乐观交易传播信号(Optimistic Transaction Propagation Signal)提案解析:确定性 Turbine 重传树的设计、接收端验证与攻击模型 Solana 乐观交易传播信号Optimistic Transaction Propagation Signal提案解析确定性 Turbine 重传树的设计、接收端验证与攻击模型【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solana本篇技术指南基于 Solana 官方设计提案文档 optimistic-transaction-propagation-signal.md 撰写。该提案着眼于提升 Solana 交易的乐观确认效率通过将 Turbine 重传树从随机生成改为确定性生成让每个接收节点都能仅凭本地信息推算出自己在整棵重传树中的位置、已获得多少质押权重的覆盖从而向共识层发出交易传播进度的乐观信号。读完本文你将掌握 Turbine 重传树的现状算法、确定性种子与 weighted_shuffle 的实现原理、接收端层级与质押占比的计算方法以及该提案面临的攻击模型与开放问题。一、背景Turbine 重传树的现状Solana 的区块数据shred通过名为 Turbine 的多层树形广播结构在网络中传播leader 生成 shred 后由根节点root逐层向叶子节点转发。当前实现中每个节点重传 shred 时其转发目标列表的构建方式记录在提案文档的 Current Retransmit behavior 一节中共分三步候选集合构建依次考虑 epoch 质押节点epoch staked nodes、TVU 对等节点tvu peers按联系信息与 shred 版本过滤、以及当前验证节点自身将三者拼接concatenating去重与过滤按 pubkey 去重去重时优先保留带联系信息contact info的条目随后仅保留具有联系信息的条目加权随机打乱将该列表按质押权重stake weight随机打乱然后向最多FANOUT个邻居neighbors和最多FANOUT个子节点children重传 shred。上述逻辑在源码中均有对应实现。在 turbine/src/cluster_nodes.rs 的get_nodes函数中候选节点集合由本节点自身 gossip 表可见的全部 TVU 对等节点 全部质押节点三部分拼接而成随后通过sorted_by_key(|node| Reverse((node.stake, node.pubkey)))稳定排序并按 pubkey 去重从而保证去重时优先保留带联系信息的条目。NodeId枚举ContactInfo(ContactInfo)与Pubkey(Pubkey)正是对有联系信息与仅有公钥无联系信息两类节点的建模。随机打乱与邻居/子节点选取则体现在ClusterNodesRetransmitStage::get_retransmit_peersturbine/src/cluster_nodes.rs它基于get_seeded_rng(slot_leader, shred)构造随机源对weighted_shuffle进行shuffle(mut rng)再调用get_retransmit_peers(fanout, self_index, nodes)计算当前节点应当转发的子节点列表。树形布局由注释给出turbine/src/cluster_nodes.rsroot : [0] 1st layer: [1, 2, ..., fanout] 2nd layer: [[fanout 1, ..., fanout * 2], [fanout * 2 1, ..., fanout * 3], ... [fanout * fanout 1, ..., fanout * (fanout 1)]] 3rd layer: ...即leader 将 shred 广播给 root 节点root 转发给第 1 层全部节点第 1 层每个节点再各自转发给第 2 层中属于自己邻域neighborhood的fanout个节点依此类推。get_retransmit_peers通过offset (index - 1) % fanout、anchor index - offset等索引运算精确定位邻域get_retransmit_parent则逆向计算父节点turbine/src/cluster_nodes.rs 中的test_get_retransmit_nodes用fanout 2、fanout 3的显式节点编号对父子关系进行了逐对断言验证。二、核心思路确定性重传树随机打乱意味着同一节点在不同时刻、不同网络状态下对同一 shred 的重传目标并不一致任何单个节点都无法预测还有哪些节点尚未收到数据也就无法对传播进度形成可靠判断。本提案的核心改动是将重传树的构建改为确定性deterministic计算。具体地weighted_shuffle将改用确定性种子当enable_deterministic_seed功能开启时种子由三元组shred slot、shred index、leader pubkey派生if enable_deterministic_seed(self.slot(), root_bank) { hashv([ self.slot().to_le_bytes(), self.index().to_le_bytes(), leader_pubkey.to_bytes(), ])这样任何持有相同输入slot、index、leader的节点都能独立复现出完全一致的打乱顺序与树结构。注意enable_deterministic_seed目前仅存在于本提案的设想中尚未在仓库源码中实现全文搜索仅在 docs/src/proposals/optimistic-transaction-propagation-signal.md 中出现因此以下描述均属提案设计。在确定性树中节点选取规则被重新定义首先只考虑 epoch 质押节点无论其是否具有联系信息甚至可能包含验证节点自身基于确定性 shred 种子对 epoch 质押节点做weighted_shuffle得到确定性的排列顺序定义neighbor_set从当前节点的邻居中最多选取FANOUT个定义child_set从当前节点的子节点中最多选取FANOUT个neighbor_set与child_set均需按联系信息过滤无法联系到的节点不参与实际转发定义epoch_set为neighbor_set与child_set的并集定义remaining_set为其余所有具有联系信息且不在epoch_set中的节点若epoch_set的大小不足2 * FANOUT则从remaining_set中随机补选最多2 * FANOUT - epoch_set.len个节点参与重传。这一设计的精妙之处在于确定性为主、随机为补确定性部分保证每个节点可复现、可推演而随机补选部分只负责在质押节点数量不足时兜底例如 epoch 初期质押节点较少不会破坏树主体结构的可预测性。三、确定性种子与 weighted_shuffle 的底层实现3.1 种子如何生成提案中的种子三元组slot、index、leader pubkey与仓库现有实现高度吻合。在 ledger/src/shred.rs 中ShredId::seed已经实现了几乎相同的哈希逻辑pub fn seed(self, leader: Pubkey) - [u8; 32] { let ShredId(slot, index, shred_type) self; hashv([ slot.to_le_bytes(), u8::from(*shred_type).to_le_bytes(), index.to_le_bytes(), AsRef::[u8]::as_ref(leader), ]) .to_bytes() }ShredId由(slot, index, shred_type)三元组构成与提案的(slot, index, leader)仅差一个shred_type字节。这一种子随后被 turbine/src/cluster_nodes.rs 的get_seeded_rng用于初始化ChaChaRngfn get_seeded_rng(leader: Pubkey, shred: ShredId) - ChaChaRng { let seed shred.seed(leader); ChaChaRng::from_seed(seed) }也就是说每个 shred 一个确定性随机源的机制已经存在于生产代码中提案只是把同样的思路从打乱所有节点推广到仅对质押节点做确定性排序并将其结果暴露给接收端用于进度推断。3.2 WeightedShuffle二叉索引树上的加权抽样weighted_shuffle模块位于 gossip/src/weighted_shuffle.rs其实现基于二叉索引树Fenwick Tree见文件头部注释维护未选中索引的质押权重前缀和核心保证有三条gossip/src/weighted_shuffle.rs返回的索引在[0, weights.len())内互不重复权重越高的索引越倾向于靠前出现且出现概率与其权重成正比零权重索引被单独打乱并排在最后。关键 API 包括WeightedShuffle::new(name, weights)构建二叉索引树负权重与溢出权重按零处理并上报指标gossip/src/weighted_shuffle.rsfirst(self, rng)等价于shuffle(mut rng).next()即加权抽取第一个索引gossip/src/weighted_shuffle.rsshuffle(mut self, rng)返回按权重依次抽样的迭代器每次通过search定位累积权重区间内的抽样点再用remove从树中移除已选权重gossip/src/weighted_shuffle.rsremove_index(mut self, index)在打乱前显式剔除某索引例如 slot leader 自身见 turbine/src/cluster_nodes.rs。由于WeightedShuffle对同一个确定性 RNG 输入会给出完全确定性的输出序列因此同一 (slot, index, leader) → 同一排序在数学上是严格可复现的——这正是接收端能够逆向推算自身位置的前提。四、接收端如何从确定性树中推算传播进度当某个验证节点收到一条被重传的 shred 时它可以按如下步骤判断自己处于整棵树的哪个位置以及多少质押权重已经在它之前完成了分发前置条件判断若当前验证节点不属于该 shred 所在 epoch 的质押节点集合则无法获得任何早期重传信息因为它根本不在确定性树中见下文信号桶一节计算确定性种子用 (slot, index, leader pubkey) 计算 deterministic shred seed重放确定性打乱对 epoch 质押节点集合运行确定性的epoch_stakesshuffle得到与发送端完全一致的排列定位自身在该排列中查找自身位于neighbor_set还是child_set确定自己在树中的层级累加前置质押计算当前及此前所有分发层级current and prior distribution levels中所有节点的质押总和——这个总和占 epoch 总质押的比例即在收到该 shred 时树中已有多少比例的质押权重被覆盖。4.1 层级与 root_distance 的对应关系仓库现有实现已经为层级判断提供了现成逻辑。在 turbine/src/cluster_nodes.rs 中root_distance的计算方式是let root_distance if self_index 0 { 0 } else if self_index fanout { 1 } else if self_index fanout.saturating_add(1).saturating_mul(fanout) { 2 } else { 3 // If changed, update MAX_NUM_TURBINE_HOPS. };即排列首位为 root距离 0随后fanout个为第 1 层再往后fanout * (fanout 1)个为第 2 层其余为第 3 层全局跳数上限由 turbine/src/cluster_nodes.rs 的MAX_NUM_TURBINE_HOPS 4约束。在 turbine/src/retransmit_stage.rs 中num_shreds_received与num_shreds_sent均为按MAX_NUM_TURBINE_HOPS长度统计的数组record函数turbine/src/retransmit_stage.rs分别对在距离 k 处收到与在距离 k 处转发的 shred 计数——说明距离度量已经贯穿于重传阶段的指标体系。提案中的neighbor_set/child_set即对应这一层级体系节点在排列中的索引越小越靠前距离 root 越近其收到数据意味着树中越多的前置分发已经完成。4.2 质押求和的边界考量在累加质押权重时提案专门指出两个容易出错的边界情况被跳过的节点质押总和可能包含此前分发层级中因缺少联系信息而被跳过的节点的质押。这些节点在确定性排列中占位但实际未收到数据若将其质押计入已覆盖会产生乐观偏差被过滤的自身当前节点原本位于发送端确定性打乱的排列中但因为缺少联系信息而被过滤、未实际收到转发随后它又从随机补选路径收到重传此时节点会误以为这次重传来自确定性树计算而非后续随机补选。提案认为这种情况良性的benign——因为当前节点会**低估underestimate**重传树中已处理的前置质押权重即信号偏保守不会导致过度乐观的确认。五、攻击模型分析确定性重传树让接收节点能够推断传播进度但也引入了一种新的信号滥用面恶意节点可以伪造传播进度信号。提案分别考虑了两种攻击leader 攻击第 0 层leader 除了按正常流程将 shred 分发到树中还额外把 shred或伪造的假 shred直接发送给第 2 层及以上的节点使这些节点误以为树中已有更大比例的转发已被处理。由于 leader 在系统内天然处于最可信的源头位置这种攻击最难防御。第 n 层节点攻击位于第 n 层的恶意节点将 shred 重传给第 n2 层及以上的节点同样会让接收者高估树的处理进度。这两类攻击的共同点是接收节点无法仅凭收到了数据就判断数据来自确定性路径还是恶意直传路径。这也直接引出了提案的开放问题接收节点是否应该尝试验证 shred 的来源确实是预期中的转发节点如果需要验证如何考虑 IP 欺骗spoofing成本与可行性该传播进度信息最终应如何被消费例如是作为乐观确认的辅助信号还是参与共识超时/确认阈值的计算从源码角度看turbine/src/cluster_nodes.rs 已经实现了get_retransmit_parent——它能在确定性树中逆向查出任一节点的父节点同时明确注释非质押节点位置不确定因此返回None。这一函数正是验证来源是否来自预期父节点所需的基础能力但提案将其作为是否应当验证的开放问题提出说明在工程取舍上尚未定论。六、信号桶传播信号的实践分层提案在 Notes 一节给出信号的分桶设计明确不同位置的节点能够发出不同粒度的信号当前 leader在发出广播broadcast时即可发出第 1 层已覆盖的信号第 1 层节点收到 shred 时可发出第 1 层已覆盖的信号发出重传retransmit时可发出第 1 层 第 2 层子集已覆盖的信号第 2 层节点收到 shred 时可发出第 2 层已覆盖的信号发出重传时可发出第 2 层 第 3 层子集已覆盖的信号非质押节点不属于 epoch 质押节点集合无法发出任何信号。可以看到信号粒度随节点在树中的深度增加而变粗层级越深节点能够确认的传播范围越大但信号到达共识决策点的时间也越晚。这一分层设计让共识层可以根据信号来源的层级对不同强度的乐观传播确认加以区分利用。七、小结与展望本提案通过将 Turbine 重传树从随机化改造为以 (slot, index, leader pubkey) 为种子的确定性加权打乱赋予网络中每个质押节点一项新能力仅凭收到的 shred 与本地 epoch 质押数据即可推算出自己在重传树中的位置以及已被覆盖的质押权重比例从而为交易的乐观确认提供可验证、可分层的传播进度信号。从仓库现有实现看提案的诸多基础设施已经就绪确定性种子生成ledger/src/shred.rs、ChaChaRng 种子化turbine/src/cluster_nodes.rs、加权打乱的二叉索引树实现gossip/src/weighted_shuffle.rs、树形层级与父/子节点计算turbine/src/cluster_nodes.rs以及按距离分桶的统计指标turbine/src/retransmit_stage.rs。enable_deterministic_seed功能开关本身尚未落地攻击防护与信号消费方式也仍是开放问题——但作为设计蓝图它为 Solana 进一步压缩乐观确认延迟、提升交易传播的可观测性指明了一条清晰的技术路径。【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solana创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表