Skip to content

Commit 448cc8c

Browse files
authored
Merge pull request #31 from YoubetDao/feature/cl-architecture
feat: Add cl architecture translation
2 parents 5f47839 + 23ebce2 commit 448cc8c

File tree

3 files changed

+248
-1
lines changed

3 files changed

+248
-1
lines changed

src/SUMMARY.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
- [区块构建](./block-building.md)
1414

1515
# 共识层
16-
1. [概览](./cl-overview.md)
16+
- [概述](./cl-overview.md)
17+
- [客户端架构](./cl-architecture.md)

src/cl-architecture.md

+245
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
# 共识层(CL)架构
2+
3+
> 许多区块链共识协议都是*可分叉的*。可分叉的链使用分叉选择规则,有时会发生重组。
4+
>
5+
> 以太坊的共识协议结合了两个独立的共识协议。_LMD GHOST_ 本质上提供活性。_Casper FFG_ 提供最终性。这两者共同被称为 _Gasper_
6+
>
7+
> 在一个*活性*协议中,好的事情总会发生。在一个*安全*协议中,坏的事情永远不会发生。没有任何实用的协议能够始终保持安全性的同时又始终保持活性。
8+
9+
## 分叉选择机制
10+
11+
[BFT](BFT)中所述,由于各种原因 - 比如网络延迟、中断、消息乱序或恶意行为 — 网络中的节点可能会对网络状态有不同的认知。最终,我们希望每个诚实节点都能就一个相同的、线性的历史记录和系统状态的共同视图达成一致。协议的分叉选择规则正是帮助实现这种共识的机制。
12+
13+
#### 区块树
14+
15+
基于区块树和节点对网络本地视图的决策标准,分叉选择规则旨在选择最有可能成为最终规范链的分支。它选择在节点收敛到共同视图时最不可能被剪枝的分支。
16+
17+
<a id="img_blocktree"></a>
18+
19+
<figure class="diagram" style="text-align:center; width:95%">
20+
21+
![Diagram for Block Tree](../images/cl/blocktree.svg)
22+
23+
_分叉选择规则从候选区块中选择一个头区块。头区块标识了一条从创世区块开始的唯一线性区块链。_
24+
25+
</figcaption>
26+
</figure>
27+
28+
#### 分叉选择规则
29+
30+
分叉选择规则通过选择分支末端的区块(称为头区块)来隐式地选择一个分支。对于任何正确的节点来说,任何分叉选择的首要规则是:被选中的区块必须根据协议规则是有效的,并且它的所有祖先区块也必须是有效的。任何无效区块都会被忽略,基于无效区块构建的区块也是无效的。
31+
32+
以下是几个不同分叉选择规则的例子:
33+
34+
- **工作量证明(Proof-of-work)**:在以太坊和比特币中,使用"最重链规则"(有时被称为"最长链",但这种说法并不严格准确)。头区块是累积"工作量"最多的链的末端区块。
35+
> 需要注意的是,与普遍的认知相反,以太坊的工作量证明协议[并没有使用](https://ethereum.stackexchange.com/questions/38121/why-did-ethereum-abandon-the-ghost-protocol/50693#50693)任何形式的 GHOST 作为分叉选择规则。这个误解一直存在,可能是因为[以太坊白皮书](https://ethereum.org/en/whitepaper/#modified-ghost-implementation)的缘故。最终当 Vitalik 被问到这个问题时,他确认虽然在 PoW 下曾计划使用 GHOST,但由于担心某些未明确的攻击而从未实施。最重链规则更简单且经过充分测试,运行良好。
36+
- **Casper FFG (权益证明)**:在以太坊的 PoS Casper FFG 协议中,分叉选择规则是"遵循包含**最高高度**已证明检查点的链",并且永远不会回滚已最终确定的区块。
37+
- **LMD GHOST (权益证明)**:在以太坊的 PoS LMD GHOST 协议中,分叉选择规则是选择"最贪婪最重可观察子树"。这涉及计算验证者对区块及其子孙区块的累积投票。它同样也应用 Casper FFG 的规则。
38+
39+
这些分叉选择规则都会为区块分配一个数值分数。得分最高的区块即为头区块。目标是让所有正确的节点在看到某个区块时,都会认同它是头区块并跟随它的分支。这样,所有正确的节点最终都会就一条从创世区块开始的规范链达成一致。
40+
41+
#### 重组和回滚
42+
43+
当节点接收到新的投票(在权益证明中包括对区块的新投票)时,它会根据这些新信息重新评估分叉选择规则。通常情况下,新区块会是当前头区块的子区块,并成为新的头区块。
44+
45+
然而,有时新区块可能是区块树中另一个区块的后代。如果节点没有这个新区块的父区块,它会向其对等节点请求该区块以及其他缺失的区块。
46+
47+
在更新后的区块树上运行分叉选择规则可能会显示,新的头区块位于与之前头区块不同的分支上。当这种情况发生时,节点必须执行重组(reorganisation)。这意味着它将移除(回滚)之前包含的区块,并采用新头区块所在分支上的区块。
48+
49+
例如,如果一个节点的链上有区块 $A, B, D, E,$ 和 $F$,并且它将 $F$ 视为头区块,它知道有区块 $C$ 的存在但在其当前的链视图中并不出现;该区块位于侧分支上。
50+
51+
<a id="img_reorg0"></a>
52+
53+
<figure class="diagram" style="text-align:center">
54+
55+
![Diagram for Reorg-0](../../images/cl/reorg-0.svg)
56+
57+
<figcaption>
58+
59+
_此时,节点认为区块 $F$ 是最佳头区块,因此它的链是区块 $[A \leftarrow B \leftarrow D \leftarrow E \leftarrow F]$_
60+
61+
</figcaption>
62+
</figure>
63+
64+
当节点随后收到构建在区块 $C$ 上而不是当前头区块 $F$ 上的区块 $G$ 时,它必须决定是否应该将 $G$ 作为新的头区块。举例来说,如果分叉选择规则表明 $G$ 是更好的头区块,节点将回滚区块 $D、E$ 和 $F$。它会将这些区块从链上移除,就像从未收到过它们一样,并回退到区块 $B$ 之后的状态。
65+
66+
然后,节点会将区块 $C$ 和 $G$ 添加到它的链上并处理它们。在这次重组之后,节点的链将包含 $A、B、C$ 和 $G$。
67+
68+
<a id="img_reorg1"></a>
69+
70+
<figure class="diagram" style="text-align:center">
71+
72+
![Diagram for Reorg-1](../../images/cl/reorg-1.svg)
73+
74+
<figcaption>
75+
76+
_此时,节点认为区块 $G$ 是最佳头区块,因此它的链必须改变为区块 $[A \leftarrow B \leftarrow C \leftarrow G]$_
77+
78+
</figcaption>
79+
</figure>
80+
81+
后来,可能出现一个区块 $H$,它构建在区块 $F$ 上,分叉选择规则说 $H$ 应该是新的头区块,节点将再次重组,回滚到区块 $B$ 并重新播放 $H$ 分支上的区块。
82+
83+
由于网络延迟,一两个区块的短重组是很常见的。除非链遭受攻击,或者分叉选择规则及其实现存在漏洞,否则较长的重组应该很少发生。
84+
85+
### 安全性和活性
86+
87+
在共识机制中,有两个关键概念:安全性和活性。
88+
89+
**安全性**意味着"坏事永远不会发生",比如防止双重支付或确认冲突的检查点。它确保一致性,这意味着所有诚实节点应该始终对区块链的状态达成一致。
90+
91+
**活性**意味着"好事最终会发生",确保区块链始终能添加新的区块,永远不会陷入死锁状态。
92+
93+
**CAP 定理**指出没有分布式系统能够同时提供一致性、可用性和分区容错性。这意味着当通信不可靠时,我们无法设计出在所有情况下都既安全又活跃的系统。
94+
95+
#### 以太坊优先保证活性
96+
97+
以太坊的共识协议旨在在良好的网络条件下同时提供安全性和活性。然而,在网络出现问题时,它优先保证活性。在网络分区的情况下,每个分区的节点都会继续产生区块,但无法达成最终确定性(这是一个安全性属性)。如果分区持续存在,每个分区可能会确定不同的历史记录,导致形成两条无法调和的独立链。
98+
99+
因此,虽然以太坊努力同时实现安全性和活性,但它倾向于确保网络保持活跃并继续处理交易,即使在严重的网络中断期间可能会带来潜在的安全性问题。
100+
101+
## 机器中的幽灵
102+
103+
以太坊的权益证明共识协议结合了两个独立的协议:[LMD GHOST](/wiki/cl/gasper?id=lmd-ghost.md)[Casper FFG](/wiki/cl/gasper?id=casper-ffg.md)。这两者共同被称为 "Gasper" 共识协议。关于这两个协议的详细信息以及它们如何协同工作将在下一节 [Gasper] 中详细介绍。
104+
105+
Gasper 旨在结合 LMD GHOST 和 Casper FFG 的优势。LMD GHOST 提供活性,通过定期产生新区块确保链持续运行。然而,它容易产生分叉且在形式上并不安全。另一方面,Casper FFG 通过定期对链进行最终确定来提供安全性,防止长程回滚。
106+
107+
本质上,LMD GHOST 保持链向前推进,而 Casper FFG 通过确定区块来确保稳定性。这种组合使以太坊能够优先保证活性,意味着即使 Casper FFG 无法确定区块,链仍然能继续增长。尽管这种组合机制并非完美且存在一些复杂性,但它是一个在实践中运行良好的工程解决方案。
108+
109+
## 架构
110+
111+
以太坊是一个由节点组成的去中心化网络,这些节点通过点对点连接进行通信。这些连接由运行以太坊客户端软件的计算机形成。
112+
113+
<a id="img_network"></a>
114+
115+
<figure class="diagram" style="text-align:center">
116+
117+
![Diagram for Network](../../images/cl/network.png)
118+
119+
<figcaption>
120+
121+
_节点不需要运行验证者客户端(绿色节点)就可以成为网络的一部分,但是要参与共识,则需要质押 32 ETH 并运行验证者客户端。_
122+
123+
</figcaption>
124+
</figure>
125+
126+
### 共识层的组件
127+
128+
- **信标节点**:信标节点使用客户端软件来协调以太坊的权益证明共识。例如 Prysm、Teku、Lighthouse 和 Nimbus。信标节点与其他信标节点、本地执行节点以及(可选的)本地验证者进行通信。
129+
130+
- **验证者**:验证者客户端是允许人们在以太坊共识层质押 32 ETH 的软件。验证者在权益证明系统中负责提议区块,取代了工作量证明中的矿工。验证者只与本地信标节点通信,后者为其提供指令并将其工作广播到网络中。
131+
132+
承载真实应用的主要以太坊网络被称为以太坊主网。以太坊主网是以太坊的实时生产环境,用于铸造和管理真实的以太币(ETH)并具有实际货币价值。
133+
134+
此外还有测试网络,用于铸造和管理测试用的以太币,供开发者、节点运营者和验证者在使用主网真实 ETH 之前测试新功能。每个以太坊网络都有两层:执行层(EL)和共识层(CL)。每个以太坊节点都包含这两层的软件:执行层客户端软件(如 Nethermind、Besu、Geth 和 Erigon)和共识层客户端软件(如 Prysm、Teku、Lighthouse、Nimbus 和 Lodestar)。
135+
136+
<a id="img_node-layers"></a>
137+
138+
<figure class="diagram" style="width: 80%;text-align:center">
139+
140+
![Diagram for CL](../../images/cl/cl.png)
141+
142+
</figure>
143+
144+
**共识层**负责维护共识链(信标链)并处理从其他对等节点接收到的共识区块(信标区块)和证明。**共识客户端**参与一个独立的[点对点网络](/wiki/cl/cl-networking.md),其规范与执行客户端不同。它们需要参与区块传播以接收来自对等节点的新区块,并在轮到它们提议时广播区块。
145+
146+
执行层和共识层客户端并行运行,需要保持连接以进行通信。共识客户端向执行客户端提供指令,执行客户端则将交易包传递给共识客户端以包含在信标区块中。通信通过本地 RPC 连接使用 **Engine-API** 实现。它们共享一个 [ENR](/wiki/cl/cl-networking?id=ethereum-enr),但每个客户端使用独立的密钥(eth1 密钥和 eth2 密钥)。
147+
148+
### 控制流程
149+
150+
**当共识客户端不是区块生产者时:**
151+
152+
1. 通过区块 gossip 协议接收区块。
153+
2. 对区块进行预验证。
154+
3. 将区块中的交易作为执行负载发送到执行层。
155+
4. 执行层执行交易并验证区块状态。
156+
5. 执行层将验证数据发送回共识层。
157+
6. 共识层将区块添加到其区块链中并对其进行证明,将证明广播到网络中。
158+
159+
**当共识客户端是区块生产者时:**
160+
161+
1. 收到成为下一个区块生产者的通知。
162+
2. 调用执行客户端中的创建区块方法。
163+
3. 执行层访问交易内存池。
164+
4. 执行客户端将交易打包成区块,执行它们,并生成区块哈希。
165+
5. 共识客户端将交易和区块哈希添加到信标区块中。
166+
6. 共识客户端通过区块 gossip 协议广播区块。
167+
7. 其他客户端验证区块并对其进行证明。
168+
8. 一旦得到足够验证者的证明,区块就会被添加到链头,被证明合理性并最终确定。
169+
170+
### 状态转换
171+
172+
状态转换函数在区块链中至关重要。每个节点维护一个反映其对世界认知的状态。
173+
174+
节点通过按顺序应用区块使用"状态转换函数"来更新它们的状态。这个函数是"纯函数",意味着其输出仅依赖于输入且没有副作用。因此,如果每个节点从相同的状态(创世状态)开始并应用相同的区块,它们最终都会得到相同的状态。如果不是这样,就说明出现了共识失败。
175+
176+
如果 $S$ 是信标状态,$B$ 是信标区块,则状态转换函数 $f$ 为:
177+
178+
$$S' \equiv f(S, B)$$
179+
180+
这里,$S$ 是前置状态,$S'$ 是后置状态。函数 $f$ 随着每个新区块的到来而迭代执行以更新状态。
181+
182+
### 信标链状态转换
183+
184+
与区块驱动的工作量证明不同,信标链是槽驱动的。状态更新取决于槽的进展,而不依赖于区块是否存在。
185+
186+
信标链的状态转换函数包括:
187+
188+
1. **每槽转换**: $S' \equiv f_s(S)$
189+
2. **每块转换**: $S' \equiv f_b(S, B)$
190+
3. **每周期转换**: $S' \equiv f_e(S)$
191+
192+
每个函数都按照信标链规范中定义的特定时间更新链。
193+
194+
### 有效性条件
195+
196+
从前置状态和已签名区块得到的后置状态是通过 `state_transition(state, signed_block)` 计算的。导致未处理异常(例如,断言失败或越界访问)或 uint64 溢出/下溢的转换都是无效的。
197+
198+
### 信标链状态转换函数
199+
200+
从前置状态 `state` 和已签名区块 `signed_block` 得到的后置状态是通过 `state_transition(state, signed_block)` 定义的。触发未处理异常(例如,`assert` 断言失败或列表越界访问)的状态转换被视为无效。导致 `uint64` 溢出或下溢的状态转换也被视为无效。
201+
202+
```python
203+
def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, validate_result: bool=True) -> None:
204+
block = signed_block.message
205+
# Process slots (including those with no blocks) since block
206+
process_slots(state, block.slot)
207+
# Verify signature
208+
if validate_result:
209+
assert verify_block_signature(state, signed_block)
210+
# Process block
211+
process_block(state, block)
212+
# Verify state root
213+
if validate_result:
214+
assert block.state_root == hash_tree_root(state)
215+
```
216+
217+
```python
218+
def verify_block_signature(state: BeaconState, signed_block: SignedBeaconBlock) -> bool:
219+
proposer = state.validators[signed_block.message.proposer_index]
220+
signing_root = compute_signing_root(signed_block.message, get_domain(state, DOMAIN_BEACON_PROPOSER))
221+
return bls.Verify(proposer.pubkey, signing_root, signed_block.signature)
222+
```
223+
224+
```python
225+
def process_slots(state: BeaconState, slot: Slot) -> None:
226+
assert state.slot < slot
227+
while state.slot < slot:
228+
process_slot(state)
229+
# Process epoch on the start slot of the next epoch
230+
if (state.slot + 1) % SLOTS_PER_EPOCH == 0:
231+
process_epoch(state)
232+
state.slot = Slot(state.slot + 1)
233+
```
234+
235+
## Resources
236+
237+
- Vitalik Buterin, ["Parametrizing Casper: the decentralization/finality time/overhead tradeoff"](https://medium.com/@VitalikButerin/parametrizing-casper-the-decentralization-finality-time-overhead-tradeoff-3f2011672735)
238+
- [Engine API spec](https://hackmd.io/@n0ble/consensus_api_design_space)
239+
- [Vitalik's Annotated Ethereum 2.0 Spec](https://notes.ethereum.org/@vbuterin/SkeyEI3xv)
240+
- Ethereum, ["Eth2: Annotated Spec"](https://github.com/ethereum/annotated-spec)
241+
- Martin Kleppmann, [Distributed Systems.](https://www.youtube.com/playlist?list=PLeKd45zvjcDFUEv_ohr_HdUFe97RItdiB)
242+
- Leslie Lamport et al., [The Byzantine Generals Problem.](https://lamport.azurewebsites.net/pubs/byz.pdf)
243+
- Austin Griffith, [Byzantine Generals - ETH.BUILD.](https://www.youtube.com/watch?v=c7yvOlwBPoQ)
244+
- Michael Sproul, ["Inside Ethereum"](https://www.youtube.com/watch?v=LviEOQD9e8c)
245+
- [Eth2 Handbook by Ben Edgington](https://eth2book.info/capella/part2/consensus/)

src/overview.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# 共识层概述

0 commit comments

Comments
 (0)