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层级为零