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("te6ccgEBAQEAggAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////")?;
201
202        let mut builder = CellBuilder::new();
203        for _ in 0..MAX_BIT_LEN {
204            builder.store_bit_one()?;
205        }
206        assert!(builder.store_bit_one().is_err());
207        let built_cell = builder.build()?;
208
209        assert_eq!(parsed_cell.repr_hash(), built_cell.repr_hash());
210
211        let mut builder = CellBuilder::new();
212        builder.store_bit_one()?;
213        builder.store_u128(0xaaffaaffaaffaaffaaffaaffaaffaaff)?;
214        let cell = builder.build()?;
215
216        let mut builder = CellBuilder::new();
217        builder.store_bit_one()?;
218        builder.store_u64(0xaaffaaffaaffaaff)?;
219        builder.store_u64(0xaaffaaffaaffaaff)?;
220        assert_eq!(cell.as_ref(), builder.build()?.as_ref());
221
222        let mut builder = CellBuilder::new();
223        builder.store_zeros(1020)?;
224        builder.store_small_uint(0x5, 3)?;
225        builder.build()?;
226
227        let mut builder = CellBuilder::new();
228        builder.store_small_uint(5, 3)?;
229        builder.store_u256(HashBytes::wrap(&[
230            0xdf, 0x86, 0xce, 0xbc, 0xe8, 0xd5, 0xab, 0x0c, 0x69, 0xb4, 0xce, 0x33, 0xfe, 0x9b,
231            0x0e, 0x2c, 0xdf, 0x69, 0xa3, 0xe1, 0x13, 0x7e, 0x64, 0x85, 0x6b, 0xbc, 0xfd, 0x39,
232            0xe7, 0x9b, 0xc1, 0x6f,
233        ]))?;
234        let cell = builder.build()?;
235
236        let target_cell =
237            Boc::decode_base64("te6ccgEBAQEAIwAAQbvw2dedGrVhjTaZxn/TYcWb7TR8Im/MkK13n6c883gt8A==")?;
238        assert_eq!(cell.as_ref(), target_cell.as_ref());
239
240        let mut builder = CellBuilder::new();
241        builder.store_zeros(3)?;
242        builder.store_raw(&[0xdd, 0x55], 10)?;
243        builder.store_reference(target_cell)?;
244        builder.store_reference(cell)?;
245        let cell = builder.build()?;
246
247        let mut builder = CellBuilder::new();
248        builder.store_slice(cell.as_slice()?)?;
249        let cell = builder.build()?;
250        println!("{}", cell.display_tree());
251
252        Ok(())
253    }
254
255    #[test]
256    fn test_tx() {
257        let cell = Boc::decode_base64("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").unwrap();
258
259        let stats = cell.compute_unique_stats(1 << 22).unwrap();
260        assert_eq!(stats, CellTreeStats {
261            bit_count: 4681,
262            cell_count: 266
263        });
264    }
265}