59 lines
4.3 KiB
Markdown
59 lines
4.3 KiB
Markdown
![]() |
---
|
|||
|
title: 维修服务
|
|||
|
---
|
|||
|
|
|||
|
## 维修服务
|
|||
|
|
|||
|
修复服务负责检索未能通过Turbine等主要通信协议传送的遗失碎片。 它负责管理下面`维修协议`部分中描述的协议。
|
|||
|
|
|||
|
## 挑战。
|
|||
|
|
|||
|
1\) 验证节点可能会因为网络故障而无法接收特定的碎片。
|
|||
|
|
|||
|
2\) 考虑一个场景,blockstore包含一组插槽{1, 3, 5}。 那么Blockstore接收到一些插槽7的碎片,其中对于每一个碎片b,b.parent == 6,那么父子关系6 -> 7就存储在blockstore中。 但是,没有办法将这些插槽链到Blockstore中任何一个现有的库中,因此,`碎片修复`协议不会修复这些插槽。 如果这些插槽恰好是主链的一部分,这将停止该节点上的重放进度。
|
|||
|
|
|||
|
## 修复相关基元
|
|||
|
|
|||
|
纪元插槽: 每个验证节点都在Gossip上分别广播`纪元插槽`的各个部分。
|
|||
|
|
|||
|
- `储藏`:一个以纪元为单位的所有已完成插槽的压缩集。
|
|||
|
- `缓存`:最新的`N`个已完成的插槽的运行长度编码(RLE),从某个插槽`M`开始,其中`N`是一个MTU大小的数据包所能容纳的插槽数。
|
|||
|
|
|||
|
gossip中的`Epoch Slots`每当验证节点收到一个在epoch内的完整插槽时,就会更新。 已完成的插槽由blockstore检测,并通过通道发送到维修服务。 需要注意的是,我们知道当一个插槽`X`完成的时候,包含插槽`X`的纪元必须存在纪元时间表,因为WindowService会拒绝未确认的纪元的碎片。
|
|||
|
|
|||
|
每完成一个`N/2`插槽,最老的`N/2`插槽就会从`缓存`移到`stash`中。 RLE的基值`M`也要更新。
|
|||
|
|
|||
|
## 修复请求协议
|
|||
|
|
|||
|
修复协议为进步Blockstore的分叉结构做了最好的尝试。
|
|||
|
|
|||
|
不同的协议策略来解决上述难题。
|
|||
|
|
|||
|
1. Shred Repair\(解决挑战\#1\):这是最基本的修复协议,目的是检测和填补账本中的 "漏洞"。 Blockstore会跟踪最新的根插槽。 然后,RepairService会从根插槽开始定期迭代blockstore中的每一个分叉,向验证节点发送修复请求,以获取任何缺失的碎片。 它每次迭代最多会发送一些`N`修复请求。 碎片修复应该根据领导者的分叉重量来优先修复分叉。 验证节点应该只向在其EpochSlots中标记该插槽已完成的验证节点发送修复请求。 验证节点应该优先修复他们负责通过涡轮重传的每个插槽中的碎片。 验证节点可以计算出他们负责重传的碎片,因为turbine的种子是基于leader id、slot和碎片 index的。
|
|||
|
|
|||
|
注意:验证节点只接受当前可验证的epoch (验证节点有领袖时间表的epoch) 内的碎纸片。
|
|||
|
|
|||
|
2. Preemptive Slot Repair\(解决挑战 \#2\):这个协议的目标是发现 "孤儿 "插槽的链路关系,这些插槽目前没有链到任何已知的分叉。 碎片修复应该根据领导者的分叉权重来优先修复孤儿插槽。
|
|||
|
|
|||
|
- Blockstore将在一个单独的列族中跟踪 "孤儿 "插槽的集合。
|
|||
|
- 修复服务将定期为blockstore中的每个孤儿提出`Orphan`请求。
|
|||
|
|
|||
|
`Orphan(orphan)`请求--`orphan`是请求者想知道的孤儿插槽的父母`Orphan(orphan)`响应--请求的`orphan`的前`N`个父母的最高分叉量。
|
|||
|
|
|||
|
在收到响应`p`时,其中`p`是父插槽中的一些碎片,验证节点将:
|
|||
|
|
|||
|
- 如果它还不存在,那么就在区块存储中为`p.slot`插入一个空的`SlotMeta`。
|
|||
|
- 如果`p.slot`确实存在,根据`父辈`更新`p`的父插槽。
|
|||
|
|
|||
|
注意:一旦这些空插槽被添加到区块存储中,`Shred Repair`协议应该尝试填补这些插槽。
|
|||
|
|
|||
|
注意:验证节点只会接受包含当前可验证的epoch (验证节点有领导时间表的epoch) 内的碎片的响应。
|
|||
|
|
|||
|
验证节点应该尝试将孤儿请求发送给在其EpochSlots中已将该孤儿标记为已完成的验证节点。 如果不存在这样的验证节点,那么就以利害关系加权的方式随机选择一个验证节点。
|
|||
|
|
|||
|
## 修复响应协议
|
|||
|
|
|||
|
当验证节点收到一个碎片`S`的请求时,如果他们有碎片,他们就会响应。
|
|||
|
|
|||
|
当验证节点通过修复响应收到碎纸片时,他们会检查`EpochSlots`,看看是否有 <= `1/3` 的网络已经将这个插槽标记为完成。 如果是这样,他们就会通过其相关的涡轮路径重新提交这个碎片,但前提是这个验证节点之前没有重传过这个碎片。
|