@@ -39,25 +39,40 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
39
39
td::BitSlice bit_reader (serialized.as_slice ().ubegin (), serialized.as_slice ().size () * 8 );
40
40
int orig_size = bit_reader.size ();
41
41
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
+
42
50
// Read number of nodes from header
43
51
int node_count = bit_reader.bits ().get_uint (16 );
44
52
bit_reader.advance (16 );
45
53
46
54
// Initialize data structures
47
55
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
+
49
59
std::vector<vm::CellBuilder> cell_builders (node_count);
50
60
std::vector<std::vector<int >> boc_graph (node_count);
51
61
52
62
// Read cell metadata
53
63
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
+ }
55
69
bit_reader.advance (4 );
56
70
cell_refs_cnt[i] = bit_reader.bits ().get_uint (4 );
57
71
bit_reader.advance (4 );
58
72
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;
61
76
} else {
62
77
is_data_small[i] = bit_reader.bits ().get_uint (1 );
63
78
bit_reader.advance (1 );
@@ -86,8 +101,8 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
86
101
87
102
// Read initial cell data
88
103
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 );
91
106
}
92
107
93
108
int remainder_bits = cell_data_length[i] % 8 ;
@@ -138,7 +153,7 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
138
153
// Read remaining cell data
139
154
for (int i = 0 ; i < node_count; ++i) {
140
155
int padding_bits = 0 ;
141
- if (cell_type [i] != 1 && !is_data_small[i]) {
156
+ if (!prunned_branch_level [i] && !is_data_small[i]) {
142
157
while (bit_reader.bits ()[0 ] == 0 ) {
143
158
++padding_bits;
144
159
bit_reader.advance (1 );
@@ -153,27 +168,33 @@ td::Result<td::BufferSlice> boc_decompress_improved_structure_lz4(td::Slice data
153
168
// Build cell tree
154
169
std::vector<td::Ref<vm::Cell>> nodes (node_count);
155
170
for (int i = node_count - 1 ; i >= 0 ; --i) {
156
- bool is_special = cell_type[i] != int (vm::CellTraits::SpecialType::Ordinary);
157
171
for (int child : boc_graph[i]) {
158
172
cell_builders[i].store_ref (nodes[child]);
159
173
}
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]);
161
180
}
162
181
163
182
// 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 ();
165
184
return result;
166
185
}
167
186
168
187
td::Result<td::BufferSlice> boc_compress_improved_structure_lz4 (td::Slice data_serialized_31) {
169
188
// 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 ();
171
190
172
191
// Initialize data structures for graph representation
173
192
td::HashMap<vm::Cell::Hash, int > cell_hashes;
174
193
std::vector<std::vector<int >> boc_graph;
175
194
std::vector<td::BitSlice> cell_data;
176
195
std::vector<int > cell_type;
196
+ std::vector<int > prunned_branch_level;
197
+ std::vector<int > root_indexes;
177
198
178
199
// Build graph representation using recursive lambda
179
200
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
192
213
// Initialize new cell in graph
193
214
boc_graph.emplace_back ();
194
215
cell_type.emplace_back (int (cell_slice.special_type ()));
216
+ prunned_branch_level.push_back (0 );
195
217
196
218
// Process special cell of type PrunnedBranch
197
219
if (cell_slice.special_type () == vm::CellTraits::SpecialType::PrunnedBranch) {
198
220
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 ];
199
222
} else {
200
223
cell_data.emplace_back (cell_slice.as_bitslice ());
201
224
}
@@ -209,8 +232,11 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_s
209
232
return current_cell_id;
210
233
};
211
234
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
+ }
214
240
215
241
// Calculate graph properties
216
242
const int node_count = boc_graph.size ();
@@ -244,7 +270,7 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_s
244
270
for (int i = 0 ; i < node_count; ++i) {
245
271
in_degree[i] = boc_graph[i].size ();
246
272
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);
248
274
}
249
275
}
250
276
@@ -273,15 +299,20 @@ td::Result<td::BufferSlice> boc_compress_improved_structure_lz4(td::Slice data_s
273
299
274
300
// Build compressed representation
275
301
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
+ }
277
307
278
308
// Store node count
279
309
result.reserve_bitslice (16 ).bits ().store_uint (node_count, 16 );
280
310
281
311
// Store cell types and sizes
282
312
for (int i = 0 ; i < node_count; ++i) {
283
313
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 );
285
316
result.reserve_bitslice (4 ).bits ().store_uint (boc_graph[node].size (), 4 );
286
317
287
318
if (cell_type[node] != 1 ) {
0 commit comments