---
title: 维修服务
---

## 维修服务

修复服务负责检索未能通过Turbine等主要通信协议传送的遗失碎片。 它负责管理下面`维修协议`部分中描述的协议。

## 挑战。

1\) 验证节点可能会因为网络故障而无法接收特定的碎片。

2\) 考虑一个场景，blockstore包含一组插槽{1, 3, 5}。 那么Blockstore接收到一些插槽7的碎片，其中对于每一个碎片b，b.parent == 6，那么父子关系6 -&gt; 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` 的网络已经将这个插槽标记为完成。 如果是这样，他们就会通过其相关的涡轮路径重新提交这个碎片，但前提是这个验证节点之前没有重传过这个碎片。
