首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是SSZ SimpleSerialize,为什么要开发它?

什么是SSZ SimpleSerialize,为什么要开发它?
EN

Ethereum用户
提问于 2019-08-18 05:35:00
回答 1查看 2K关注 0票数 15

我们看到的是最新的等级库,它没有太多的背景信息或关于SSZ试图实现的目标的解释。SSZ的主要目标是什么?

它的序列化和Merkleization优势的示例将非常有用,因为这可能是一个典型的问题。

EN

回答 1

Ethereum用户

回答已采纳

发布于 2020-04-01 06:14:13

SimpleSerialize (SSZ)是Eth2中使用的标准序列化格式。SSZ规范指导读者如何执行两个不同的任务:

  1. 编码/解码:如何将Eth2数据结构(例如,BeaconBlockBeaconState)编码为可以通过网络发送或存储在数据库中的字节字符串。
  2. Merkleization:如何找到给定数据结构的散列(从技术上讲,它是一个梅克尔根,而不是一个普通的“哈希”)。

对于每一项任务,我都将说明目标(或我对它们的理解),并为其中的每一项任务树立榜样。

1.编码/解码

据我所知,从来没有关于SSZ目标的规范声明。然而,我认为公平地说,这些是其中的一些目标:

  • 简单:这种格式最初是由Vitalik定义的,他想要一种比RLP ( Eth1编码方案)更简单的格式。
  • Bijective:对于某个类型的实例,应该只有该实例的一个SSZ表示;不应该有不同的字节表示相同的BeaconBlock。使用此属性,SSZ编码为该实例形成一个“标识”。
  • 压缩: SSZ字节需要通过网络发送,所以它们应该是紧凑的(在不影响简单性的情况下)。
  • 默克尔-第一:兼容的设计,以防止汞的方案,将生效后阶段的Eth2。
  • 便宜的遍历: SSZ的第一个版本不包括“偏移”方案,但是Peter Szilagyi (Geth)建议包括偏移量,这样就可以便宜地遍历序列化结构的字段。这对于受约束的环境(例如EVM)是很好的,因为这些环境可能需要读取结构的单个字段,而不需要对整个过程进行解码。

编解码示例

我将提供一个简单的示例,并将读者推荐给@protolambda的SSZ编码图

让我们假设这个虚构的数据结构,因为Eth2规范中没有一个结构适合这个示例:

代码语言:javascript
复制
class Example
    id: uint64,
    bytes: List[uint8, 64]
    next: uint64

Example有两个64位整数字段(idnext)和一个可以容纳0-64字节的bytes字段。让我们实例化它:

代码语言:javascript
复制
my_example = Example(id=42, bytes=List[0, 1, 2], next=43)

现在,让我们看看serialize(my_example)的输出:

代码语言:javascript
复制
# serialize(my_example)
#
# Note: this is a single byte-array split over four lines for readability.
[
  42, 0, 0, 0,  # The little-endian encoding of `id`, 42.
  12, 0, 0, 0,  # The "offset" that indicates where the variable-length value of `bytes` starts (little-endian 12).
  43, 0, 0, 0,  # The little-endian encoding of `next`, 43.
  0, 1, 2       # The value of the `bytes` field.
]

正如我们所看到的,字段按照定义的顺序进行编码。“固定尺寸”项直接序列化到缓冲区中,而“变尺寸”项首先作为指向项目实际值开始的“偏移量”序列化。变量大小项的实际值(而不是偏移)是在所有固定大小的项和偏移量附加后追加的。

2.合并

Eth2不只是使用块编码的简单SHA256哈希来标识它(例如,sha256(serialize(block)) )。相反,Eth2中的所有散列都是Merkle根。

决定在所有散列中使用Merkle是为了让轻量级客户端和执行环境可以使用Merkel-保护法来了解Eth2状态的部分内容。例如,如果轻型客户端具有某个块根的可信的32字节散列,我可以向该轻型客户端提供一个简洁的密码证明,即验证器n具有x的平衡。

然而,将Merkle用作规范散列的决定有很大的计算开销。灯塔中的同步瓶颈(我工作的客户端)正在执行这些Merkle。当一个简单的sha256(serialize(block))花费微秒时,其中一些例程需要几十毫秒(即慢数百万倍)。

因此,我认为Merkleization方案的目标是确保受限环境(轻型客户端、执行环境、eth1等)可以获得轻量级的证据,他们可以用来做重要的决定。

Merklization示例

让我们使用前面的Example类型以及my_example实例化。同样,我建议使用@protolambda:SSZ散列树根与合并的图表。

为了帮助这个示例,我们定义了hash_concat(a, b),它返回ab连接的SHA256散列。例如,hash_concat([1], [2]) == hash([1, 2])

首先,我们确定了Example梅克尔树的叶子:

代码语言:javascript
复制
# id: little-endian 42, right-0-padded to 32 bytes.
leaf_0 = [42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

# bytes: when a list is hashed, you first hash the list values (right-0-padded to the next multiple of 32) along with the little-endian encoding of the list length (aka.,  "mixing in the length").
leaf_1 = hash_concat(
  [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [3, 0, 0, 0]
)

# id: little-endian 43, right-0-padded to 32 bytes.
leaf_2 = [43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 

现在,我们将叶子散到Merkle树的中间层:

代码语言:javascript
复制
# Hash the concatenation of `id` and `bytes`.
node_1 = hash_concat(leaf_0, leaf_1);

# Hash the concatentation of `next` and a "zero leaf" (32 zero-bytes), since there is no fourth element.
node_2 = hash_concat(leaf_2, [0; 32])

最后,我们可以用root = hash_concat(node_1, node_2)找到这棵梅克尔树的根。

最终,我们创建了一个嵌套的Merkle树,如下所示:

代码语言:javascript
复制
             root
               |
       -----------------
      /                  \
 node_1                node_2
    |                     |
  ------             -----------
 /      \           /           \
id  bytes_root    next       ZERO_LEAF
         |
      -------
     /       \
  bytes   len(bytes) 
票数 17
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/74005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档