TON茶余饭后——TVM简单入门(一)

系列文章目录


前言

这里是全新的一次TVM入门课程,此前读者将TVM白皮书汉化后,效果并不理想。许多人没有足够的计算机底层水平,与逻辑理解的培训。所有就有了这个十分简洁的栏目,我们会根据源代码的片段内容通过十分透彻简洁的重点概括+举例子的方式讲解TON虚拟机的设计原理。

从TVM的Cell开始

cell介绍

原文

TVM memory and persistent storage consist of cells. Recall that the TVM memory and persistent storage consist of (TVM) cells. Each cell contains up to 1023 bits of data and up to four references to other cells.11 Circular references are forbidden and cannot be created by means of TVM (cf. 2.3.5). In this way, all cells kept in TVM memory and persistent storage constitute a directed acyclic graph (DAG).
11From the perspective of low-level cell operations, these data bits and cell references are not intermixed. In other words, an (ordinary) cell essentially is a couple consisting of a list of up to 1023 bits and of a list of up to four cell references, without prescribing an order in which the references and the data bits should be deserialized, even though TL-B schemes appear to suggest such an order.

以下是重点内容:

  1. TVM单元的定义:TVM的内存和持久化存储由单元(cells)组成。每个单元可以包含最多1023位的数据和最多四个对其他单元的引用。

  2. 数据和引用的结构:从低级单元操作的角度来看,数据位和单元引用不会混合在一起。也就是说,一个普通的单元本质上是一对,包括一个最多包含1023位的位列表和一个最多包含四个单元引用的列表。并没有规定在反序列化时引用和数据位的顺序,即使TL-B方案似乎暗示了这样的顺序。

  3. 禁止循环引用:TVM禁止创建循环引用,这意味着所有存储在TVM内存和持久化存储中的单元构成了一个有向无环图(DAG)。这有助于避免内存泄漏和无限循环,确保了数据结构的一致性和稳定性。

举例说明:
假设我们正在开发一个智能合约,需要在TVM中存储一系列交易记录。每个交易记录可以表示为一个单元,其中包含交易的详细信息(如金额、时间戳等)和对其他相关交易记录的引用(例如,一个交易可能引用了之前的交易作为其资金来源)。这些单元将按照交易发生的顺序链接起来,形成一个DAG结构,其中每个单元都指向之前的交易,但没有任何单元会指向自己或形成循环,从而确保了整个数据结构的完整性和安全性。

这段内容讨论了TVM中的一个重要特性:禁止循环引用。在某些编程环境中,循环引用可能导致内存泄漏,因为垃圾回收器无法确定何时释放相互引用的对象。TVM通过其设计避免了这种情况,确保了数据结构的有向无环图(DAG)特性。以下是对这一过程的详细解释:

  1. 尝试创建循环引用:假设我们有两个单元A和B,我们首先创建单元A并写入一些数据。然后,我们创建单元B并写入一些数据,同时在单元B中添加一个引用指向之前构建的单元A。最后,我们在单元A中添加一个引用指向单元B。

  2. TVM的处理方式:在TVM中,这一系列操作的结果并不是形成了一个循环引用(A引用B,B引用A)。相反,我们得到了一个新的单元A’,它包含了原始存储在单元A中的数据的副本,以及一个指向单元B的引用。同时,单元B包含了一个引用指向原始的单元A。

  3. 透明写入复制机制:TVM的透明写入复制(copy-on-write)机制和“一切都是值”的范式允许我们仅使用先前构建的单元来创建新的单元,从而禁止了循环引用的出现。

  4. 对内存管理的影响:由于不存在循环引用,TVM可以使用引用计数来立即释放未使用的内存,而不需要依赖垃圾回收器。这对于TON区块链中的数据存储至关重要,因为它可以提高内存管理的效率,并减少内存泄漏的风险。

  5. 对TON区块链的意义:在TON区块链中,这种避免循环引用的特性对于确保数据的一致性和安全性非常重要。它允许区块链系统高效地处理和存储智能合约和交易数据,同时避免了复杂的垃圾回收过程,这对于区块链的性能和可扩展性至关重要。

cell的级别

The level of a cell. Every cell c has another attribute Lvl(c) called its (de Brujn) level, which currently takes integer values in the range 0. . . 3.The level of an ordinary cell is always equal to the maximum of the levels of all its children ci:
Lvl(c) = max Lvl(ci) , (1) 1≤i≤r
for an ordinary cell c containing r references to cells c1, ..., cr. If r = 0, Lvl(c) = 0. Exotic cells may have different rules for setting their level.
A cell’s level affects the number of higher hashes it has. More precisely, a level l cell has l higher hashes Hash1(c), . . . , Hashl(c) in addition to its representation hash Hash(c) = Hash∞(c). Cells of non-zero level appear inside Merkle proofs and Merkle updates, after some branches of the tree of cells representing a value of an abstract data type are pruned.

这段内容描述了TVM单元的另一个属性——单元级别(de Bruijn级别),这个属性对于理解单元在数据结构中的位置和它们在Merkle证明中的作用非常重要。以下是关键点的总结:

  1. 单元级别的定义:每个单元c都有一个称为其de Bruijn级别的属性,记作Lvl©,目前的取值范围是0到3。

  2. 普通单元的级别:对于包含r个引用(指向其他单元c1, …, cr)的普通单元c,其级别是其所有子单元级别的最大值。如果单元没有引用(r=0),则其级别为0。

  3. 异型单元的级别:异型单元可能有不同的规则来设置它们的级别,这与普通单元不同。

  4. 单元级别的影响:单元的级别影响它拥有的更高级别哈希的数量。具体来说,级别为l的单元除了其表示哈希Hash© = Hash∞©之外,还有l个更高级别的哈希Hash1©, …, Hashl©。

  5. 非零级别单元的应用:非零级别的单元会出现在Merkle证明和Merkle更新中,这些证明和更新是在代表抽象数据类型值的单元树的一些分支被剪枝之后形成的。

举例说明:
假设我们有一个存储在TVM中的Merkle树,这棵树用于验证数据的完整性。每个单元可能代表数据的一部分,例如,一个文件的片段或交易记录。当我们需要验证树中的某个特定单元时,我们可能会创建一个Merkle证明,这个证明包含了从根单元到目标单元的路径上的单元的哈希值。在这个过程中,单元的级别就非常重要,因为它决定了我们需要多少个哈希值来验证单元的路径。级别较高的单元可能需要更多的哈希值来证明其路径,这反映了它在树中的位置更深,需要更多的证据来验证其完整性。

序列化过程

3.1.4. Standard cell representation. When a cell needs to be transferred by a network protocol or stored in a disk file, it must be serialized. The standard representation CellRepr(c) = CellRepr∞(c) of a cell c as an octet (byte) sequence is constructed as follows:
1. Two descriptor bytes d1 and d2 are serialized first. Byte d1 equals r+8s+32l, where 0 ≤ r ≤ 4 is the quantity of cell references contained in the cell, 0 ≤ l ≤ 3 is the level of the cell, and 0 ≤ s ≤ 1 is 1 for exotic cells and 0 for ordinary cells. Byte d2 equals ⌊b/8⌋+⌈b/8⌉, where 0 ≤ b ≤ 1023 is the quantity of data bits in c.
2. Then the data bits are serialized as ⌈b/8⌉ 8-bit octets (bytes). If b is not a multiple of eight, a binary 1 and up to six binary 0s are appended to the data bits. After that, the data is split into ⌈b/8⌉ eight-bit groups, and each group is interpreted as an unsigned big-endian integer 0 . . . 255 and stored into an octet.
3. Finally, each of the r cell references is represented by 32 bytes contain- ing the 256-bit representation hash Hash(ci), explained below in 3.1.5, of the cell ci referred to.
In this way, 2 + ⌈b/8⌉ + 32r bytes of CellRepr(c) are obtained.

这里描述了TVM单元(cell)的标准序列化表示形式,即如何将单元转换为字节序列,以便通过网络协议传输或存储在磁盘文件中。以下是序列化过程的关键步骤:

  1. 描述符字节

    • 首先序列化的是两个描述符字节d1d2
    • d1字节的值计算公式为r+8s+32l,其中r是单元中包含的单元引用数量(0到4),l是单元的级别(0到3),s是单元类型(对于普通单元为0,异型单元为1)。
    • d2字节的值计算公式为⌊b/8⌋+⌈b/8⌉,其中b是单元中的数据位数(0到1023)。
  2. 数据位序列化

    • 数据位被序列化为⌈b/8⌉个8位字节。如果b不是8的倍数,数据位后面会追加一个二进制1和最多六个二进制0。
    • 然后数据被分成⌈b/8⌉个8位组,每个组被解释为一个无符号的大端整数(0到255),并存储为一个字节。
  3. 单元引用序列化

    • 最后,单元中的每个引用r被表示为32字节,包含被引用单元ci的256位表示哈希Hash(ci)

通过这个过程,得到的单元序列化表示CellRepr(c)由2 + ⌈b/8⌉ + 32r字节组成。

举例说明:
假设我们有一个单元,它包含3个引用,256位数据,并且是一个普通单元(级别为0)。序列化这个单元的步骤如下:

  1. 计算d1d2

    • d1 = 3 + 80 + 320 = 3
    • d2 = ⌊256/8⌋ + ⌈256/8⌉ = 32 + 32 = 64
  2. 序列化数据位:

    • 数据位为256位,正好是8的倍数,所以不需要追加额外的位。
    • 数据被分成32个8位组,每组转换为一个大端整数并存储为字节。
  3. 序列化单元引用:

    • 每个引用转换为32字节的哈希值,所以3个引用总共需要96字节。

最终,这个单元的序列化表示将由2(描述符字节)+ 32(数据位)+ 96(引用哈希)= 130字节组成。
数据位序列化的过程是将单元中的数据位转换为一种可以在网络上传输或在磁盘上存储的格式。这个过程确保了数据的完整性和一致性,无论数据在何处处理或存储。以下是数据位序列化步骤的详细解释及其作用:

  1. 计算字节数:首先,确定数据位b需要多少个8位字节(即1字节)来存储。这是通过计算⌈b/8⌉来完成的,意味着如果b不是8的倍数,就会向上取整到最近的整数。这样做是为了确保所有的数据位都能被完全包含在8位字节中。

  2. 填充位:如果数据位b的数量不是8的倍数,那么在数据位的末尾追加一个二进制1和最多六个二进制0,直到总位数成为8的倍数。这一步骤的目的是为了形成一个完整的字节序列,因为网络传输和文件存储通常以字节为单位。追加的二进制1用于指示原始数据的结束,而随后的零则确保了字节的对齐。

  3. 分组和转换:将填充后的数据位分成⌈b/8⌉个8位组,每个组都被视为一个无符号的大端整数。大端(Big-Endian)是一种多字节数据的存储方式,其中最重要的字节(最高位字节)存储在最低的内存地址处。这种格式被广泛用于网络协议和文件格式中,因为它可以确保不同系统之间数据的一致性。

  4. 存储为字节:每个8位组被存储为一个字节。这样,整个数据位序列就被转换为了一个字节序列,这个序列可以直接用于网络传输或写入到磁盘文件中。

序列化的作用包括:

  • 确保数据完整性:通过确保数据在序列化过程中保持完整,可以避免在数据传输或存储过程中出现错误。
  • 促进数据交换:序列化后的数据可以在网络上传输或在不同的系统和平台之间共享,因为字节序列是一种通用的数据表示形式。
  • 便于存储和检索:将数据转换为字节序列后,可以更容易地将其存储在磁盘上,并在需要时快速检索和恢复。
  • 支持数据压缩和加密:序列化的数据可以被压缩以减少存储空间,或者被加密以保护数据的安全性。

猜你喜欢

转载自blog.csdn.net/zhuqiyua/article/details/142977394