1use std::fmt::Debug;
2use std::hash::Hash;
3use std::io;
4use std::ops::Deref;
5use std::sync::Arc;
6
7pub use bag_of_cells::*;
8use base64::Engine;
9use bitstream_io::{BigEndian, BitWrite, BitWriter};
10pub use builder::*;
11pub use error::*;
12use hmac::digest::Digest;
13use lazy_static::lazy_static;
14pub use parser::*;
15pub use raw::*;
16use sha2::Sha256;
17pub use slice::*;
18pub use ton_cell_num::*;
19pub use util::*;
20
21use crate::cell::cell_type::CellType;
22use crate::cell::level_mask::LevelMask;
23use crate::types::DEFAULT_CELL_HASH;
24use crate::TonHash;
25
26mod bag_of_cells;
27mod builder;
28mod cell_type;
29pub mod dict;
30mod error;
31mod level_mask;
32mod ton_cell_num;
33
34mod parser;
35mod raw;
36mod raw_boc_from_boc;
37mod slice;
38#[cfg(test)]
39mod test_boc;
40mod util;
41
42const DEPTH_BYTES: usize = 2;
43const MAX_LEVEL: u8 = 3;
44
45pub type ArcCell = Arc<Cell>;
46
47lazy_static! {
48 pub static ref EMPTY_CELL: Cell = Cell::default();
49 pub static ref EMPTY_ARC_CELL: ArcCell = Arc::new(Cell::default());
50}
51
52#[derive(PartialEq, Eq, Clone, Hash)]
53pub struct Cell {
54 data: Vec<u8>,
55 bit_len: usize,
56 references: Vec<ArcCell>,
57 cell_type: CellType,
58 level_mask: LevelMask,
59 hashes: [TonHash; 4],
60 depths: [u16; 4],
61}
62
63impl Cell {
64 pub fn new(
65 data: Vec<u8>,
66 bit_len: usize,
67 references: Vec<ArcCell>,
68 is_exotic: bool,
69 ) -> Result<Self, TonCellError> {
70 let cell_type = if is_exotic {
71 CellType::determine_exotic_cell_type(&data)?
72 } else {
73 CellType::Ordinary
74 };
75
76 cell_type.validate(&data, bit_len, &references)?;
77 let level_mask = cell_type.level_mask(&data, bit_len, &references)?;
78 let (hashes, depths) =
79 calculate_hashes_and_depths(cell_type, &data, bit_len, &references, level_mask)?;
80
81 let result = Self {
82 data,
83 bit_len,
84 references,
85 level_mask,
86 cell_type,
87 hashes,
88 depths,
89 };
90
91 Ok(result)
92 }
93
94 pub fn parser(&self) -> CellParser<'_> {
95 CellParser::new(self)
96 }
97
98 #[allow(clippy::let_and_return)]
99 pub fn parse<F, T>(&self, parse: F) -> Result<T, TonCellError>
100 where
101 F: FnOnce(&mut CellParser) -> Result<T, TonCellError>,
102 {
103 let mut parser = self.parser();
104 let res = parse(&mut parser);
105 res
106 }
107
108 pub fn parse_fully<F, T>(&self, parse: F) -> Result<T, TonCellError>
109 where
110 F: FnOnce(&mut CellParser) -> Result<T, TonCellError>,
111 {
112 let mut reader = self.parser();
113 let res = parse(&mut reader);
114 reader.ensure_empty()?;
115 res
116 }
117
118 pub fn reference(&self, idx: usize) -> Result<&ArcCell, TonCellError> {
119 self.references.get(idx).ok_or(TonCellError::InvalidIndex {
120 idx,
121 ref_count: self.references.len(),
122 })
123 }
124
125 pub fn data(&self) -> &[u8] {
126 self.data.as_slice()
127 }
128
129 pub fn bit_len(&self) -> usize {
130 self.bit_len
131 }
132
133 pub fn references(&self) -> &[ArcCell] {
134 self.references.as_slice()
135 }
136
137 pub(crate) fn get_level_mask(&self) -> u32 {
138 self.level_mask.mask()
139 }
140
141 pub fn cell_depth(&self) -> u16 {
142 self.get_depth(MAX_LEVEL)
143 }
144
145 pub fn get_depth(&self, level: u8) -> u16 {
146 self.depths[level.min(3) as usize]
147 }
148
149 pub fn cell_hash(&self) -> TonHash {
150 self.get_hash(MAX_LEVEL)
151 }
152
153 pub fn get_hash(&self, level: u8) -> TonHash {
154 self.hashes[level.min(3) as usize].clone()
155 }
156
157 pub fn is_exotic(&self) -> bool {
158 self.cell_type != CellType::Ordinary
159 }
160
161 pub fn is_library(&self) -> bool {
162 self.cell_type == CellType::Library
163 }
164
165 pub fn cell_hash_base64(&self) -> String {
166 self.cell_hash().to_base64()
167 }
168
169 pub fn load_snake_formatted_string(&self) -> Result<String, TonCellError> {
170 let mut cell: &Cell = self;
171 let mut first_cell = true;
172 let mut uri = String::new();
173 loop {
174 let parsed_cell = if first_cell {
175 String::from_utf8_lossy(&cell.data[1..]).to_string()
176 } else {
177 String::from_utf8_lossy(&cell.data).to_string()
178 };
179 uri.push_str(&parsed_cell);
180 match cell.references.len() {
181 0 => return Ok(uri),
182 1 => {
183 cell = cell.references[0].deref();
184 first_cell = false;
185 }
186 n => {
187 return Err(TonCellError::boc_deserialization_error(format!(
188 "Invalid snake format string: found cell with {} references",
189 n
190 )))
191 }
192 }
193 }
194 }
195
196 fn parse_snake_data(&self, buffer: &mut Vec<u8>) -> Result<(), TonCellError> {
197 let mut cell = self;
198 let mut first_cell = true;
199 loop {
200 let mut parser = cell.parser();
201 if first_cell {
202 let first_byte = parser.load_u8(8)?;
203
204 if first_byte != 0 {
205 return Err(TonCellError::boc_deserialization_error(
206 "Invalid snake format",
207 ));
208 }
209 }
210 let remaining_bytes = parser.remaining_bytes();
211 let mut data = parser.load_bytes(remaining_bytes)?;
212 buffer.append(&mut data);
213 match cell.references.len() {
214 0 => return Ok(()),
215 1 => {
216 cell = cell.references[0].deref();
217 first_cell = false;
218 }
219 n => {
220 return Err(TonCellError::boc_deserialization_error(format!(
221 "Invalid snake format string: found cell with {} references",
222 n
223 )))
224 }
225 }
226 }
227 }
228
229 pub fn to_arc(self) -> ArcCell {
230 Arc::new(self)
231 }
232
233 #[deprecated]
235 pub fn expect_reference_count(&self, expected_refs: usize) -> Result<(), TonCellError> {
236 let ref_count = self.references.len();
237 if ref_count != expected_refs {
238 Err(TonCellError::CellParserError(format!(
239 "Cell should contain {} reference cells, actual: {}",
240 expected_refs, ref_count
241 )))
242 } else {
243 Ok(())
244 }
245 }
246}
247
248impl Debug for Cell {
249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250 write_cell_debug(f, self, 0)
251 }
252}
253
254impl Default for Cell {
255 fn default() -> Self {
256 Self {
257 data: Default::default(),
258 bit_len: Default::default(),
259 references: Default::default(),
260 cell_type: Default::default(),
261 level_mask: Default::default(),
262 hashes: [DEFAULT_CELL_HASH; 4],
263 depths: Default::default(),
264 }
265 }
266}
267
268fn get_repr_for_data(
269 original_data_bit_len: usize,
270 (data, data_bit_len): (&[u8], usize),
271 refs: &[ArcCell],
272 level_mask: LevelMask,
273 level: u8,
274 cell_type: CellType,
275) -> Result<Vec<u8>, TonCellError> {
276 let data_len = data.len();
278 let buffer_len = 2 + data_len + (32 + 2) * refs.len();
280
281 let mut writer = BitWriter::endian(Vec::with_capacity(buffer_len), BigEndian);
282 let d1 = get_refs_descriptor(cell_type, refs, level_mask.apply(level).mask())?;
283 let d2 = get_bits_descriptor(original_data_bit_len)?;
284
285 writer.write_var(8, d1).map_cell_parser_error()?;
287 writer.write_var(8, d2).map_cell_parser_error()?;
288 write_data(&mut writer, data, data_bit_len).map_cell_parser_error()?;
290 write_ref_depths(&mut writer, refs, cell_type, level)?;
292 write_ref_hashes(&mut writer, refs, cell_type, level)?;
293
294 let result = writer
295 .writer()
296 .ok_or_else(|| TonCellError::cell_builder_error("Stream for cell repr is not byte-aligned"))
297 .map(|b| b.to_vec());
298
299 result
300}
301
302fn calculate_hashes_and_depths(
305 cell_type: CellType,
306 data: &[u8],
307 bit_len: usize,
308 references: &[ArcCell],
309 level_mask: LevelMask,
310) -> Result<([TonHash; 4], [u16; 4]), TonCellError> {
311 let hash_count = if cell_type == CellType::PrunedBranch {
312 1
313 } else {
314 level_mask.hash_count()
315 };
316
317 let total_hash_count = level_mask.hash_count();
318 let hash_i_offset = total_hash_count - hash_count;
319
320 let mut depths: Vec<u16> = Vec::with_capacity(hash_count);
321 let mut hashes: Vec<TonHash> = Vec::with_capacity(hash_count);
322
323 for (hash_i, level_i) in (0..=level_mask.level())
325 .filter(|&i| level_mask.is_significant(i))
326 .enumerate()
327 {
328 if hash_i < hash_i_offset {
329 continue;
330 }
331
332 let (current_data, current_bit_len) = if hash_i == hash_i_offset {
333 (data, bit_len)
334 } else {
335 let previous_hash = hashes
336 .get(hash_i - hash_i_offset - 1)
337 .ok_or_else(|| TonCellError::InternalError("Can't get right hash".to_owned()))?;
338 (previous_hash.as_slice(), 256)
339 };
340
341 let depth = if references.is_empty() {
343 0
344 } else {
345 let max_ref_depth = references.iter().fold(0, |max_depth, reference| {
346 let child_depth = cell_type.child_depth(reference, level_i);
347 max_depth.max(child_depth)
348 });
349
350 max_ref_depth + 1
351 };
352
353 let repr = get_repr_for_data(
355 bit_len,
356 (current_data, current_bit_len),
357 references,
358 level_mask,
359 level_i,
360 cell_type,
361 )?;
362 let hash = Sha256::new_with_prefix(repr).finalize()[..]
363 .try_into()
364 .map_err(|error| {
365 TonCellError::InternalError(format!(
366 "Can't get [u8; 32] from finalized hash with error: {error}"
367 ))
368 })?;
369
370 depths.push(depth);
371 hashes.push(hash);
372 }
373
374 cell_type.resolve_hashes_and_depths(hashes, depths, data, bit_len, level_mask)
375}
376
377fn get_refs_descriptor(
380 cell_type: CellType,
381 references: &[ArcCell],
382 level_mask: u32,
383) -> Result<u8, TonCellError> {
384 if references.len() > MAX_CELL_REFERENCES {
385 Err(TonCellError::InvalidCellData(
386 "Cell should not contain more than 4 references".to_string(),
387 ))
388 } else if level_mask > MAX_LEVEL_MASK {
389 Err(TonCellError::InvalidCellData(
390 "Cell level mask can not be higher than 3".to_string(),
391 ))
392 } else {
393 let cell_type_var = (cell_type != CellType::Ordinary) as u8;
394 let d1 = references.len() as u8 + 8 * cell_type_var + level_mask as u8 * 32;
395 Ok(d1)
396 }
397}
398
399fn get_bits_descriptor(bit_len: usize) -> Result<u8, TonCellError> {
402 if bit_len > MAX_CELL_BITS {
403 Err(TonCellError::InvalidCellData(
404 "Cell data length should not contain more than 1023 bits".to_string(),
405 ))
406 } else {
407 let d2 = (bit_len / 8 + bit_len.div_ceil(8)) as u8;
408 Ok(d2)
409 }
410}
411
412fn write_data(
413 writer: &mut BitWriter<Vec<u8>, BigEndian>,
414 data: &[u8],
415 bit_len: usize,
416) -> Result<(), io::Error> {
417 let data_len = data.len();
418 let rest_bits = bit_len % 8;
419 let full_bytes = rest_bits == 0;
420
421 if !full_bytes {
422 writer.write_bytes(&data[..data_len - 1])?;
423 let last_byte = data[data_len - 1];
424 let l = last_byte | (1 << (8 - rest_bits - 1));
425 writer.write_var(8, l)?;
426 } else {
427 writer.write_bytes(data)?;
428 }
429
430 Ok(())
431}
432
433fn write_ref_depths(
434 writer: &mut BitWriter<Vec<u8>, BigEndian>,
435 refs: &[ArcCell],
436 parent_cell_type: CellType,
437 level: u8,
438) -> Result<(), TonCellError> {
439 for reference in refs {
440 let child_depth = if matches!(
441 parent_cell_type,
442 CellType::MerkleProof | CellType::MerkleUpdate
443 ) {
444 reference.get_depth(level + 1)
445 } else {
446 reference.get_depth(level)
447 };
448
449 writer
450 .write_var(8, child_depth / 256)
451 .map_cell_parser_error()?;
452 writer
453 .write_var(8, child_depth % 256)
454 .map_cell_parser_error()?;
455 }
456
457 Ok(())
458}
459
460fn write_ref_hashes(
461 writer: &mut BitWriter<Vec<u8>, BigEndian>,
462 refs: &[ArcCell],
463 parent_cell_type: CellType,
464 level: u8,
465) -> Result<(), TonCellError> {
466 for reference in refs {
467 let child_hash = if matches!(
468 parent_cell_type,
469 CellType::MerkleProof | CellType::MerkleUpdate
470 ) {
471 reference.get_hash(level + 1)
472 } else {
473 reference.get_hash(level)
474 };
475
476 writer
477 .write_bytes(child_hash.as_slice())
478 .map_cell_parser_error()?;
479 }
480
481 Ok(())
482}
483
484fn write_cell_debug(
485 f: &mut std::fmt::Formatter<'_>,
486 cell: &Cell,
487 indent_level: usize,
488) -> std::fmt::Result {
489 let indent = " ".repeat(indent_level);
490 let mut data_display: String = cell.data.iter().fold(String::new(), |mut acc, &byte| {
492 acc.push_str(&format!("{:02X}", byte));
493 acc
494 });
495
496 let data_display = if data_display.is_empty() {
497 "_"
498 } else {
499 if !cell.bit_len.is_multiple_of(8) {
504 data_display.push('_');
505 }
506 &data_display
507 };
508
509 if cell.references.is_empty() {
510 writeln!(
512 f,
513 "{}Cell x{{Type: {:?}, data: [{}], bit_len: {}}}",
514 indent, cell.cell_type, data_display, cell.bit_len
515 )
516 } else {
517 writeln!(
519 f,
520 "{}Cell x{{Type: {:?}, data: [{}], bit_len: {}, references: [",
521 indent, cell.cell_type, data_display, cell.bit_len
522 )?;
523 for reference in &cell.references {
524 write_cell_debug(f, reference, indent_level + 1)?;
525 }
526 writeln!(f, "{}]}}", indent)
527 }
528}
529
530#[cfg(test)]
531mod test {
532 use std::sync::Arc;
533
534 use super::cell_type::CellType;
535 use super::{get_bits_descriptor, get_refs_descriptor, Cell};
536 use crate::cell::CellBuilder;
537
538 #[test]
539 fn default_cell() {
540 let result = Cell::default();
541
542 let expected = Cell::new(vec![], 0, vec![], false).unwrap();
543
544 assert_eq!(result, expected)
545 }
546
547 #[test]
548 fn d1_descriptor_test() {
549 let empty_cell = Arc::new(CellBuilder::new().build().unwrap());
550
551 let r1 = get_refs_descriptor(CellType::Ordinary, &[], 0).unwrap();
552 assert_eq!(r1, 0);
553
554 let r2 = get_refs_descriptor(CellType::Ordinary, &[], 4).is_err();
555 assert!(r2);
556
557 let r3 = get_refs_descriptor(CellType::Ordinary, &[empty_cell.clone()], 3).unwrap();
558 assert_eq!(r3, 97);
559
560 let r4 =
561 get_refs_descriptor(CellType::Ordinary, vec![empty_cell; 5].as_slice(), 3).is_err();
562 assert!(r4);
563 }
564
565 #[test]
566 fn d2_descriptor_test() {
567 let r1 = get_bits_descriptor(0).unwrap();
568 assert_eq!(r1, 0);
569
570 let r2 = get_bits_descriptor(1023).unwrap();
571 assert_eq!(r2, 255);
572
573 let r3 = get_bits_descriptor(1024).is_err();
574 assert!(r3)
575 }
576}