Skip to main content

tycho_types/models/message/
address.rs

1use std::str::FromStr;
2
3use crate::cell::*;
4use crate::error::{Error, ParseAddrError};
5use crate::models::block::ShardIdent;
6use crate::models::message::{load_ext_addr, store_ext_addr};
7use crate::num::*;
8use crate::util::*;
9
10/// Basic internal address trait.
11pub trait Addr {
12    /// Returns the workchain part of the address.
13    fn workchain(&self) -> i32;
14    /// Returns the high bits of the address as a number.
15    fn prefix(&self) -> u64;
16}
17
18/// Any possible address of specification
19#[derive(Default, Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
20pub enum AnyAddr {
21    /// Empty address. 2 zero bits
22    #[default]
23    None,
24    /// External address
25    Ext(ExtAddr),
26    /// Standard internal address
27    Std(StdAddr),
28    /// Variable-length internal address
29    Var(VarAddr),
30}
31
32impl AnyAddr {
33    /// Returns the number of data bits that this struct occupies.
34    pub fn bit_len(&self) -> u16 {
35        match self {
36            AnyAddr::None => 2, // 2 bits of zeroes
37            AnyAddr::Ext(addr) => addr.bit_len(),
38            AnyAddr::Std(addr) => addr.bit_len(),
39            AnyAddr::Var(addr) => addr.bit_len(),
40        }
41    }
42}
43
44impl Store for AnyAddr {
45    fn store_into(
46        &self,
47        builder: &mut CellBuilder,
48        context: &dyn CellContext,
49    ) -> Result<(), Error> {
50        match self {
51            Self::None => store_ext_addr(builder, context, &None),
52            Self::Std(addr) => addr.store_into(builder, context),
53            Self::Var(addr) => addr.store_into(builder, context),
54            Self::Ext(addr) => store_ext_addr(builder, context, &Some(addr.clone())),
55        }
56    }
57}
58
59impl<'a> Load<'a> for AnyAddr {
60    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
61        let addr = if ok!(slice.get_bit(0)) {
62            let addr = ok!(IntAddr::load_from(slice));
63            match addr {
64                IntAddr::Std(addr) => Self::Std(addr),
65                IntAddr::Var(addr) => Self::Var(addr),
66            }
67        } else {
68            match ok!(load_ext_addr(slice)) {
69                Some(addr) => Self::Ext(addr),
70                None => Self::None,
71            }
72        };
73
74        Ok(addr)
75    }
76}
77
78// for all
79impl From<Option<ExtAddr>> for AnyAddr {
80    fn from(value: Option<ExtAddr>) -> Self {
81        if let Some(addr) = value {
82            AnyAddr::Ext(addr)
83        } else {
84            AnyAddr::None
85        }
86    }
87}
88
89impl From<Option<IntAddr>> for AnyAddr {
90    fn from(value: Option<IntAddr>) -> Self {
91        match value {
92            Some(IntAddr::Std(addr)) => AnyAddr::Std(addr),
93            Some(IntAddr::Var(addr)) => AnyAddr::Var(addr),
94            None => AnyAddr::None,
95        }
96    }
97}
98
99impl From<IntAddr> for AnyAddr {
100    fn from(value: IntAddr) -> Self {
101        match value {
102            IntAddr::Std(addr) => AnyAddr::Std(addr),
103            IntAddr::Var(addr) => AnyAddr::Var(addr),
104        }
105    }
106}
107
108impl From<ExtAddr> for AnyAddr {
109    fn from(value: ExtAddr) -> Self {
110        AnyAddr::Ext(value)
111    }
112}
113
114impl From<StdAddr> for AnyAddr {
115    fn from(value: StdAddr) -> Self {
116        AnyAddr::Std(value)
117    }
118}
119
120impl From<VarAddr> for AnyAddr {
121    fn from(value: VarAddr) -> Self {
122        AnyAddr::Var(value)
123    }
124}
125
126/// Internal message address.
127#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
128pub enum IntAddr {
129    /// Standard internal address.
130    Std(StdAddr),
131    /// Variable-length internal address.
132    Var(VarAddr),
133}
134
135impl Default for IntAddr {
136    #[inline]
137    fn default() -> Self {
138        Self::Std(StdAddr::default())
139    }
140}
141
142impl IntAddr {
143    /// The maximum number of bits that address occupies.
144    pub const BITS_MAX: u16 = 1 + VarAddr::BITS_MAX;
145
146    /// Returns `true` if this address is for a masterchain block.
147    ///
148    /// See [`ShardIdent::MASTERCHAIN`]
149    #[inline]
150    pub const fn is_masterchain(&self) -> bool {
151        self.workchain() == ShardIdent::MASTERCHAIN.workchain()
152    }
153
154    /// Returns the workchain part of the address.
155    #[inline]
156    pub const fn workchain(&self) -> i32 {
157        match self {
158            Self::Std(addr) => addr.workchain as i32,
159            Self::Var(addr) => addr.workchain,
160        }
161    }
162
163    /// Returns the workchain part of the address.
164    #[inline]
165    pub const fn anycast(&self) -> &Option<Box<Anycast>> {
166        match self {
167            Self::Std(addr) => &addr.anycast,
168            Self::Var(addr) => &addr.anycast,
169        }
170    }
171
172    /// Returns the underlying standard address.
173    #[inline]
174    pub const fn as_std(&self) -> Option<&StdAddr> {
175        match self {
176            Self::Std(addr) => Some(addr),
177            Self::Var(_) => None,
178        }
179    }
180
181    /// Returns the underlying variable-length address.
182    #[inline]
183    pub const fn as_var(&self) -> Option<&VarAddr> {
184        match self {
185            Self::Std(_) => None,
186            Self::Var(addr) => Some(addr),
187        }
188    }
189
190    /// Returns the number of data bits that this struct occupies.
191    pub const fn bit_len(&self) -> u16 {
192        match self {
193            Self::Std(addr) => addr.bit_len(),
194            Self::Var(addr) => addr.bit_len(),
195        }
196    }
197
198    /// Returns the high bits of the address as a number.
199    pub fn prefix(&self) -> u64 {
200        match self {
201            Self::Std(addr) => addr.prefix(),
202            Self::Var(addr) => addr.prefix(),
203        }
204    }
205}
206
207impl Addr for IntAddr {
208    #[inline]
209    fn workchain(&self) -> i32 {
210        IntAddr::workchain(self)
211    }
212
213    #[inline]
214    fn prefix(&self) -> u64 {
215        IntAddr::prefix(self)
216    }
217}
218
219impl From<(i8, HashBytes)> for IntAddr {
220    #[inline]
221    fn from((workchain, address): (i8, HashBytes)) -> Self {
222        IntAddr::Std(StdAddr::new(workchain, address))
223    }
224}
225
226impl FromStr for IntAddr {
227    type Err = ParseAddrError;
228
229    fn from_str(s: &str) -> Result<Self, Self::Err> {
230        // TODO: impl from_str for VarAddr
231        Ok(Self::Std(ok!(StdAddr::from_str(s))))
232    }
233}
234
235impl std::fmt::Display for IntAddr {
236    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237        match self {
238            IntAddr::Std(addr) => std::fmt::Display::fmt(addr, f),
239            IntAddr::Var(_) => f.write_str("varaddr"), // TODO: impl display
240        }
241    }
242}
243
244impl Store for IntAddr {
245    fn store_into(
246        &self,
247        builder: &mut CellBuilder,
248        context: &dyn CellContext,
249    ) -> Result<(), Error> {
250        match self {
251            Self::Std(addr) => addr.store_into(builder, context),
252            Self::Var(addr) => addr.store_into(builder, context),
253        }
254    }
255}
256
257impl<'a> Load<'a> for IntAddr {
258    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
259        if !ok!(slice.load_bit()) {
260            return Err(Error::InvalidTag);
261        }
262
263        Ok(if unlikely(ok!(slice.load_bit())) {
264            let anycast = ok!(Option::<Box<Anycast>>::load_from(slice));
265            let address_len = ok!(Uint9::load_from(slice));
266            let workchain = ok!(slice.load_u32()) as i32;
267            if !slice.has_remaining(address_len.into_inner(), 0) {
268                return Err(Error::CellUnderflow);
269            }
270
271            let mut address = vec![0; address_len.into_inner().div_ceil(8) as usize];
272            ok!(slice.load_raw(&mut address, address_len.into_inner()));
273
274            Self::Var(VarAddr {
275                anycast,
276                address_len,
277                workchain,
278                address,
279            })
280        } else {
281            Self::Std(StdAddr {
282                anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
283                workchain: ok!(slice.load_u8()) as i8,
284                address: ok!(slice.load_u256()),
285            })
286        })
287    }
288}
289
290#[cfg(feature = "serde")]
291impl serde::Serialize for IntAddr {
292    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
293    where
294        S: serde::Serializer,
295    {
296        match self {
297            Self::Std(addr) => addr.serialize(serializer),
298            Self::Var(_) => {
299                // TODO: impl serde for `VarAddr`
300                serializer.serialize_str("varaddr")
301            }
302        }
303    }
304}
305
306#[cfg(feature = "serde")]
307impl<'de> serde::Deserialize<'de> for IntAddr {
308    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
309    where
310        D: serde::Deserializer<'de>,
311    {
312        // TODO: impl serde for `VarAddr`
313        StdAddr::deserialize(deserializer).map(IntAddr::Std)
314    }
315}
316
317#[cfg(feature = "arbitrary")]
318impl<'a> arbitrary::Arbitrary<'a> for IntAddr {
319    #[inline]
320    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
321        if u.ratio(1u8, 20u8)? {
322            u.arbitrary().map(Self::Var)
323        } else {
324            u.arbitrary().map(Self::Std)
325        }
326    }
327
328    #[inline]
329    fn size_hint(depth: usize) -> (usize, Option<usize>) {
330        Self::try_size_hint(depth).unwrap_or_default()
331    }
332
333    #[inline]
334    fn try_size_hint(
335        depth: usize,
336    ) -> Result<(usize, Option<usize>), arbitrary::MaxRecursionReached> {
337        Ok(arbitrary::size_hint::and(
338            <u8 as arbitrary::Arbitrary>::try_size_hint(depth)?,
339            arbitrary::size_hint::or(StdAddr::size_hint(depth), VarAddr::size_hint(depth)),
340        ))
341    }
342}
343
344/// Standard internal address.
345#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
346pub struct StdAddr {
347    /// Optional anycast info.
348    pub anycast: Option<Box<Anycast>>,
349    /// Workchain id (one-byte range).
350    pub workchain: i8,
351    /// Account id.
352    pub address: HashBytes,
353}
354
355impl StdAddr {
356    /// The number of data bits that address without anycast occupies.
357    ///
358    /// - 2 bits id (`0b10`)
359    /// - 1 bit Maybe None
360    /// - 8 bits workchain
361    /// - 256 bits address
362    pub const BITS_WITHOUT_ANYCAST: u16 = 2 + 1 + 8 + 256;
363
364    /// The maximum number of bits that address with anycast occupies.
365    pub const BITS_MAX: u16 = Self::BITS_WITHOUT_ANYCAST + Anycast::BITS_MAX;
366
367    /// Address with all values set as zero (e.g. `0:000...000`).
368    ///
369    /// Same as `StdAddr::default()`.
370    pub const ZERO: Self = Self::new(0, HashBytes::ZERO);
371
372    /// Constructs a new masterchain standard address without anycast info.
373    pub const fn new_masterchain(address: HashBytes) -> Self {
374        Self {
375            anycast: None,
376            workchain: ShardIdent::MASTERCHAIN.workchain() as i8,
377            address,
378        }
379    }
380
381    /// Constructs a new standard address without anycast info.
382    #[inline]
383    pub const fn new(workchain: i8, address: HashBytes) -> Self {
384        Self {
385            anycast: None,
386            workchain,
387            address,
388        }
389    }
390
391    /// Parses a base64-encoded address.
392    #[cfg(feature = "base64")]
393    pub fn from_str_ext(
394        s: &str,
395        format: StdAddrFormat,
396    ) -> Result<(Self, Base64StdAddrFlags), ParseAddrError> {
397        use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
398
399        match s.len() {
400            0 => Err(ParseAddrError::Empty),
401            66..=69 if format.allow_raw => Self::from_str(s).map(|addr| (addr, Default::default())),
402            48 if format.allow_base64 || format.allow_base64_url => {
403                let mut buffer = [0u8; 36];
404
405                let base64_url = s.contains(['_', '-']);
406
407                let Ok(36) = if base64_url {
408                    BASE64_URL_SAFE
409                } else {
410                    BASE64_STANDARD
411                }
412                .decode_slice(s, &mut buffer) else {
413                    return Err(ParseAddrError::BadFormat);
414                };
415
416                #[cfg(not(fuzzing))]
417                {
418                    let crc = crate::crc::crc_16(&buffer[..34]);
419                    if buffer[34] as u16 != (crc >> 8) || buffer[35] as u16 != (crc & 0xff) {
420                        return Err(ParseAddrError::BadFormat);
421                    }
422                }
423
424                let addr = StdAddr::new(
425                    buffer[1] as i8,
426                    HashBytes(buffer[2..34].try_into().unwrap()),
427                );
428                let flags = Base64StdAddrFlags {
429                    testnet: buffer[0] & 0x80 != 0,
430                    base64_url,
431                    bounceable: buffer[0] & 0x40 == 0,
432                };
433                Ok((addr, flags))
434            }
435            _ => Err(ParseAddrError::BadFormat),
436        }
437    }
438
439    /// Returns `true` if this address is for a masterchain block.
440    ///
441    /// See [`ShardIdent::MASTERCHAIN`]
442    #[inline]
443    pub const fn is_masterchain(&self) -> bool {
444        self.workchain as i32 == ShardIdent::MASTERCHAIN.workchain()
445    }
446
447    /// Returns `true` if this address is `0:000...000`.
448    pub const fn is_zero(&self) -> bool {
449        self.workchain == 0 && self.anycast.is_none() && self.address.is_zero()
450    }
451
452    /// Returns the number of data bits that this struct occupies.
453    pub const fn bit_len(&self) -> u16 {
454        let mut bit_len = Self::BITS_WITHOUT_ANYCAST;
455        if let Some(anycast) = &self.anycast {
456            bit_len += anycast.bit_len();
457        }
458        bit_len
459    }
460
461    /// Returns the high bits of the address as a number.
462    pub const fn prefix(&self) -> u64 {
463        u64::from_be_bytes(*self.address.first_chunk())
464    }
465
466    /// Returns a pretty-printer for base64-encoded address.
467    #[cfg(feature = "base64")]
468    pub const fn display_base64(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
469        DisplayBase64StdAddr {
470            addr: self,
471            flags: Base64StdAddrFlags {
472                testnet: false,
473                base64_url: false,
474                bounceable,
475            },
476        }
477    }
478
479    /// Returns a pretty-printer for URL-safe base64-encoded address.
480    #[cfg(feature = "base64")]
481    pub const fn display_base64_url(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
482        DisplayBase64StdAddr {
483            addr: self,
484            flags: Base64StdAddrFlags {
485                testnet: false,
486                base64_url: true,
487                bounceable,
488            },
489        }
490    }
491}
492
493impl Default for StdAddr {
494    #[inline]
495    fn default() -> Self {
496        Self::ZERO
497    }
498}
499
500impl Addr for StdAddr {
501    #[inline]
502    fn workchain(&self) -> i32 {
503        self.workchain as i32
504    }
505
506    #[inline]
507    fn prefix(&self) -> u64 {
508        StdAddr::prefix(self)
509    }
510}
511
512impl std::fmt::Display for StdAddr {
513    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
514        if let Some(anycast) = &self.anycast {
515            ok!(f.write_fmt(format_args!("{anycast}:")))
516        }
517
518        f.write_fmt(format_args!("{}:{}", self.workchain, self.address))
519    }
520}
521
522impl From<(i8, HashBytes)> for StdAddr {
523    #[inline]
524    fn from((workchain, address): (i8, HashBytes)) -> Self {
525        Self::new(workchain, address)
526    }
527}
528
529impl From<(i8, [u8; 32])> for StdAddr {
530    #[inline]
531    fn from((workchain, address): (i8, [u8; 32])) -> Self {
532        Self::new(workchain, HashBytes(address))
533    }
534}
535
536impl From<StdAddr> for IntAddr {
537    #[inline]
538    fn from(value: StdAddr) -> Self {
539        Self::Std(value)
540    }
541}
542
543impl FromStr for StdAddr {
544    type Err = ParseAddrError;
545
546    fn from_str(s: &str) -> Result<Self, Self::Err> {
547        if s.is_empty() {
548            return Err(ParseAddrError::Empty);
549        }
550
551        let mut result = Self::default();
552
553        let mut parts = s.split(':');
554        match parts.next() {
555            Some(part) => match part.parse() {
556                Ok(workchain) => result.workchain = workchain,
557                Err(_) => return Err(ParseAddrError::InvalidWorkchain),
558            },
559            None => return Err(ParseAddrError::Empty),
560        }
561
562        match parts.next() {
563            Some(part) => match hex::decode_to_slice(part, &mut result.address.0) {
564                Ok(()) => {}
565                Err(_) => return Err(ParseAddrError::InvalidAccountId),
566            },
567            None => return Err(ParseAddrError::InvalidAccountId),
568        }
569
570        if parts.next().is_none() {
571            Ok(result)
572        } else {
573            Err(ParseAddrError::UnexpectedPart)
574        }
575    }
576}
577
578impl Store for StdAddr {
579    fn store_into(
580        &self,
581        builder: &mut CellBuilder,
582        context: &dyn CellContext,
583    ) -> Result<(), Error> {
584        if !builder.has_capacity(self.bit_len(), 0) {
585            return Err(Error::CellOverflow);
586        }
587        ok!(builder.store_small_uint(0b10, 2));
588        ok!(self.anycast.store_into(builder, context));
589        ok!(builder.store_u8(self.workchain as u8));
590        builder.store_u256(&self.address)
591    }
592}
593
594impl<'a> Load<'a> for StdAddr {
595    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
596        if !ok!(slice.load_bit()) || ok!(slice.load_bit()) {
597            return Err(Error::InvalidTag);
598        }
599
600        Ok(Self {
601            anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
602            workchain: ok!(slice.load_u8()) as i8,
603            address: ok!(slice.load_u256()),
604        })
605    }
606}
607
608impl crate::dict::DictKey for StdAddr {
609    const BITS: u16 = StdAddr::BITS_WITHOUT_ANYCAST;
610}
611
612impl crate::dict::StoreDictKey for StdAddr {
613    fn store_into_data(&self, builder: &mut CellDataBuilder) -> Result<(), Error> {
614        if self.anycast.is_some() || !builder.has_capacity_bits(Self::BITS_WITHOUT_ANYCAST) {
615            return Err(Error::InvalidData);
616        }
617        ok!(builder.store_small_uint(0b100, 3)); // `0b10` (tag) | `0b0` ("none" for anycast)
618        ok!(builder.store_u8(self.workchain as u8));
619        builder.store_u256(&self.address)
620    }
621}
622
623impl crate::dict::LoadDictKey for StdAddr {
624    fn load_from_data(data: &CellDataBuilder) -> Option<Self> {
625        let [first_byte, second_byte, data @ ..] = data.raw_data();
626
627        // 2 bits id, 1 bit maybe (None), 8 bits workchain, 256 bits address
628
629        const PREFIX_BITS: u8 = 0b1000_0000;
630        const PREFIX_MASK: u8 = 0b1110_0000;
631
632        const R: u8 = 3;
633        const SHIFT: u8 = 8 - R;
634        const REV_SHIFT: u8 = 120 + R;
635
636        if unlikely((first_byte ^ PREFIX_BITS) & PREFIX_MASK != 0) {
637            return None;
638        }
639
640        let mut result = Self {
641            anycast: None,
642            // 100xxxxx | xxxaaaaa -> xxxxxxxx
643            workchain: ((first_byte << R) | (second_byte >> SHIFT)) as i8,
644            address: HashBytes::ZERO,
645        };
646
647        // SAFETY: transmuting [u8; 32] to [u128; 2] is safe
648        let [mut hi, mut lo]: [u128; 2] =
649            unsafe { std::mem::transmute::<[u8; 32], _>(data[..32].try_into().unwrap()) };
650
651        // Numbers are in big endian order, swap bytes on little endian arch
652        #[cfg(target_endian = "little")]
653        {
654            hi = hi.swap_bytes();
655            lo = lo.swap_bytes();
656        }
657
658        // SAFETY: transmuting [[u8; 16]; 2] to [u8; 32] is safe
659        result.address = unsafe {
660            std::mem::transmute::<[[u8; 16]; 2], HashBytes>([
661                ((hi >> SHIFT) | ((*second_byte as u128) << REV_SHIFT)).to_be_bytes(),
662                ((lo >> SHIFT) | (hi << REV_SHIFT)).to_be_bytes(),
663            ])
664        };
665
666        Some(result)
667    }
668}
669
670#[cfg(feature = "serde")]
671impl serde::Serialize for StdAddr {
672    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
673    where
674        S: serde::Serializer,
675    {
676        if serializer.is_human_readable() {
677            serializer.collect_str(self)
678        } else {
679            (self.workchain, &self.address).serialize(serializer)
680        }
681    }
682}
683
684#[cfg(feature = "serde")]
685impl<'de> serde::Deserialize<'de> for StdAddr {
686    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
687    where
688        D: serde::Deserializer<'de>,
689    {
690        use serde::de::{Error, Visitor};
691
692        struct StdAddrVisitor;
693
694        impl Visitor<'_> for StdAddrVisitor {
695            type Value = StdAddr;
696
697            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
698                f.write_str("a standard address")
699            }
700
701            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
702            where
703                E: Error,
704            {
705                StdAddr::from_str(v).map_err(E::custom)
706            }
707        }
708
709        if deserializer.is_human_readable() {
710            deserializer.deserialize_str(StdAddrVisitor)
711        } else {
712            <(i8, HashBytes)>::deserialize(deserializer)
713                .map(|(workchain, address)| Self::new(workchain, address))
714        }
715    }
716}
717
718#[cfg(feature = "arbitrary")]
719impl<'a> arbitrary::Arbitrary<'a> for StdAddr {
720    #[inline]
721    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
722        Ok(Self {
723            anycast: u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?,
724            workchain: u.arbitrary()?,
725            address: u.arbitrary()?,
726        })
727    }
728
729    #[inline]
730    fn size_hint(depth: usize) -> (usize, Option<usize>) {
731        arbitrary::size_hint::and(Option::<Anycast>::size_hint(depth), (33, Some(33)))
732    }
733}
734
735/// A helper struct to work with base64-encoded addresses.
736#[cfg(feature = "base64")]
737pub struct StdAddrBase64Repr<const URL_SAFE: bool = true>;
738
739#[cfg(all(feature = "base64", feature = "serde"))]
740impl<const URL_SAFE: bool> StdAddrBase64Repr<URL_SAFE> {
741    /// Serializes address into a base64-encoded string.
742    pub fn serialize<S>(addr: &StdAddr, serializer: S) -> Result<S::Ok, S::Error>
743    where
744        S: serde::Serializer,
745    {
746        serializer.collect_str(&DisplayBase64StdAddr {
747            addr,
748            flags: Base64StdAddrFlags {
749                testnet: false,
750                base64_url: URL_SAFE,
751                bounceable: false,
752            },
753        })
754    }
755
756    /// Deserializes address as a base64-encoded string.
757    pub fn deserialize<'de, D>(deserializer: D) -> Result<StdAddr, D::Error>
758    where
759        D: serde::Deserializer<'de>,
760    {
761        use serde::de::{Error, Visitor};
762
763        struct StdAddrBase64Visitor;
764
765        impl Visitor<'_> for StdAddrBase64Visitor {
766            type Value = StdAddr;
767
768            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
769                f.write_str("a standard address")
770            }
771
772            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
773            where
774                E: Error,
775            {
776                StdAddr::from_str_ext(v, StdAddrFormat::any())
777                    .map(|(addr, _)| addr)
778                    .map_err(E::custom)
779            }
780        }
781
782        deserializer.deserialize_str(StdAddrBase64Visitor)
783    }
784}
785
786/// Parsing options for [`StdAddr::from_str_ext`]
787#[cfg(feature = "base64")]
788#[derive(Debug, Clone, Copy)]
789pub struct StdAddrFormat {
790    /// Allow raw address (0:000...000).
791    pub allow_raw: bool,
792    /// Allow base64-encoded address.
793    pub allow_base64: bool,
794    /// Allow URL-safe base64 encoding.
795    pub allow_base64_url: bool,
796}
797
798#[cfg(feature = "base64")]
799impl StdAddrFormat {
800    /// Allows any address format.
801    pub const fn any() -> Self {
802        StdAddrFormat {
803            allow_raw: true,
804            allow_base64: true,
805            allow_base64_url: true,
806        }
807    }
808}
809
810/// Base64-encoded address flags.
811#[cfg(feature = "base64")]
812#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
813pub struct Base64StdAddrFlags {
814    /// Address belongs to testnet.
815    pub testnet: bool,
816    /// Use URL-safe base64 encoding.
817    pub base64_url: bool,
818    /// Whether to set `bounce` flag during transfer.
819    pub bounceable: bool,
820}
821
822/// Pretty-printer for [`StdAddr`] in base64 format.
823#[cfg(feature = "base64")]
824pub struct DisplayBase64StdAddr<'a> {
825    /// Address to display.
826    pub addr: &'a StdAddr,
827    /// Encoding flags.
828    pub flags: Base64StdAddrFlags,
829}
830
831#[cfg(feature = "base64")]
832impl std::fmt::Display for DisplayBase64StdAddr<'_> {
833    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
834        use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
835
836        let mut buffer = [0u8; 36];
837        buffer[0] = (0x51 - (self.flags.bounceable as i32) * 0x40
838            + (self.flags.testnet as i32) * 0x80) as u8;
839        buffer[1] = self.addr.workchain as u8;
840        buffer[2..34].copy_from_slice(self.addr.address.as_array());
841
842        let crc = crate::crc::crc_16(&buffer[..34]);
843        buffer[34] = (crc >> 8) as u8;
844        buffer[35] = (crc & 0xff) as u8;
845
846        let mut output = [0u8; 48];
847        if self.flags.base64_url {
848            BASE64_URL_SAFE
849        } else {
850            BASE64_STANDARD
851        }
852        .encode_slice(buffer, &mut output)
853        .unwrap();
854
855        // SAFETY: output is guaranteed to contain only ASCII.
856        let output = unsafe { std::str::from_utf8_unchecked(&output) };
857        f.write_str(output)
858    }
859}
860
861/// Variable-length internal address.
862#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
863pub struct VarAddr {
864    /// Optional anycast info.
865    pub anycast: Option<Box<Anycast>>,
866    /// Address length in bits.
867    pub address_len: Uint9,
868    /// Workchain id (full range).
869    pub workchain: i32,
870    /// Variable-length address.
871    pub address: Vec<u8>,
872}
873
874impl VarAddr {
875    /// The maximum number of bits that address occupies.
876    ///
877    /// - 2 bits id (`0b11`)
878    /// - 1 + `Anycast::BITS_MAX` maybe anycast
879    /// - 9 bits `address_len`
880    /// - 32 bits workchain
881    /// - `address_len` bits of address
882    pub const BITS_MAX: u16 =
883        2 + 1 + Anycast::BITS_MAX + Uint9::BITS + 32 + Uint9::MAX.into_inner();
884
885    /// Returns `true` if this address is for a masterchain block.
886    ///
887    /// See [`ShardIdent::MASTERCHAIN`]
888    #[inline]
889    pub const fn is_masterchain(&self) -> bool {
890        self.workchain == ShardIdent::MASTERCHAIN.workchain()
891    }
892
893    /// Returns the number of data bits that this struct occupies.
894    pub const fn bit_len(&self) -> u16 {
895        let mut bit_len = 2 + 1 + Uint9::BITS + 32 + self.address_len.into_inner();
896        if let Some(anycast) = &self.anycast {
897            bit_len += anycast.bit_len();
898        }
899        bit_len
900    }
901
902    /// Returns the high bits of the address as a number.
903    pub fn prefix(&self) -> u64 {
904        let mut prefix = [0; 8];
905        let total_bytes = std::cmp::min(self.address.len(), 8);
906        prefix[..total_bytes].copy_from_slice(&self.address[..total_bytes]);
907        u64::from_be_bytes(prefix)
908    }
909}
910
911impl From<VarAddr> for IntAddr {
912    #[inline]
913    fn from(value: VarAddr) -> Self {
914        Self::Var(value)
915    }
916}
917
918impl Store for VarAddr {
919    fn store_into(
920        &self,
921        builder: &mut CellBuilder,
922        context: &dyn CellContext,
923    ) -> Result<(), Error> {
924        if !builder.has_capacity(self.bit_len(), 0) {
925            return Err(Error::CellOverflow);
926        }
927        ok!(builder.store_small_uint(0b11, 2));
928        ok!(self.anycast.store_into(builder, context));
929        ok!(self.address_len.store_into(builder, context));
930        ok!(builder.store_u32(self.workchain as u32));
931        builder.store_raw(&self.address, self.address_len.into_inner())
932    }
933}
934
935impl Addr for VarAddr {
936    #[inline]
937    fn workchain(&self) -> i32 {
938        self.workchain
939    }
940
941    #[inline]
942    fn prefix(&self) -> u64 {
943        VarAddr::prefix(self)
944    }
945}
946
947#[cfg(feature = "arbitrary")]
948impl<'a> arbitrary::Arbitrary<'a> for VarAddr {
949    #[inline]
950    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
951        let anycast = u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?;
952        let address_len = u.arbitrary::<Uint9>()?;
953        let workchain = u.arbitrary()?;
954
955        let bit_len = address_len.into_inner() as usize;
956        let mut address = u.bytes(bit_len.div_ceil(8))?.to_vec();
957        if let Some(last_byte) = address.last_mut() {
958            let rem = bit_len % 8;
959            if rem != 0 {
960                *last_byte &= u8::MAX << (8 - rem);
961            }
962        }
963
964        Ok(Self {
965            anycast,
966            address_len,
967            workchain,
968            address,
969        })
970    }
971
972    #[inline]
973    fn size_hint(_: usize) -> (usize, Option<usize>) {
974        (1 + 2 + 4, None)
975    }
976}
977
978/// External address.
979///
980/// ```text
981/// addr_none$00 = MsgAddressExt;
982/// addr_extern$01 len:(## 9) external_address:(bits len) = MsgAddressExt;
983/// ```
984#[derive(Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
985pub struct ExtAddr {
986    /// Number of bits stored in data.
987    pub data_bit_len: Uint9,
988    /// External address data
989    pub data: Box<[u8]>,
990}
991
992impl ExtAddr {
993    /// Creates non-empty external address.
994    pub fn new<T>(data_bit_len: u16, data: T) -> Option<Self>
995    where
996        T: Into<Vec<u8>>,
997    {
998        let data_bit_len = Uint9::new(data_bit_len);
999        if data_bit_len.is_valid() {
1000            let mut data = data.into();
1001
1002            // Normalize data size.
1003            let bits = data_bit_len.into_inner() as usize;
1004            let bytes = bits.div_ceil(8);
1005            if let Some(additional) = bytes.checked_sub(data.len())
1006                && additional > 0
1007            {
1008                // Use `_exact` here to avoid realloc during the final `into_boxed_slice`.
1009                data.reserve_exact(additional);
1010            }
1011            data.resize(bytes, 0);
1012
1013            // Normalize the trailing bit (remove it).
1014            let rem = bits % 8;
1015            if rem > 0 {
1016                debug_assert!(bytes > 0, "non-zero bits cannot fit into zero bytes");
1017                let tag_mask = 1u8 << (7 - rem);
1018                let data_mask = !(tag_mask - 1) << 1;
1019                data[bytes - 1] &= data_mask;
1020            }
1021
1022            Some(Self {
1023                data_bit_len,
1024                data: data.into_boxed_slice(),
1025            })
1026        } else {
1027            None
1028        }
1029    }
1030
1031    /// Returns the number of data bits that this struct occupies.
1032    pub const fn bit_len(&self) -> u16 {
1033        Uint9::BITS + self.data_bit_len.into_inner()
1034    }
1035}
1036
1037impl std::fmt::Display for ExtAddr {
1038    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1039        let bitstring = Bitstring {
1040            bytes: &self.data,
1041            bit_len: self.data_bit_len.into_inner(),
1042        };
1043        write!(f, ":{bitstring}")
1044    }
1045}
1046
1047impl std::fmt::Debug for ExtAddr {
1048    #[inline]
1049    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1050        std::fmt::Display::fmt(self, f)
1051    }
1052}
1053
1054impl FromStr for ExtAddr {
1055    type Err = ParseAddrError;
1056
1057    fn from_str(s: &str) -> Result<Self, Self::Err> {
1058        if s.is_empty() {
1059            return Err(ParseAddrError::Empty);
1060        }
1061
1062        let Some(s) = s.strip_prefix(':') else {
1063            return Err(ParseAddrError::UnexpectedPart);
1064        };
1065
1066        let Ok((data, bit_len)) = Bitstring::from_hex_str(s) else {
1067            return Err(ParseAddrError::InvalidAccountId);
1068        };
1069
1070        ExtAddr::new(bit_len, data).ok_or(ParseAddrError::UnexpectedPart)
1071    }
1072}
1073
1074#[cfg(feature = "serde")]
1075impl serde::Serialize for ExtAddr {
1076    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1077        if serializer.is_human_readable() {
1078            serializer.collect_str(self)
1079        } else {
1080            (self.data_bit_len.into_inner(), &self.data).serialize(serializer)
1081        }
1082    }
1083}
1084
1085#[cfg(feature = "serde")]
1086impl<'de> serde::Deserialize<'de> for ExtAddr {
1087    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1088        use serde::de::{Error, Visitor};
1089
1090        struct ExtAddrVisitor;
1091
1092        impl Visitor<'_> for ExtAddrVisitor {
1093            type Value = ExtAddr;
1094
1095            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1096                f.write_str("an external address")
1097            }
1098
1099            fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
1100                ExtAddr::from_str(v).map_err(E::custom)
1101            }
1102        }
1103
1104        if deserializer.is_human_readable() {
1105            deserializer.deserialize_str(ExtAddrVisitor)
1106        } else {
1107            <(u16, Vec<u8>)>::deserialize(deserializer).and_then(|(data_bit_len, data)| {
1108                ExtAddr::new(data_bit_len, data)
1109                    .ok_or_else(|| Error::custom("invalid external address data length"))
1110            })
1111        }
1112    }
1113}
1114
1115#[cfg(feature = "arbitrary")]
1116impl<'a> arbitrary::Arbitrary<'a> for ExtAddr {
1117    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1118        let data_bit_len = u.arbitrary::<Uint9>()?;
1119
1120        let bit_len = data_bit_len.into_inner() as usize;
1121        let mut data = u.bytes(bit_len.div_ceil(8))?.to_vec();
1122        if let Some(last_byte) = data.last_mut() {
1123            let rem = bit_len % 8;
1124            if rem != 0 {
1125                *last_byte &= u8::MAX << (8 - rem);
1126            }
1127        }
1128
1129        Ok(Self {
1130            data_bit_len,
1131            data: data.into_boxed_slice(),
1132        })
1133    }
1134
1135    #[inline]
1136    fn size_hint(_: usize) -> (usize, Option<usize>) {
1137        (2, None)
1138    }
1139}
1140
1141/// Anycast prefix info.
1142///
1143/// ```text
1144/// anycast_info$_ depth:(#<= 30) { depth >= 1 } rewrite_pfx:(bits depth) = Anycast;
1145/// ```
1146#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
1147pub struct Anycast {
1148    /// Prefix length in bits.
1149    pub depth: SplitDepth,
1150    /// Rewrite prefix data.
1151    pub rewrite_prefix: Vec<u8>,
1152}
1153
1154impl Anycast {
1155    /// The minimum allowed number of bits in the rewrite prefix.
1156    pub const MIN_DEPTH: u8 = 1;
1157    /// The maximum allowed number of bits in the rewrite prefix.
1158    pub const MAX_DEPTH: u8 = 30;
1159
1160    /// The maximum number of bits that an Anycast occupies.
1161    pub const BITS_MAX: u16 = SplitDepth::BITS + Self::MAX_DEPTH as u16;
1162
1163    /// Constructs anycast info from rewrite prefix.
1164    pub fn from_slice(rewrite_prefix: &CellSlice<'_>) -> Result<Self, Error> {
1165        let depth = ok!(SplitDepth::from_bit_len(rewrite_prefix.size_bits()));
1166
1167        let mut data = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1168        ok!(rewrite_prefix.get_raw(0, &mut data, depth.into_bit_len()));
1169
1170        Ok(Self {
1171            depth,
1172            rewrite_prefix: data,
1173        })
1174    }
1175
1176    /// Returns the number of data bits that this struct occupies.
1177    pub const fn bit_len(&self) -> u16 {
1178        SplitDepth::BITS + self.depth.into_bit_len()
1179    }
1180}
1181
1182impl std::fmt::Display for Anycast {
1183    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1184        let bitstring = Bitstring {
1185            bytes: &self.rewrite_prefix,
1186            bit_len: self.depth.into_bit_len(),
1187        };
1188        std::fmt::Display::fmt(&bitstring, f)
1189    }
1190}
1191
1192impl Store for Anycast {
1193    fn store_into(
1194        &self,
1195        builder: &mut CellBuilder,
1196        context: &dyn CellContext,
1197    ) -> Result<(), Error> {
1198        if !builder.has_capacity(self.bit_len(), 0) {
1199            return Err(Error::CellOverflow);
1200        }
1201        ok!(self.depth.store_into(builder, context));
1202        builder.store_raw(&self.rewrite_prefix, self.depth.into_bit_len())
1203    }
1204}
1205
1206impl<'a> Load<'a> for Anycast {
1207    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1208        let depth = ok!(SplitDepth::load_from(slice));
1209        if !slice.has_remaining(depth.into_bit_len(), 0) {
1210            return Err(Error::CellUnderflow);
1211        }
1212
1213        let mut rewrite_prefix = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1214        ok!(slice.load_raw(&mut rewrite_prefix, depth.into_bit_len()));
1215
1216        Ok(Self {
1217            depth,
1218            rewrite_prefix,
1219        })
1220    }
1221}
1222
1223#[cfg(feature = "arbitrary")]
1224impl<'a> arbitrary::Arbitrary<'a> for Anycast {
1225    #[inline]
1226    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1227        let split_depth = SplitDepth::arbitrary(u)?;
1228        let bit_len = split_depth.into_bit_len();
1229
1230        let bytes = u.bytes(bit_len.div_ceil(8) as _)?;
1231
1232        let b = CellBuilder::from_raw_data(bytes, bit_len).unwrap();
1233        Ok(Self::from_slice(&b.as_data_slice()).unwrap())
1234    }
1235
1236    #[inline]
1237    fn size_hint(_: usize) -> (usize, Option<usize>) {
1238        (2, Some(5))
1239    }
1240}
1241
1242#[cfg(test)]
1243mod tests {
1244    use super::*;
1245    use crate::dict::Dict;
1246
1247    #[test]
1248    fn dict_with_std_addr_keys() {
1249        let mut dict = Dict::<StdAddr, u32>::new();
1250        dict.set(StdAddr::new(-1, HashBytes([0x33; 32])), 123)
1251            .unwrap();
1252        dict.set(StdAddr::new(0, HashBytes([0x10; 32])), 321)
1253            .unwrap();
1254        dict.set(StdAddr::new(-1, HashBytes([0x55; 32])), 234)
1255            .unwrap();
1256        dict.set(StdAddr::new(0, HashBytes([0x20; 32])), 432)
1257            .unwrap();
1258
1259        for entry in dict.iter() {
1260            let (addr, value) = entry.unwrap();
1261            println!("{addr}: {value}");
1262        }
1263    }
1264
1265    #[test]
1266    fn anycast_str() {
1267        // 0 bit
1268        let empty_res = Anycast::from_slice(&Cell::empty_cell().as_slice().unwrap());
1269        assert_eq!(empty_res.unwrap_err(), Error::IntOverflow);
1270
1271        // 1 bit
1272        let mut prefix = CellBuilder::new();
1273        prefix.store_bit_one().unwrap();
1274        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1275        assert_eq!(anycast.to_string(), "c_");
1276
1277        // 8 bit
1278        let mut prefix = CellBuilder::new();
1279        prefix.store_u8(0xa5).unwrap();
1280        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1281        assert_eq!(anycast.to_string(), "a5");
1282
1283        // 30 bit
1284        let mut prefix = CellBuilder::new();
1285        prefix.store_uint(0xb00b1e5, 28).unwrap();
1286        prefix.store_zeros(2).unwrap();
1287        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1288        assert_eq!(anycast.to_string(), "b00b1e52_");
1289    }
1290
1291    #[test]
1292    fn address_prefix() {
1293        let addr = "0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415"
1294            .parse::<StdAddr>()
1295            .unwrap();
1296        assert_eq!(addr.prefix(), 0xece57bcc6c530283);
1297
1298        let var_addr = VarAddr {
1299            anycast: None,
1300            address_len: Uint9::new(32),
1301            workchain: 0,
1302            address: vec![0xb0, 0xba, 0xca, 0xfe],
1303        };
1304        assert_eq!(var_addr.prefix(), 0xb0bacafe00000000);
1305
1306        let var_addr = VarAddr {
1307            anycast: None,
1308            address_len: Uint9::new(72),
1309            workchain: 0,
1310            address: vec![0xb0, 0xba, 0xca, 0xfe, 0xb0, 0x0b, 0x1e, 0x5a, 0xff],
1311        };
1312        assert_eq!(var_addr.prefix(), 0xb0bacafeb00b1e5a);
1313    }
1314
1315    #[test]
1316    fn base64_address() {
1317        let addr = "0:84545d4d2cada0ce811705d534c298ca42d29315d03a16eee794cefd191dfa79"
1318            .parse::<StdAddr>()
1319            .unwrap();
1320        assert_eq!(
1321            addr.display_base64(true).to_string(),
1322            "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw"
1323        );
1324        assert_eq!(
1325            StdAddr::from_str_ext(
1326                "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw",
1327                StdAddrFormat::any()
1328            )
1329            .unwrap(),
1330            (addr, Base64StdAddrFlags {
1331                testnet: false,
1332                base64_url: false,
1333                bounceable: true,
1334            })
1335        );
1336
1337        let addr = "0:dddde93b1d3398f0b4305c08de9a032e0bc1b257c4ce2c72090aea1ff3e9ecfd"
1338            .parse::<StdAddr>()
1339            .unwrap();
1340        assert_eq!(
1341            addr.display_base64_url(false).to_string(),
1342            "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_Tyv"
1343        );
1344        assert_eq!(
1345            addr.display_base64(false).to_string(),
1346            "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv"
1347        );
1348
1349        assert_eq!(
1350            StdAddr::from_str_ext(
1351                "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv",
1352                StdAddrFormat::any()
1353            )
1354            .unwrap(),
1355            (addr.clone(), Base64StdAddrFlags {
1356                testnet: false,
1357                base64_url: false,
1358                bounceable: false,
1359            })
1360        );
1361
1362        assert_eq!(
1363            addr.display_base64_url(true).to_string(),
1364            "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq"
1365        );
1366        assert_eq!(
1367            addr.display_base64(true).to_string(),
1368            "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/WFq"
1369        );
1370
1371        assert_eq!(
1372            StdAddr::from_str_ext(
1373                "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq",
1374                StdAddrFormat::any()
1375            )
1376            .unwrap(),
1377            (addr, Base64StdAddrFlags {
1378                testnet: false,
1379                base64_url: true,
1380                bounceable: true,
1381            })
1382        );
1383    }
1384
1385    #[test]
1386    fn ext_addr_works() {
1387        for bits in 0..=32 {
1388            let addr = ExtAddr::new(bits, vec![0xaau8; 2]).unwrap();
1389            println!("{addr}");
1390        }
1391    }
1392}