tycho_types/
lib.rs

1#![warn(missing_docs)]
2
3//! Tycho types.
4//!
5//! This crate is a collection of basic structures and models for the
6//! Tycho node. The [`Cell`] represents the core
7//! data structure which is used as an atom for building other structures.
8//!
9//! *Compiler support: [requires `rustc` 1.65+][msrv]*
10//!
11//! [msrv]: #supported-rust-versions
12//!
13//! ## `Cell` vs `CellSlice` vs `CellBuilder`
14//!
15//! - [`Cell`] is an immutable tree and provides only basic methods for accessing
16//!   nodes and some meta info.
17//!
18//! - [`CellSlice`] is a read-only view for a part of some cell. It can only
19//!   be obtained from an existing cell. A cell contains **up to 1023 bits** and
20//!   **up to 4 references**. Minimal data unit is bit, so a cell slice is similar
21//!   to a couple of ranges (bit range and refs range).
22//!
23//! - [`CellBuilder`] is used to create a new cell. It is used as an append-only
24//!   data structure and is the only way to create a new cell with the provided data.
25//!   Cell creation depends on a context (e.g. message creation in a wallet or a
26//!   TVM execution with gas tracking), so [`CellBuilder::build_ext`] accepts
27//!   a [`CellContext`] parameter which can be used to track and modify cells creation.
28//!
29//! ## BOC
30//!
31//! BOC (Bag Of Cells) is a format for representing a tree of cells as bytes.
32//! [`Boc`] type is used to convert between bytes and **cells** of the same family.
33//! [`BocRepr`] helper can be used to convert between bytes and **models** (which
34//! are representable as cells).
35//!
36//! ### Merkle stuff
37//!
38//! - Pruned branch is a "building block" of merkle structures. A single pruned branch
39//!   cell replaces a whole subtree and contains just the hash of its root cell hash.
40//!
41//! - [`MerkleProof`] contains a subset of original tree of cells. In most cases
42//!   it is created from [`UsageTree`] of some visited cells. Merkle proof is used
43//!   to proof that something was presented in the origin tree and provide some additional
44//!   context.
45//!
46//! - [`MerkleUpdate`] describes a difference between two trees of cells. It can be
47//!   applied to old cell to create a new cell.
48//!
49//! ### Numeric stuff
50//!
51//! This crate introduces some unusual number types with custom bit size or variable
52//! encoding. They are only used in models, but may be useful in user code.
53//!
54//! ### Dictionaries
55//!
56//! Dictionary, erroneously called HashmapE in the original TLB schema, is an
57//! important building block of blockchain models. It is similar to `BTreeMap`.
58//! Dictionary is an immutable structure over tree of cells with fixed-length
59//! keys and arbitrary values. Updates create a new cell tree each time, so
60//! it's quite an expensive data structure to work with.
61//!
62//! ### Models
63//!
64//! There is a simple definition of nearly all blockchain models. This definition
65//! doesn't contain any complex logic, but could be extended via extension traits.
66//! The names and structure of the models are slightly different from the
67//! definition in the TLB for the sake of consistency of use.
68//!
69//! All models implement [`Load`] and [`Store`] traits for conversion from/to cells.
70//!
71//! - [`RawDict`] constrains only key size in bits. It is useful when a dictionary
72//!   can contain multiple types of values.
73//!
74//! - [`Dict`] is a strongly typed version of definition and is a preferable way
75//!   of working with this data structure. Key type must implement [`DictKey`] trait,
76//!   which is implemented for numbers and addresses.
77//!
78//! - [`AugDict`] adds additional values for all nodes. You can use it to quickly
79//!   access a subtotal of values for each subtree.
80//!   NOTE: this type is partially implemented due to its complexity.
81//!
82//! ## Supported Rust Versions
83//!
84//! This crate is built against the latest stable release. The minimum supported
85//! version is 1.65. The current crate version is not guaranteed to build on
86//! Rust versions earlier than the minimum supported version.
87//!
88//! [`Cell`]: cell::Cell
89//! [`Rc`]: std::rc::Rc
90//! [`Arc`]: std::sync::Arc
91//! [`RcCell`]: prelude::RcCell
92//! [`ArcCell`]: prelude::ArcCell
93//! [`CellSlice`]: cell::CellSlice
94//! [`CellBuilder`]: cell::CellBuilder
95//! [`Cell::as_slice`]: cell::CellImpl::as_slice
96//! [`CellBuilder::build_ext`]: cell::CellBuilder::build_ext
97//! [`CellContext`]: cell::CellContext
98//! [`Boc`]: boc::Boc
99//! [`BocRepr`]: boc::BocRepr
100//! [`UsageTree`]: cell::UsageTree
101//! [`MerkleProof`]: merkle::MerkleProof
102//! [`MerkleUpdate`]: merkle::MerkleUpdate
103//! [`RawDict`]: dict::RawDict
104//! [`Dict`]: dict::Dict
105//! [`DictKey`]: dict::DictKey
106//! [`AugDict`]: dict::AugDict
107//! [`Load`]: cell::Load
108//! [`Store`]: cell::Store
109/// Prevents using `From::from` for plain error conversion.
110macro_rules! ok {
111    ($e:expr $(,)?) => {
112        match $e {
113            core::result::Result::Ok(val) => val,
114            core::result::Result::Err(err) => return core::result::Result::Err(err),
115        }
116    };
117}
118
119#[allow(unused)]
120macro_rules! assert_impl_all {
121    ($type:ty: $($trait:path),+ $(,)?) => {
122        const _: fn() = || {
123            // Only callable when `$type` implements all traits in `$($trait)+`.
124            fn assert_impl_all<T: ?Sized $(+ $trait)+>() {}
125            assert_impl_all::<$type>();
126        };
127    };
128}
129
130extern crate self as tycho_types;
131
132pub mod boc;
133pub mod cell;
134pub mod crc;
135pub mod dict;
136pub mod merkle;
137pub mod num;
138pub mod prelude;
139pub mod util;
140
141#[cfg(feature = "models")]
142pub mod models;
143
144#[cfg(feature = "abi")]
145pub mod abi;
146
147#[cfg(feature = "arbitrary")]
148pub mod arbitrary;
149
150pub mod error;
151#[cfg(test)]
152mod tests {
153    use crate::cell::{CellTreeStats, MAX_BIT_LEN};
154    use crate::prelude::*;
155    use crate::util::decode_base64;
156
157    #[test]
158    fn correct_deserialization() {
159        let data = decode_base64("te6ccgEBBAEAzwACg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAIBAEAAAAAAAAAAAAAAAAAAAAAAAAAAm2c6ClpzoTVSAHvzVQGDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHKq1w7OAAkYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACRwAwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEljGP8=").unwrap();
160
161        let cell = Boc::decode(&data).unwrap();
162        assert_eq!(cell.repr_hash(), &[
163            0x63, 0xd4, 0x75, 0x13, 0x9a, 0xc1, 0x4f, 0x3e, 0xfe, 0x69, 0x0e, 0xd7, 0xfd, 0x4f,
164            0xf0, 0x02, 0x1c, 0xf2, 0x6b, 0xc4, 0xab, 0xd0, 0xaf, 0x01, 0x40, 0xa3, 0xb4, 0xc8,
165            0x95, 0xf0, 0x73, 0x76
166        ]);
167
168        let serialized = Boc::encode(cell.as_ref());
169        assert_eq!(serialized, data);
170    }
171
172    #[test]
173    fn big_cell_deserialization() {
174        let data = decode_base64("te6ccgIDAAwAAQAAAACIAAAEBAABAAEAAQABAAEEBAACAAIAAgACAAIEBAADAAMAAwADAAMEBAAEAAQABAAEAAQEBAAFAAUABQAFAAUEBAAGAAYABgAGAAYEBAAHAAcABwAHAAcEBAAIAAgACAAIAAgEBAAJAAkACQAJAAkEBAAKAAoACgAKAAoEBAALAAsACwALAAsABAAA").unwrap();
175        let cell = Boc::decode(data).unwrap();
176
177        let stats = cell.compute_unique_stats(1 << 22).unwrap();
178        assert_eq!(stats, CellTreeStats {
179            bit_count: 192,
180            cell_count: 12
181        });
182    }
183
184    #[test]
185    fn test_builder() -> anyhow::Result<()> {
186        let parsed_cell = Boc::decode_base64("te6ccgEBAQEAAwAAAbE=")?;
187
188        let mut builder = CellBuilder::new();
189        builder.store_bit_one()?;
190        builder.store_bit_zero()?;
191        builder.store_bit_one()?;
192        builder.store_bit_one()?;
193        builder.store_bit_zero()?;
194        builder.store_bit_zero()?;
195        builder.store_bit_zero()?;
196        let built_cell = builder.build()?;
197
198        assert_eq!(parsed_cell.repr_hash(), built_cell.repr_hash());
199
200        let parsed_cell = Boc::decode_base64(
201            "te6ccgEBAQEAggAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////",
202        )?;
203
204        let mut builder = CellBuilder::new();
205        for _ in 0..MAX_BIT_LEN {
206            builder.store_bit_one()?;
207        }
208        assert!(builder.store_bit_one().is_err());
209        let built_cell = builder.build()?;
210
211        assert_eq!(parsed_cell.repr_hash(), built_cell.repr_hash());
212
213        let mut builder = CellBuilder::new();
214        builder.store_bit_one()?;
215        builder.store_u128(0xaaffaaffaaffaaffaaffaaffaaffaaff)?;
216        let cell = builder.build()?;
217
218        let mut builder = CellBuilder::new();
219        builder.store_bit_one()?;
220        builder.store_u64(0xaaffaaffaaffaaff)?;
221        builder.store_u64(0xaaffaaffaaffaaff)?;
222        assert_eq!(cell.as_ref(), builder.build()?.as_ref());
223
224        let mut builder = CellBuilder::new();
225        builder.store_zeros(1020)?;
226        builder.store_small_uint(0x5, 3)?;
227        builder.build()?;
228
229        let mut builder = CellBuilder::new();
230        builder.store_small_uint(5, 3)?;
231        builder.store_u256(HashBytes::wrap(&[
232            0xdf, 0x86, 0xce, 0xbc, 0xe8, 0xd5, 0xab, 0x0c, 0x69, 0xb4, 0xce, 0x33, 0xfe, 0x9b,
233            0x0e, 0x2c, 0xdf, 0x69, 0xa3, 0xe1, 0x13, 0x7e, 0x64, 0x85, 0x6b, 0xbc, 0xfd, 0x39,
234            0xe7, 0x9b, 0xc1, 0x6f,
235        ]))?;
236        let cell = builder.build()?;
237
238        let target_cell =
239            Boc::decode_base64("te6ccgEBAQEAIwAAQbvw2dedGrVhjTaZxn/TYcWb7TR8Im/MkK13n6c883gt8A==")?;
240        assert_eq!(cell.as_ref(), target_cell.as_ref());
241
242        let mut builder = CellBuilder::new();
243        builder.store_zeros(3)?;
244        builder.store_raw(&[0xdd, 0x55], 10)?;
245        builder.store_reference(target_cell)?;
246        builder.store_reference(cell)?;
247        let cell = builder.build()?;
248
249        let mut builder = CellBuilder::new();
250        builder.store_slice(cell.as_slice()?)?;
251        let cell = builder.build()?;
252        println!("{}", cell.display_tree());
253
254        Ok(())
255    }
256
257    #[test]
258    fn test_tx() {
259        let cell = Boc::decode_base64("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").unwrap();
260
261        let stats = cell.compute_unique_stats(1 << 22).unwrap();
262        assert_eq!(stats, CellTreeStats {
263            bit_count: 4681,
264            cell_count: 266
265        });
266    }
267}