Ячейки и пакеты ячеек (Cell & Bag of Cells (BoC))
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Cell
Ячейка представляет собой структуру данных в блокчейне TON. Ячейки могут хранить до 1023 бит и иметь до 4 ссылок на другие ячейки.


Bag of Cells
Bag of Cells (BoC) - это формат для сериализации ячеек в массивы байтов, который более подробно описан в схеме TL-B.


В TON все состоит из ячеек, включая код контракта, хранимые данные, блоки, что обеспечивает упрощение и надежную гибкость процесса.


Сериализация ячеек
Давайте проанализируем наш первый пример Bag of Cells :


1[8_] -> {
24[0AAAAA],
7[FE] -> {
24[0AAAAA]
}
}
В этом примере у нас есть корневая ячейка размером 1 бит, которая имеет 2 ссылки: первая на 24-битную ячейку, а вторая на 7-битную ячейку, которая имеет 1 ссылку на 24-битную ячейку.
Чтобы эта структура работала так, как задумано, необходимо превратить ячейки в одну последовательность байтов. Для этого, во-первых, мы используем только уникальные типы ячеек, ниже представлены 3 из 4:
1[8_]
24[0AAAAA]
7[FE]
Чтобы оставить только уникальные ячейки, их необходимо сравнить. Чтобы сделать это, нам нужно сравнить [хэши] (#cell-хэш) ячеек.
1[8_] -> index 0 (root cell)
7[FE] -> index 1
24[0AAAAA] -> index 2
Теперь давайте вычислим описания для каждой из 3 ячеек, упомянутых выше. Эти описания состоят из 2 байт, в которых хранятся флаги, содержащие информацию о длине данных и количестве связей с данными.
Первый байт - дескриптор ссылок - вычисляется как r+8s+32l
, где 0 ≤ r ≤ 4
- количество ссылок ячеек, 0 ≤ s ≤ 1
- 1 для экзотических ячеек и 0 для обычных, а 0 ≤ l ≤ 3
- уровней ячейки.
Второй - битовый дескриптор - равен floor(b / 8) + ceil (b / 8)
, где 0 <= b <= 1023
- количество бит в ячейке. Этот дескриптор представляет длину полных 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)}
}
Упаковка Bag of Cells
Давайте упакуем ячейку из раздела выше. Мы уже сериализовали ее в плоский 14-байтовый массив.
Поэтому мы строим заголовок согласно его схеме.
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
Примеры реализации Bag of Cells: Сериализация, Десериализация