cell与cell包 (BoC)
cell
cell是TON区块链上的一种数据结构。cell能够存储多达1023位,并且可以拥有最多4个对其他cell的引用。
cell包
cell包 (BoC) 是一种将cell序列化为字节数组的格式,这一格式在 TL-B schema 中有进一步描述。
在TON上,所有东西都由cell构成,包括合约代码、存储的数据、区块等,实现了过程中的流线型和强大的灵活性。
cell序列化
让我们分析我们的第一个cell包示例:
1[8_] -> {
24[0AAAAA],
7[FE] -> {
24[0AAAAA]
}
}
在此示例中,我们有一个1位大小的根cell,它有2个链接:第一个指向一个24位cell,第二个指向一个7位cell,后者又有一个链接指向一个24位cell。
为了使此框架按预期工作,需要将cell转换为单一的字节序列。为此,首先,我们只利用唯一的cell类型,下面3个中的2个如下所示:
1[8_]
24[0AAAAA]
7[FE]
为了只留下唯一的cell,需要进行比较。为此,我们需要比较cell的哈希。
1[8_] -> index 0 (root cell)
7[FE] -> index 1
24[0AAAAA] -> index 2
现在,让我们计算上述3个cell的描述。这些描述由2个字节组成,存储了有关数据长度和数据链接数量的标志信息。
第一个字节 - 引用描述符 - 计算为 r+8s+32l
,其中 0 ≤ r ≤ 4
是cell引用(链接)的数量,0 ≤ s ≤ 1
对于异类cell为1,对于普通cell为0,0 ≤ l ≤ 3
是cell的层级。
第二个字节 - 位描述符 - 等于 floor(b / 8) + ceil (b / 8)
,其中 0 <= b <= 1023
是cell中的位数。这个描述符代表cell数据的完整4位组的长度(但如果不为空至少为1)。
结果是:
1[8_] -> 0201 -> 2 refs, length 1
7[FE] -> 0101 -> 1 ref, length 1
24[0AAAAA] -> 0006 -> 0 refs, length 6
对于不完整的4位组的数据,在序列的末尾添加1位。这意味着它表示组的结束位,并用于确定不完整组的真实大小。让我们添加以下位:
1[8_] -> C0 -> 0b10000000->0b11000000
7[FE] -> FF -> 0b11111110->0b11111111
24[0AAAAA] -> 0AAAAA -> do not change (full groups)
现在让我们添加引用索引:
0 1[8_] -> 0201 -> refers to 2 cells with such indexes
1 7[FE] -> 02 -> refers to cells with index 2
2 24[0AAAAA] -> no refs
并将其全部组合在一起:
0201 C0 0201
0101 FF 02
0006 0AAAAA
并通过将相应的字符串连接成一个单一的字节数组来拼接它们:
0201c002010101ff0200060aaaaa
,大小14字节。
显示示例
func (c *Cell) descriptors() []byte {
ceilBytes := c.bitsSz / 8
if c.bitsSz%8 ! = 0 {
ceilBytes++
}
// calc size
ln := ceilBytes + c.bitsSz / 8
specBit := byte(0)
if c.special {
specBit = 8
}
return []byte{byte(len(c.refs)) + specBit + c.level*32, byte(ln)}
}
打包cell包
让我们打包上一节直接提到的cell。我们已经将其序列化为一个扁平的14字节数组。
因此,我们根据其架构构建header。
b5ee9c72 -> id tl-b of the BoC structure
01 -> flags and size:(## 3), in our case the flags are all 0,
and the number of bytes needed to store the number of cells is 1.
we get - 0b0_0_0_00_001
01 -> number of bytes to store the size of the serialized cells
03 -> number of cells, 1 byte (defined by 3 bits size:(## 3), equal to 3.
01 -> number of root cells - 1
00 -> absent, always 0 (in current implementations)
0e -> size of serialized cells, 1 byte (size defined above), equal to 14
00 -> root cell index, size 1 (determined by 3 size:(## 3) bits from header),
always 0
0201c002010101ff0200060aaaaa -> serialized cells
接下来,我们将上述所有内容连接成一个字节数组,得到我们最终的BoC:
b5ee9c7201010301000e000201c002010101ff0200060aaaaa
特殊cell
通常,TON上运行的cell分为两大类:普通cell和特殊cell。用户处理的大多数cell是普通cell,负责携带信息。
然而,为了实现网络的内部功能,有时需要特殊cell,并且它们用于多种目的,这取决于它们的子类型。
cell层级
每个cell都有一个称为Level
的属性,它由0到3的整数表示。
普通cell层级
普通cell的层级始终等于其所有引用的层级的最大值:
Lvl(c) = max(Lvl(r_0), ..., Lvl(r_i), ..., Lvl(r_e))
其中i
是c
的引用索引,e
是c
的引用数量。
没有引用的普通cell层级为零
特殊cell层级
特殊cell对其层级的设置有不同的规则,这些规则在此文中有描述。
cell哈希
在大多数情况下,用户使用的是层级为0的普通cell,它们只有一个哈希,称为 representation hash(或 hash infinity)。
层级为Lvl(c) = l
的cellc
,其中1 ≤ l ≤ 3
,除了 representation hash 外,还有l
个"更高"的哈希。
标准cell representation hash 计算
首先,我们需要计算cell表示(类似于上面描述的cell序列化)
- 计算描述符字节
- 添加序列化cell数据
- 对于每个cell的引用,添加其深度
- 对于每个cell的引用,添加其 representation hash
- 计算结果的SHA256哈希
让我们分析以下示例:
无引用的cell
32[0000000F]
- 描述符计算
引用描述符等于 r+8s+32l = 0 + 0 + 0 = 0 = 00
位描述符等于 floor(b / 8) + ceil (b / 8) = 8 = 08
连接这些字节,我们得到 0008
- cell数据序列化
在这种情况下,我们有完整的4位组,所以我们不必向cell数据添加任何位。结果是 0000000f
- 引用深度
我们跳过这部分,因为我们的cell没有任何引用
- 引用哈希
我们跳过这部分,因为我们的cell没有任何引用
- SHA256计算
连接前面步骤的字节,我们得到 00080000000f
,其SHA256为 57b520dbcb9d135863fc33963cde9f6db2ded1430d88056810a2c9434a3860f9
- 这就是cell representation hash 。
带有引用的cell
24[00000B] -> {
32[0000000F],
32[0000000F]
}
- 描述符计算
引用描述符等于 r+8s+32l = 2 + 0 + 0 = 0 = 02
位描述符等于 floor(b / 8) + ceil (b / 8) = 6 = 06
连接这些字节,我们得到 0206
- cell数据序列化
在这种情况下,我们有完整的4位组,所以我们不必向cell数据添加任何位。结果是 00000b
- 引用深度
深度由2个字节表示。我们的cell有2个引用,每个的深度都是零,所以这一步的结果是 00000000
。
- 引用哈希
对于每个引用,我们添加其哈希(我们上面计算过),所以结果是 \`57b520dbcb9d135863fc33963cde9f6db2ded1430d88056810a2c9434a3860f957b520dbcb9d135863fc33963cde9f6db2ded1430d88056810a2c9434a3860f9
- SHA256计算
连接前面步骤的字节,我们得到 020600000b0000000057b520dbcb9d135863fc33963cde9f6db2ded1430d88056810a2c9434a3860f957b520dbcb9d135863fc33963cde9f6db2ded1430d88056810a2c9434a3860f9
,其SHA256为 f345277cc6cfa747f001367e1e873dcfa8a936b8492431248b7a3eeafa8030e7
- 这就是cell representation hash
更高哈希的计算
普通cellc
的更高哈希与其 representation hash 的计算类似,但使用其引用的更高哈希而不是它们的 representation hash。
特殊cell有其自己的计算更高哈希的规则,这些规则在此文中有描述。