Skip to content

Commit 2005f70

Browse files
committed
[improve-block-compression] Fix encoding of Prunned branch cells. Add support for collated data format.
1 parent bb6477e commit 2005f70

File tree

1 file changed

+47
-16
lines changed

1 file changed

+47
-16
lines changed

crypto/vm/boc_compression.cpp renamed to crypto/vm/boc-compression.cpp

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,25 +39,40 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
3939
td::BitSlice bit_reader(serialized.as_slice().ubegin(), serialized.as_slice().size() * 8);
4040
int orig_size = bit_reader.size();
4141

42+
int root_count = bit_reader.bits().get_uint(16);
43+
bit_reader.advance(16);
44+
std::vector<int> root_indexes(root_count);
45+
for (int i = 0; i < root_count; ++i) {
46+
root_indexes[i] = bit_reader.bits().get_uint(16);
47+
bit_reader.advance(16);
48+
}
49+
4250
// Read number of nodes from header
4351
int node_count = bit_reader.bits().get_uint(16);
4452
bit_reader.advance(16);
4553

4654
// Initialize data structures
4755
std::vector<int> cell_data_length(node_count), is_data_small(node_count);
48-
std::vector<int> cell_type(node_count), cell_refs_cnt(node_count);
56+
std::vector<int> is_special(node_count), cell_refs_cnt(node_count);
57+
std::vector<int> prunned_branch_level(node_count, 0);
58+
4959
std::vector<vm::CellBuilder> cell_builders(node_count);
5060
std::vector<std::vector<int>> boc_graph(node_count);
5161

5262
// Read cell metadata
5363
for (int i = 0; i < node_count; ++i) {
54-
cell_type[i] = bit_reader.bits().get_uint(4);
64+
int cell_type = bit_reader.bits().get_uint(4);
65+
is_special[i] = bool(cell_type);
66+
if (is_special[i]) {
67+
prunned_branch_level[i] = cell_type - 1;
68+
}
5569
bit_reader.advance(4);
5670
cell_refs_cnt[i] = bit_reader.bits().get_uint(4);
5771
bit_reader.advance(4);
5872

59-
if (cell_type[i] == 1) {
60-
cell_data_length[i] = 256 + 16;
73+
if (prunned_branch_level[i]) {
74+
int coef = prunned_branch_level[i] == 3 ? 2 : 1;
75+
cell_data_length[i] = (256 + 16) * coef;
6176
} else {
6277
is_data_small[i] = bit_reader.bits().get_uint(1);
6378
bit_reader.advance(1);
@@ -86,8 +101,8 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
86101

87102
// Read initial cell data
88103
for (int i = 0; i < node_count; ++i) {
89-
if (cell_type[i] == 1) {
90-
cell_builders[i].store_long(0x0101, 16);
104+
if (prunned_branch_level[i]) {
105+
cell_builders[i].store_long((1 << 8) + prunned_branch_level[i], 16);
91106
}
92107

93108
int remainder_bits = cell_data_length[i] % 8;
@@ -138,7 +153,7 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
138153
// Read remaining cell data
139154
for (int i = 0; i < node_count; ++i) {
140155
int padding_bits = 0;
141-
if (cell_type[i] != 1 && !is_data_small[i]) {
156+
if (!prunned_branch_level[i] && !is_data_small[i]) {
142157
while (bit_reader.bits()[0] == 0) {
143158
++padding_bits;
144159
bit_reader.advance(1);
@@ -153,27 +168,33 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
153168
// Build cell tree
154169
std::vector<td::Ref<vm::Cell>> nodes(node_count);
155170
for (int i = node_count - 1; i >= 0; --i) {
156-
bool is_special = cell_type[i] != int(vm::CellTraits::SpecialType::Ordinary);
157171
for (int child : boc_graph[i]) {
158172
cell_builders[i].store_ref(nodes[child]);
159173
}
160-
nodes[i] = cell_builders[i].finalize(is_special);
174+
nodes[i] = cell_builders[i].finalize(is_special[i]);
175+
}
176+
177+
std::vector<td::Ref<vm::Cell>> root_nodes;
178+
for (int index : root_indexes) {
179+
root_nodes.push_back(nodes[index]);
161180
}
162181

163182
// Create final result
164-
auto result = vm::std_boc_serialize(nodes[0], 31).move_as_ok();
183+
auto result = vm::std_boc_serialize_multi(root_nodes, 31).move_as_ok();
165184
return result;
166185
}
167186

168187
td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_serialized_31) {
169188
// Deserialize input data
170-
td::Ref<vm::Cell> root = vm::std_boc_deserialize(data_serialized_31).move_as_ok();
189+
std::vector<td::Ref<vm::Cell>> roots = vm::std_boc_deserialize_multi(data).move_as_ok();
171190

172191
// Initialize data structures for graph representation
173192
td::HashMap<vm::Cell::Hash, int> cell_hashes;
174193
std::vector<std::vector<int>> boc_graph;
175194
std::vector<td::BitSlice> cell_data;
176195
std::vector<int> cell_type;
196+
std::vector<int> prunned_branch_level;
197+
std::vector<int> root_indexes;
177198

178199
// Build graph representation using recursive lambda
179200
const auto build_graph = [&](auto&& self, td::Ref<vm::Cell> cell) -> int {
@@ -192,10 +213,12 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_s
192213
// Initialize new cell in graph
193214
boc_graph.emplace_back();
194215
cell_type.emplace_back(int(cell_slice.special_type()));
216+
prunned_branch_level.push_back(0);
195217

196218
// Process special cell of type PrunnedBranch
197219
if (cell_slice.special_type() == vm::CellTraits::SpecialType::PrunnedBranch) {
198220
cell_data.emplace_back(cell_slice.as_bitslice().subslice(16, cell_slice.as_bitslice().size() - 16));
221+
prunned_branch_level.back() = cell_slice.data()[1];
199222
} else {
200223
cell_data.emplace_back(cell_slice.as_bitslice());
201224
}
@@ -209,8 +232,11 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_s
209232
return current_cell_id;
210233
};
211234

212-
// Build the graph starting from root
213-
build_graph(build_graph, root);
235+
// Build the graph starting from roots
236+
for (auto root : roots) {
237+
root_indexes.push_back(boc_graph.size());
238+
build_graph(build_graph, root);
239+
}
214240

215241
// Calculate graph properties
216242
const int node_count = boc_graph.size();
@@ -244,7 +270,7 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_s
244270
for (int i = 0; i < node_count; ++i) {
245271
in_degree[i] = boc_graph[i].size();
246272
if (in_degree[i] == 0) {
247-
queue.emplace_back(cell_type[i] == 0 ? 4 : cell_type[i], -int(cell_data[i].size()), -i);
273+
queue.emplace_back(cell_type[i] == 0, -int(cell_data[i].size()), -i);
248274
}
249275
}
250276

@@ -273,15 +299,20 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_s
273299

274300
// Build compressed representation
275301
td::BitString result;
276-
result.reserve_bits(data_serialized_31.size() * 8);
302+
result.reserve_bits(data.size() * 8);
303+
result.reserve_bitslice(16).bits().store_uint(root_indexes.size(), 16);
304+
for (int root_ind : root_indexes) {
305+
result.reserve_bitslice(16).bits().store_uint(rank[root_ind], 16);
306+
}
277307

278308
// Store node count
279309
result.reserve_bitslice(16).bits().store_uint(node_count, 16);
280310

281311
// Store cell types and sizes
282312
for (int i = 0; i < node_count; ++i) {
283313
int node = topo_order[i];
284-
result.reserve_bitslice(4).bits().store_uint(cell_type[node], 4);
314+
int currrent_cell_type = bool(cell_type[node]) + prunned_branch_level[node];
315+
result.reserve_bitslice(4).bits().store_uint(currrent_cell_type, 4);
285316
result.reserve_bitslice(4).bits().store_uint(boc_graph[node].size(), 4);
286317

287318
if (cell_type[node] != 1) {

0 commit comments

Comments
 (0)