everscale-types 0.1.2

A set of primitive types and utilities for the Everscale blockchain.
Documentation
#![warn(missing_docs)]

//! Everscale types.
//!
//! This crate is a collection of basic structures and models for the
//! Everscale blockchain. The [`Cell`] represents the core
//! data structure which is used as an atom for building other structures.
//!
//! *Compiler support: [requires `rustc` 1.65+][msrv]*
//!
//! [msrv]: #supported-rust-versions
//!
//! ## `Cell` vs `CellSlice` vs `CellBuilder`
//!
//! - [`Cell`] is an immutable tree and provides only basic methods for accessing
//!   nodes and some meta info.
//!
//! - [`CellSlice`] is a read-only view for a part of some cell. It can only
//!   be obtained from an existing cell. A cell contains **up to 1023 bits** and
//!   **up to 4 references**. Minimal data unit is bit, so a cell slice is similar
//!   to a couple of ranges (bit range and refs range).
//!
//! - [`CellBuilder`] is used to create a new cell. It is used as an append-only
//!   data structure and is the only way to create a new cell with the provided data.
//!   Cell creation depends on a context (e.g. message creation in a wallet or a
//!   TVM execution with gas tracking), so [`CellBuilder::build_ext`] accepts
//!   a [`CellContext`] parameter which can be used to track and modify cells creation.
//!
//! ## BOC
//!
//! BOC (Bag Of Cells) is a format for representing a tree of cells as bytes.
//! [`Boc`] type is used to convert between bytes and **cells** of the same family.
//! [`BocRepr`] helper can be used to convert between bytes and **models** (which
//! are representable as cells).
//!
//! ### Merkle stuff
//!
//! - Pruned branch is a "building block" of merkle structures. A single pruned branch
//!   cell replaces a whole subtree and contains just the hash of its root cell hash.
//!
//! - [`MerkleProof`] contains a subset of original tree of cells. In most cases
//!   it is created from [`UsageTree`] of some visited cells. Merkle proof is used
//!   to proof that something was presented in the origin tree and provide some additional
//!   context.
//!
//! - [`MerkleUpdate`] describes a difference between two trees of cells. It can be
//!   applied to old cell to create a new cell.
//!
//! ### Numeric stuff
//!
//! This crate introduces some unusual number types with custom bit size or variable
//! encoding. They are only used in models, but may be useful in user code.
//!
//! ### Dictionaries
//!
//! Dictionary, erroneously called HashmapE in the original TLB schema, is an
//! important building block of blockchain models. It is similar to `BTreeMap`.
//! Dictionary is an immutable structure over tree of cells with fixed-length
//! keys and arbitrary values. Updates create a new cell tree each time, so
//! it's quite an expensive data structure to work with.
//!
//! ### Models
//!
//! There is a simple definition of nearly all blockchain models. This definition
//! doesn't contain any complex logic, but could be extended via extension traits.
//! The names and structure of the models are slightly different from the
//! definition in the TLB for the sake of consistency of use.
//!
//! All models implement [`Load`] and [`Store`] traits for conversion from/to cells.
//!
//! - [`RawDict`] constrains only key size in bits. It is useful when a dictionary
//!   can contain multiple types of values.
//!
//! - [`Dict`] is a strongly typed version of definition and is a preferable way
//!   of working with this data structure. Key type must implement [`DictKey`] trait,
//!   which is implemented for numbers and addresses.
//!
//! - [`AugDict`] adds additional values for all nodes. You can use it to quickly
//!   access a subtotal of values for each subtree.
//!   NOTE: this type is partially implemented due to its complexity.
//!
//! ## Supported Rust Versions
//!
//! This crate is built against the latest stable release. The minimum supported
//! version is 1.65. The current crate version is not guaranteed to build on
//! Rust versions earlier than the minimum supported version.
//!
//! [`Cell`]: cell::Cell
//! [`Rc`]: std::rc::Rc
//! [`Arc`]: std::sync::Arc
//! [`RcCell`]: prelude::RcCell
//! [`ArcCell`]: prelude::ArcCell
//! [`CellSlice`]: cell::CellSlice
//! [`CellBuilder`]: cell::CellBuilder
//! [`Cell::as_slice`]: cell::CellImpl::as_slice
//! [`CellBuilder::build_ext`]: cell::CellBuilder::build_ext
//! [`CellContext`]: cell::CellContext
//! [`Boc`]: boc::Boc
//! [`BocRepr`]: boc::BocRepr
//! [`UsageTree`]: cell::UsageTree
//! [`MerkleProof`]: merkle::MerkleProof
//! [`MerkleUpdate`]: merkle::MerkleUpdate
//! [`RawDict`]: dict::RawDict
//! [`Dict`]: dict::Dict
//! [`DictKey`]: dict::DictKey
//! [`AugDict`]: dict::AugDict
//! [`Load`]: cell::Load
//! [`Store`]: cell::Store
/// Prevents using `From::from` for plain error conversion.
macro_rules! ok {
    ($e:expr $(,)?) => {
        match $e {
            core::result::Result::Ok(val) => val,
            core::result::Result::Err(err) => return core::result::Result::Err(err),
        }
    };
}

#[allow(unused)]
macro_rules! assert_impl_all {
    ($type:ty: $($trait:path),+ $(,)?) => {
        const _: fn() = || {
            // Only callable when `$type` implements all traits in `$($trait)+`.
            fn assert_impl_all<T: ?Sized $(+ $trait)+>() {}
            assert_impl_all::<$type>();
        };
    };
}

extern crate self as everscale_types;

pub mod boc;
pub mod cell;
pub mod dict;
pub mod merkle;
pub mod num;
pub mod prelude;
pub mod util;

#[cfg(feature = "models")]
pub mod models;

#[cfg(feature = "abi")]
pub mod abi;

pub mod error;

#[cfg(test)]
mod tests {
    use crate::cell::{CellTreeStats, MAX_BIT_LEN};
    use crate::prelude::*;
    use crate::util::decode_base64;

    #[test]
    fn correct_deserialization() {
        let data = decode_base64("te6ccgEBBAEAzwACg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAIBAEAAAAAAAAAAAAAAAAAAAAAAAAAAm2c6ClpzoTVSAHvzVQGDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHKq1w7OAAkYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACRwAwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEljGP8=").unwrap();

        let cell = Boc::decode(&data).unwrap();
        assert_eq!(
            cell.repr_hash(),
            &[
                0x63, 0xd4, 0x75, 0x13, 0x9a, 0xc1, 0x4f, 0x3e, 0xfe, 0x69, 0x0e, 0xd7, 0xfd, 0x4f,
                0xf0, 0x02, 0x1c, 0xf2, 0x6b, 0xc4, 0xab, 0xd0, 0xaf, 0x01, 0x40, 0xa3, 0xb4, 0xc8,
                0x95, 0xf0, 0x73, 0x76
            ]
        );

        let serialized = Boc::encode(cell.as_ref());
        assert_eq!(serialized, data);
    }

    #[test]
    fn big_cell_deserialization() {
        let data = decode_base64("te6ccgIDAAwAAQAAAACIAAAEBAABAAEAAQABAAEEBAACAAIAAgACAAIEBAADAAMAAwADAAMEBAAEAAQABAAEAAQEBAAFAAUABQAFAAUEBAAGAAYABgAGAAYEBAAHAAcABwAHAAcEBAAIAAgACAAIAAgEBAAJAAkACQAJAAkEBAAKAAoACgAKAAoEBAALAAsACwALAAsABAAA").unwrap();
        let cell = Boc::decode(data).unwrap();

        let stats = cell.compute_unique_stats(1 << 22).unwrap();
        assert_eq!(
            stats,
            CellTreeStats {
                bit_count: 192,
                cell_count: 12
            }
        );
    }

    #[test]
    fn test_builder() -> anyhow::Result<()> {
        let parsed_cell = Boc::decode_base64("te6ccgEBAQEAAwAAAbE=")?;

        let mut builder = CellBuilder::new();
        builder.store_bit_one()?;
        builder.store_bit_zero()?;
        builder.store_bit_one()?;
        builder.store_bit_one()?;
        builder.store_bit_zero()?;
        builder.store_bit_zero()?;
        builder.store_bit_zero()?;
        let built_cell = builder.build()?;

        assert_eq!(parsed_cell.repr_hash(), built_cell.repr_hash());

        let parsed_cell = Boc::decode_base64("te6ccgEBAQEAggAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////")?;

        let mut builder = CellBuilder::new();
        for _ in 0..MAX_BIT_LEN {
            builder.store_bit_one()?;
        }
        assert!(builder.store_bit_one().is_err());
        let built_cell = builder.build()?;

        assert_eq!(parsed_cell.repr_hash(), built_cell.repr_hash());

        let mut builder = CellBuilder::new();
        builder.store_bit_one()?;
        builder.store_u128(0xaaffaaffaaffaaffaaffaaffaaffaaff)?;
        let cell = builder.build()?;

        let mut builder = CellBuilder::new();
        builder.store_bit_one()?;
        builder.store_u64(0xaaffaaffaaffaaff)?;
        builder.store_u64(0xaaffaaffaaffaaff)?;
        assert_eq!(cell.as_ref(), builder.build()?.as_ref());

        let mut builder = CellBuilder::new();
        builder.store_zeros(1020)?;
        builder.store_small_uint(0x5, 3)?;
        builder.build()?;

        let mut builder = CellBuilder::new();
        builder.store_small_uint(5, 3)?;
        builder.store_u256(HashBytes::wrap(&[
            0xdf, 0x86, 0xce, 0xbc, 0xe8, 0xd5, 0xab, 0x0c, 0x69, 0xb4, 0xce, 0x33, 0xfe, 0x9b,
            0x0e, 0x2c, 0xdf, 0x69, 0xa3, 0xe1, 0x13, 0x7e, 0x64, 0x85, 0x6b, 0xbc, 0xfd, 0x39,
            0xe7, 0x9b, 0xc1, 0x6f,
        ]))?;
        let cell = builder.build()?;

        let target_cell =
            Boc::decode_base64("te6ccgEBAQEAIwAAQbvw2dedGrVhjTaZxn/TYcWb7TR8Im/MkK13n6c883gt8A==")?;
        assert_eq!(cell.as_ref(), target_cell.as_ref());

        let mut builder = CellBuilder::new();
        builder.store_zeros(3)?;
        builder.store_raw(&[0xdd, 0x55], 10)?;
        builder.store_reference(target_cell)?;
        builder.store_reference(cell)?;
        let cell = builder.build()?;

        let mut builder = CellBuilder::new();
        builder.store_slice(cell.as_slice()?)?;
        let cell = builder.build()?;
        println!("{}", cell.display_tree());

        Ok(())
    }

    #[test]
    fn test_tx() {
        let cell = Boc::decode_base64("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").unwrap();

        let stats = cell.compute_unique_stats(1 << 22).unwrap();
        assert_eq!(
            stats,
            CellTreeStats {
                bit_count: 4681,
                cell_count: 266
            }
        );
    }
}