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 standard address without anycast info.
373    #[inline]
374    pub const fn new(workchain: i8, address: HashBytes) -> Self {
375        Self {
376            anycast: None,
377            workchain,
378            address,
379        }
380    }
381
382    /// Parses a base64-encoded address.
383    #[cfg(feature = "base64")]
384    pub fn from_str_ext(
385        s: &str,
386        format: StdAddrFormat,
387    ) -> Result<(Self, Base64StdAddrFlags), ParseAddrError> {
388        use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
389
390        match s.len() {
391            0 => Err(ParseAddrError::Empty),
392            66..=69 if format.allow_raw => Self::from_str(s).map(|addr| (addr, Default::default())),
393            48 if format.allow_base64 || format.allow_base64_url => {
394                let mut buffer = [0u8; 36];
395
396                let base64_url = s.contains(['_', '-']);
397
398                let Ok(36) = if base64_url {
399                    BASE64_URL_SAFE
400                } else {
401                    BASE64_STANDARD
402                }
403                .decode_slice(s, &mut buffer) else {
404                    return Err(ParseAddrError::BadFormat);
405                };
406
407                #[cfg(not(fuzzing))]
408                {
409                    let crc = crate::crc::crc_16(&buffer[..34]);
410                    if buffer[34] as u16 != (crc >> 8) || buffer[35] as u16 != (crc & 0xff) {
411                        return Err(ParseAddrError::BadFormat);
412                    }
413                }
414
415                let addr = StdAddr::new(
416                    buffer[1] as i8,
417                    HashBytes(buffer[2..34].try_into().unwrap()),
418                );
419                let flags = Base64StdAddrFlags {
420                    testnet: buffer[0] & 0x80 != 0,
421                    base64_url,
422                    bounceable: buffer[0] & 0x40 == 0,
423                };
424                Ok((addr, flags))
425            }
426            _ => Err(ParseAddrError::BadFormat),
427        }
428    }
429
430    /// Returns `true` if this address is for a masterchain block.
431    ///
432    /// See [`ShardIdent::MASTERCHAIN`]
433    #[inline]
434    pub const fn is_masterchain(&self) -> bool {
435        self.workchain as i32 == ShardIdent::MASTERCHAIN.workchain()
436    }
437
438    /// Returns `true` if this address is `0:000...000`.
439    pub const fn is_zero(&self) -> bool {
440        self.workchain == 0 && self.anycast.is_none() && self.address.is_zero()
441    }
442
443    /// Returns the number of data bits that this struct occupies.
444    pub const fn bit_len(&self) -> u16 {
445        let mut bit_len = Self::BITS_WITHOUT_ANYCAST;
446        if let Some(anycast) = &self.anycast {
447            bit_len += anycast.bit_len();
448        }
449        bit_len
450    }
451
452    /// Returns the high bits of the address as a number.
453    pub const fn prefix(&self) -> u64 {
454        u64::from_be_bytes(*self.address.first_chunk())
455    }
456
457    /// Returns a pretty-printer for base64-encoded address.
458    #[cfg(feature = "base64")]
459    pub const fn display_base64(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
460        DisplayBase64StdAddr {
461            addr: self,
462            flags: Base64StdAddrFlags {
463                testnet: false,
464                base64_url: false,
465                bounceable,
466            },
467        }
468    }
469
470    /// Returns a pretty-printer for URL-safe base64-encoded address.
471    #[cfg(feature = "base64")]
472    pub const fn display_base64_url(&self, bounceable: bool) -> DisplayBase64StdAddr<'_> {
473        DisplayBase64StdAddr {
474            addr: self,
475            flags: Base64StdAddrFlags {
476                testnet: false,
477                base64_url: true,
478                bounceable,
479            },
480        }
481    }
482}
483
484impl Default for StdAddr {
485    #[inline]
486    fn default() -> Self {
487        Self::ZERO
488    }
489}
490
491impl Addr for StdAddr {
492    #[inline]
493    fn workchain(&self) -> i32 {
494        self.workchain as i32
495    }
496
497    #[inline]
498    fn prefix(&self) -> u64 {
499        StdAddr::prefix(self)
500    }
501}
502
503impl std::fmt::Display for StdAddr {
504    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
505        if let Some(anycast) = &self.anycast {
506            ok!(f.write_fmt(format_args!("{anycast}:")))
507        }
508
509        f.write_fmt(format_args!("{}:{}", self.workchain, self.address))
510    }
511}
512
513impl From<(i8, HashBytes)> for StdAddr {
514    #[inline]
515    fn from((workchain, address): (i8, HashBytes)) -> Self {
516        Self::new(workchain, address)
517    }
518}
519
520impl From<(i8, [u8; 32])> for StdAddr {
521    #[inline]
522    fn from((workchain, address): (i8, [u8; 32])) -> Self {
523        Self::new(workchain, HashBytes(address))
524    }
525}
526
527impl From<StdAddr> for IntAddr {
528    #[inline]
529    fn from(value: StdAddr) -> Self {
530        Self::Std(value)
531    }
532}
533
534impl FromStr for StdAddr {
535    type Err = ParseAddrError;
536
537    fn from_str(s: &str) -> Result<Self, Self::Err> {
538        if s.is_empty() {
539            return Err(ParseAddrError::Empty);
540        }
541
542        let mut result = Self::default();
543
544        let mut parts = s.split(':');
545        match parts.next() {
546            Some(part) => match part.parse() {
547                Ok(workchain) => result.workchain = workchain,
548                Err(_) => return Err(ParseAddrError::InvalidWorkchain),
549            },
550            None => return Err(ParseAddrError::Empty),
551        }
552
553        match parts.next() {
554            Some(part) => match hex::decode_to_slice(part, &mut result.address.0) {
555                Ok(()) => {}
556                Err(_) => return Err(ParseAddrError::InvalidAccountId),
557            },
558            None => return Err(ParseAddrError::InvalidAccountId),
559        }
560
561        if parts.next().is_none() {
562            Ok(result)
563        } else {
564            Err(ParseAddrError::UnexpectedPart)
565        }
566    }
567}
568
569impl Store for StdAddr {
570    fn store_into(
571        &self,
572        builder: &mut CellBuilder,
573        context: &dyn CellContext,
574    ) -> Result<(), Error> {
575        if !builder.has_capacity(self.bit_len(), 0) {
576            return Err(Error::CellOverflow);
577        }
578        ok!(builder.store_small_uint(0b10, 2));
579        ok!(self.anycast.store_into(builder, context));
580        ok!(builder.store_u8(self.workchain as u8));
581        builder.store_u256(&self.address)
582    }
583}
584
585impl<'a> Load<'a> for StdAddr {
586    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
587        if !ok!(slice.load_bit()) || ok!(slice.load_bit()) {
588            return Err(Error::InvalidTag);
589        }
590
591        Ok(Self {
592            anycast: ok!(Option::<Box<Anycast>>::load_from(slice)),
593            workchain: ok!(slice.load_u8()) as i8,
594            address: ok!(slice.load_u256()),
595        })
596    }
597}
598
599impl crate::dict::DictKey for StdAddr {
600    const BITS: u16 = StdAddr::BITS_WITHOUT_ANYCAST;
601}
602
603impl crate::dict::StoreDictKey for StdAddr {
604    fn store_into_data(&self, builder: &mut CellDataBuilder) -> Result<(), Error> {
605        if self.anycast.is_some() || !builder.has_capacity_bits(Self::BITS_WITHOUT_ANYCAST) {
606            return Err(Error::InvalidData);
607        }
608        ok!(builder.store_small_uint(0b100, 3)); // `0b10` (tag) | `0b0` ("none" for anycast)
609        ok!(builder.store_u8(self.workchain as u8));
610        builder.store_u256(&self.address)
611    }
612}
613
614impl crate::dict::LoadDictKey for StdAddr {
615    fn load_from_data(data: &CellDataBuilder) -> Option<Self> {
616        let [first_byte, second_byte, data @ ..] = data.raw_data();
617
618        // 2 bits id, 1 bit maybe (None), 8 bits workchain, 256 bits address
619
620        const PREFIX_BITS: u8 = 0b1000_0000;
621        const PREFIX_MASK: u8 = 0b1110_0000;
622
623        const R: u8 = 3;
624        const SHIFT: u8 = 8 - R;
625        const REV_SHIFT: u8 = 120 + R;
626
627        if unlikely((first_byte ^ PREFIX_BITS) & PREFIX_MASK != 0) {
628            return None;
629        }
630
631        let mut result = Self {
632            anycast: None,
633            // 100xxxxx | xxxaaaaa -> xxxxxxxx
634            workchain: ((first_byte << R) | (second_byte >> SHIFT)) as i8,
635            address: HashBytes::ZERO,
636        };
637
638        // SAFETY: transmuting [u8; 32] to [u128; 2] is safe
639        let [mut hi, mut lo]: [u128; 2] =
640            unsafe { std::mem::transmute::<[u8; 32], _>(data[..32].try_into().unwrap()) };
641
642        // Numbers are in big endian order, swap bytes on little endian arch
643        #[cfg(target_endian = "little")]
644        {
645            hi = hi.swap_bytes();
646            lo = lo.swap_bytes();
647        }
648
649        // SAFETY: transmuting [[u8; 16]; 2] to [u8; 32] is safe
650        result.address = unsafe {
651            std::mem::transmute::<[[u8; 16]; 2], HashBytes>([
652                ((hi >> SHIFT) | ((*second_byte as u128) << REV_SHIFT)).to_be_bytes(),
653                ((lo >> SHIFT) | (hi << REV_SHIFT)).to_be_bytes(),
654            ])
655        };
656
657        Some(result)
658    }
659}
660
661#[cfg(feature = "serde")]
662impl serde::Serialize for StdAddr {
663    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
664    where
665        S: serde::Serializer,
666    {
667        if serializer.is_human_readable() {
668            serializer.collect_str(self)
669        } else {
670            (self.workchain, &self.address).serialize(serializer)
671        }
672    }
673}
674
675#[cfg(feature = "serde")]
676impl<'de> serde::Deserialize<'de> for StdAddr {
677    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
678    where
679        D: serde::Deserializer<'de>,
680    {
681        use serde::de::{Error, Visitor};
682
683        struct StdAddrVisitor;
684
685        impl Visitor<'_> for StdAddrVisitor {
686            type Value = StdAddr;
687
688            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
689                f.write_str("a standard address")
690            }
691
692            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
693            where
694                E: Error,
695            {
696                StdAddr::from_str(v).map_err(E::custom)
697            }
698        }
699
700        if deserializer.is_human_readable() {
701            deserializer.deserialize_str(StdAddrVisitor)
702        } else {
703            <(i8, HashBytes)>::deserialize(deserializer)
704                .map(|(workchain, address)| Self::new(workchain, address))
705        }
706    }
707}
708
709#[cfg(feature = "arbitrary")]
710impl<'a> arbitrary::Arbitrary<'a> for StdAddr {
711    #[inline]
712    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
713        Ok(Self {
714            anycast: u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?,
715            workchain: u.arbitrary()?,
716            address: u.arbitrary()?,
717        })
718    }
719
720    #[inline]
721    fn size_hint(depth: usize) -> (usize, Option<usize>) {
722        arbitrary::size_hint::and(Option::<Anycast>::size_hint(depth), (33, Some(33)))
723    }
724}
725
726/// A helper struct to work with base64-encoded addresses.
727#[cfg(feature = "base64")]
728pub struct StdAddrBase64Repr<const URL_SAFE: bool = true>;
729
730#[cfg(all(feature = "base64", feature = "serde"))]
731impl<const URL_SAFE: bool> StdAddrBase64Repr<URL_SAFE> {
732    /// Serializes address into a base64-encoded string.
733    pub fn serialize<S>(addr: &StdAddr, serializer: S) -> Result<S::Ok, S::Error>
734    where
735        S: serde::Serializer,
736    {
737        serializer.collect_str(&DisplayBase64StdAddr {
738            addr,
739            flags: Base64StdAddrFlags {
740                testnet: false,
741                base64_url: URL_SAFE,
742                bounceable: false,
743            },
744        })
745    }
746
747    /// Deserializes address as a base64-encoded string.
748    pub fn deserialize<'de, D>(deserializer: D) -> Result<StdAddr, D::Error>
749    where
750        D: serde::Deserializer<'de>,
751    {
752        use serde::de::{Error, Visitor};
753
754        struct StdAddrBase64Visitor;
755
756        impl Visitor<'_> for StdAddrBase64Visitor {
757            type Value = StdAddr;
758
759            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
760                f.write_str("a standard address")
761            }
762
763            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
764            where
765                E: Error,
766            {
767                StdAddr::from_str_ext(v, StdAddrFormat::any())
768                    .map(|(addr, _)| addr)
769                    .map_err(E::custom)
770            }
771        }
772
773        deserializer.deserialize_str(StdAddrBase64Visitor)
774    }
775}
776
777/// Parsing options for [`StdAddr::from_str_ext`]
778#[cfg(feature = "base64")]
779#[derive(Debug, Clone, Copy)]
780pub struct StdAddrFormat {
781    /// Allow raw address (0:000...000).
782    pub allow_raw: bool,
783    /// Allow base64-encoded address.
784    pub allow_base64: bool,
785    /// Allow URL-safe base64 encoding.
786    pub allow_base64_url: bool,
787}
788
789#[cfg(feature = "base64")]
790impl StdAddrFormat {
791    /// Allows any address format.
792    pub const fn any() -> Self {
793        StdAddrFormat {
794            allow_raw: true,
795            allow_base64: true,
796            allow_base64_url: true,
797        }
798    }
799}
800
801/// Base64-encoded address flags.
802#[cfg(feature = "base64")]
803#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
804pub struct Base64StdAddrFlags {
805    /// Address belongs to testnet.
806    pub testnet: bool,
807    /// Use URL-safe base64 encoding.
808    pub base64_url: bool,
809    /// Whether to set `bounce` flag during transfer.
810    pub bounceable: bool,
811}
812
813/// Pretty-printer for [`StdAddr`] in base64 format.
814#[cfg(feature = "base64")]
815pub struct DisplayBase64StdAddr<'a> {
816    /// Address to display.
817    pub addr: &'a StdAddr,
818    /// Encoding flags.
819    pub flags: Base64StdAddrFlags,
820}
821
822#[cfg(feature = "base64")]
823impl std::fmt::Display for DisplayBase64StdAddr<'_> {
824    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
825        use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE, Engine as _};
826
827        let mut buffer = [0u8; 36];
828        buffer[0] = (0x51 - (self.flags.bounceable as i32) * 0x40
829            + (self.flags.testnet as i32) * 0x80) as u8;
830        buffer[1] = self.addr.workchain as u8;
831        buffer[2..34].copy_from_slice(self.addr.address.as_array());
832
833        let crc = crate::crc::crc_16(&buffer[..34]);
834        buffer[34] = (crc >> 8) as u8;
835        buffer[35] = (crc & 0xff) as u8;
836
837        let mut output = [0u8; 48];
838        if self.flags.base64_url {
839            BASE64_URL_SAFE
840        } else {
841            BASE64_STANDARD
842        }
843        .encode_slice(buffer, &mut output)
844        .unwrap();
845
846        // SAFETY: output is guaranteed to contain only ASCII.
847        let output = unsafe { std::str::from_utf8_unchecked(&output) };
848        f.write_str(output)
849    }
850}
851
852/// Variable-length internal address.
853#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
854pub struct VarAddr {
855    /// Optional anycast info.
856    pub anycast: Option<Box<Anycast>>,
857    /// Address length in bits.
858    pub address_len: Uint9,
859    /// Workchain id (full range).
860    pub workchain: i32,
861    /// Variable-length address.
862    pub address: Vec<u8>,
863}
864
865impl VarAddr {
866    /// The maximum number of bits that address occupies.
867    ///
868    /// - 2 bits id (`0b11`)
869    /// - 1 + `Anycast::BITS_MAX` maybe anycast
870    /// - 9 bits `address_len`
871    /// - 32 bits workchain
872    /// - `address_len` bits of address
873    pub const BITS_MAX: u16 =
874        2 + 1 + Anycast::BITS_MAX + Uint9::BITS + 32 + Uint9::MAX.into_inner();
875
876    /// Returns `true` if this address is for a masterchain block.
877    ///
878    /// See [`ShardIdent::MASTERCHAIN`]
879    #[inline]
880    pub const fn is_masterchain(&self) -> bool {
881        self.workchain == ShardIdent::MASTERCHAIN.workchain()
882    }
883
884    /// Returns the number of data bits that this struct occupies.
885    pub const fn bit_len(&self) -> u16 {
886        let mut bit_len = 2 + 1 + Uint9::BITS + 32 + self.address_len.into_inner();
887        if let Some(anycast) = &self.anycast {
888            bit_len += anycast.bit_len();
889        }
890        bit_len
891    }
892
893    /// Returns the high bits of the address as a number.
894    pub fn prefix(&self) -> u64 {
895        let mut prefix = [0; 8];
896        let total_bytes = std::cmp::min(self.address.len(), 8);
897        prefix[..total_bytes].copy_from_slice(&self.address[..total_bytes]);
898        u64::from_be_bytes(prefix)
899    }
900}
901
902impl From<VarAddr> for IntAddr {
903    #[inline]
904    fn from(value: VarAddr) -> Self {
905        Self::Var(value)
906    }
907}
908
909impl Store for VarAddr {
910    fn store_into(
911        &self,
912        builder: &mut CellBuilder,
913        context: &dyn CellContext,
914    ) -> Result<(), Error> {
915        if !builder.has_capacity(self.bit_len(), 0) {
916            return Err(Error::CellOverflow);
917        }
918        ok!(builder.store_small_uint(0b11, 2));
919        ok!(self.anycast.store_into(builder, context));
920        ok!(self.address_len.store_into(builder, context));
921        ok!(builder.store_u32(self.workchain as u32));
922        builder.store_raw(&self.address, self.address_len.into_inner())
923    }
924}
925
926impl Addr for VarAddr {
927    #[inline]
928    fn workchain(&self) -> i32 {
929        self.workchain
930    }
931
932    #[inline]
933    fn prefix(&self) -> u64 {
934        VarAddr::prefix(self)
935    }
936}
937
938#[cfg(feature = "arbitrary")]
939impl<'a> arbitrary::Arbitrary<'a> for VarAddr {
940    #[inline]
941    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
942        let anycast = u.ratio(1u8, 20u8)?.then(|| u.arbitrary()).transpose()?;
943        let address_len = u.arbitrary::<Uint9>()?;
944        let workchain = u.arbitrary()?;
945
946        let bit_len = address_len.into_inner() as usize;
947        let mut address = u.bytes(bit_len.div_ceil(8))?.to_vec();
948        if let Some(last_byte) = address.last_mut() {
949            let rem = bit_len % 8;
950            if rem != 0 {
951                *last_byte &= u8::MAX << (8 - rem);
952            }
953        }
954
955        Ok(Self {
956            anycast,
957            address_len,
958            workchain,
959            address,
960        })
961    }
962
963    #[inline]
964    fn size_hint(_: usize) -> (usize, Option<usize>) {
965        (1 + 2 + 4, None)
966    }
967}
968
969/// External address.
970///
971/// ```text
972/// addr_none$00 = MsgAddressExt;
973/// addr_extern$01 len:(## 9) external_address:(bits len) = MsgAddressExt;
974/// ```
975#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
976pub struct ExtAddr {
977    /// Number of bits stored in data.
978    pub data_bit_len: Uint9,
979    /// External address data
980    pub data: Vec<u8>,
981}
982
983impl ExtAddr {
984    /// Creates non-empty external address.
985    pub fn new<T>(data_bit_len: u16, data: T) -> Option<Self>
986    where
987        T: Into<Vec<u8>>,
988    {
989        let data_bit_len = Uint9::new(data_bit_len);
990        if data_bit_len.is_valid() {
991            Some(Self {
992                data_bit_len,
993                data: data.into(),
994            })
995        } else {
996            None
997        }
998    }
999
1000    /// Returns the number of data bits that this struct occupies.
1001    pub const fn bit_len(&self) -> u16 {
1002        Uint9::BITS + self.data_bit_len.into_inner()
1003    }
1004}
1005
1006impl std::fmt::Display for ExtAddr {
1007    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1008        let bitstring = Bitstring {
1009            bytes: &self.data,
1010            bit_len: self.data_bit_len.into_inner(),
1011        };
1012        write!(f, ":{bitstring}")
1013    }
1014}
1015
1016impl FromStr for ExtAddr {
1017    type Err = ParseAddrError;
1018
1019    fn from_str(s: &str) -> Result<Self, Self::Err> {
1020        if s.is_empty() {
1021            return Err(ParseAddrError::Empty);
1022        }
1023
1024        let Some(s) = s.strip_prefix(':') else {
1025            return Err(ParseAddrError::UnexpectedPart);
1026        };
1027
1028        let Ok((data, bit_len)) = Bitstring::from_hex_str(s) else {
1029            return Err(ParseAddrError::InvalidAccountId);
1030        };
1031
1032        ExtAddr::new(bit_len, data).ok_or(ParseAddrError::UnexpectedPart)
1033    }
1034}
1035
1036#[cfg(feature = "serde")]
1037impl serde::Serialize for ExtAddr {
1038    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1039        if serializer.is_human_readable() {
1040            serializer.collect_str(self)
1041        } else {
1042            (self.data_bit_len.into_inner(), &self.data).serialize(serializer)
1043        }
1044    }
1045}
1046
1047#[cfg(feature = "serde")]
1048impl<'de> serde::Deserialize<'de> for ExtAddr {
1049    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
1050        use serde::de::{Error, Visitor};
1051
1052        struct ExtAddrVisitor;
1053
1054        impl Visitor<'_> for ExtAddrVisitor {
1055            type Value = ExtAddr;
1056
1057            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1058                f.write_str("an external address")
1059            }
1060
1061            fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
1062                ExtAddr::from_str(v).map_err(E::custom)
1063            }
1064        }
1065
1066        if deserializer.is_human_readable() {
1067            deserializer.deserialize_str(ExtAddrVisitor)
1068        } else {
1069            <(u16, Vec<u8>)>::deserialize(deserializer).and_then(|(data_bit_len, data)| {
1070                ExtAddr::new(data_bit_len, data)
1071                    .ok_or_else(|| Error::custom("invalid external address data length"))
1072            })
1073        }
1074    }
1075}
1076
1077#[cfg(feature = "arbitrary")]
1078impl<'a> arbitrary::Arbitrary<'a> for ExtAddr {
1079    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1080        let data_bit_len = u.arbitrary::<Uint9>()?;
1081
1082        let bit_len = data_bit_len.into_inner() as usize;
1083        let mut data = u.bytes(bit_len.div_ceil(8))?.to_vec();
1084        if let Some(last_byte) = data.last_mut() {
1085            let rem = bit_len % 8;
1086            if rem != 0 {
1087                *last_byte &= u8::MAX << (8 - rem);
1088            }
1089        }
1090
1091        Ok(Self { data_bit_len, data })
1092    }
1093
1094    #[inline]
1095    fn size_hint(_: usize) -> (usize, Option<usize>) {
1096        (2, None)
1097    }
1098}
1099
1100/// Anycast prefix info.
1101///
1102/// ```text
1103/// anycast_info$_ depth:(#<= 30) { depth >= 1 } rewrite_pfx:(bits depth) = Anycast;
1104/// ```
1105#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
1106pub struct Anycast {
1107    /// Prefix length in bits.
1108    pub depth: SplitDepth,
1109    /// Rewrite prefix data.
1110    pub rewrite_prefix: Vec<u8>,
1111}
1112
1113impl Anycast {
1114    /// The minimum allowed number of bits in the rewrite prefix.
1115    pub const MIN_DEPTH: u8 = 1;
1116    /// The maximum allowed number of bits in the rewrite prefix.
1117    pub const MAX_DEPTH: u8 = 30;
1118
1119    /// The maximum number of bits that an Anycast occupies.
1120    pub const BITS_MAX: u16 = SplitDepth::BITS + Self::MAX_DEPTH as u16;
1121
1122    /// Constructs anycast info from rewrite prefix.
1123    pub fn from_slice(rewrite_prefix: &CellSlice<'_>) -> Result<Self, Error> {
1124        let depth = ok!(SplitDepth::from_bit_len(rewrite_prefix.size_bits()));
1125
1126        let mut data = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1127        ok!(rewrite_prefix.get_raw(0, &mut data, depth.into_bit_len()));
1128
1129        Ok(Self {
1130            depth,
1131            rewrite_prefix: data,
1132        })
1133    }
1134
1135    /// Returns the number of data bits that this struct occupies.
1136    pub const fn bit_len(&self) -> u16 {
1137        SplitDepth::BITS + self.depth.into_bit_len()
1138    }
1139}
1140
1141impl std::fmt::Display for Anycast {
1142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1143        let bitstring = Bitstring {
1144            bytes: &self.rewrite_prefix,
1145            bit_len: self.depth.into_bit_len(),
1146        };
1147        std::fmt::Display::fmt(&bitstring, f)
1148    }
1149}
1150
1151impl Store for Anycast {
1152    fn store_into(
1153        &self,
1154        builder: &mut CellBuilder,
1155        context: &dyn CellContext,
1156    ) -> Result<(), Error> {
1157        if !builder.has_capacity(self.bit_len(), 0) {
1158            return Err(Error::CellOverflow);
1159        }
1160        ok!(self.depth.store_into(builder, context));
1161        builder.store_raw(&self.rewrite_prefix, self.depth.into_bit_len())
1162    }
1163}
1164
1165impl<'a> Load<'a> for Anycast {
1166    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
1167        let depth = ok!(SplitDepth::load_from(slice));
1168        if !slice.has_remaining(depth.into_bit_len(), 0) {
1169            return Err(Error::CellUnderflow);
1170        }
1171
1172        let mut rewrite_prefix = vec![0; depth.into_bit_len().div_ceil(8) as usize];
1173        ok!(slice.load_raw(&mut rewrite_prefix, depth.into_bit_len()));
1174
1175        Ok(Self {
1176            depth,
1177            rewrite_prefix,
1178        })
1179    }
1180}
1181
1182#[cfg(feature = "arbitrary")]
1183impl<'a> arbitrary::Arbitrary<'a> for Anycast {
1184    #[inline]
1185    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1186        let split_depth = SplitDepth::arbitrary(u)?;
1187        let bit_len = split_depth.into_bit_len();
1188
1189        let bytes = u.bytes(bit_len.div_ceil(8) as _)?;
1190
1191        let b = CellBuilder::from_raw_data(bytes, bit_len).unwrap();
1192        Ok(Self::from_slice(&b.as_data_slice()).unwrap())
1193    }
1194
1195    #[inline]
1196    fn size_hint(_: usize) -> (usize, Option<usize>) {
1197        (2, Some(5))
1198    }
1199}
1200
1201#[cfg(test)]
1202mod tests {
1203    use super::*;
1204    use crate::dict::Dict;
1205
1206    #[test]
1207    fn dict_with_std_addr_keys() {
1208        let mut dict = Dict::<StdAddr, u32>::new();
1209        dict.set(StdAddr::new(-1, HashBytes([0x33; 32])), 123)
1210            .unwrap();
1211        dict.set(StdAddr::new(0, HashBytes([0x10; 32])), 321)
1212            .unwrap();
1213        dict.set(StdAddr::new(-1, HashBytes([0x55; 32])), 234)
1214            .unwrap();
1215        dict.set(StdAddr::new(0, HashBytes([0x20; 32])), 432)
1216            .unwrap();
1217
1218        for entry in dict.iter() {
1219            let (addr, value) = entry.unwrap();
1220            println!("{addr}: {value}");
1221        }
1222    }
1223
1224    #[test]
1225    fn anycast_str() {
1226        // 0 bit
1227        let empty_res = Anycast::from_slice(&Cell::empty_cell().as_slice().unwrap());
1228        assert_eq!(empty_res.unwrap_err(), Error::IntOverflow);
1229
1230        // 1 bit
1231        let mut prefix = CellBuilder::new();
1232        prefix.store_bit_one().unwrap();
1233        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1234        assert_eq!(anycast.to_string(), "c_");
1235
1236        // 8 bit
1237        let mut prefix = CellBuilder::new();
1238        prefix.store_u8(0xa5).unwrap();
1239        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1240        assert_eq!(anycast.to_string(), "a5");
1241
1242        // 30 bit
1243        let mut prefix = CellBuilder::new();
1244        prefix.store_uint(0xb00b1e5, 28).unwrap();
1245        prefix.store_zeros(2).unwrap();
1246        let anycast = Anycast::from_slice(&prefix.as_data_slice()).unwrap();
1247        assert_eq!(anycast.to_string(), "b00b1e52_");
1248    }
1249
1250    #[test]
1251    fn address_prefix() {
1252        let addr = "0:ece57bcc6c530283becbbd8a3b24d3c5987cdddc3c8b7b33be6e4a6312490415"
1253            .parse::<StdAddr>()
1254            .unwrap();
1255        assert_eq!(addr.prefix(), 0xece57bcc6c530283);
1256
1257        let var_addr = VarAddr {
1258            anycast: None,
1259            address_len: Uint9::new(32),
1260            workchain: 0,
1261            address: vec![0xb0, 0xba, 0xca, 0xfe],
1262        };
1263        assert_eq!(var_addr.prefix(), 0xb0bacafe00000000);
1264
1265        let var_addr = VarAddr {
1266            anycast: None,
1267            address_len: Uint9::new(72),
1268            workchain: 0,
1269            address: vec![0xb0, 0xba, 0xca, 0xfe, 0xb0, 0x0b, 0x1e, 0x5a, 0xff],
1270        };
1271        assert_eq!(var_addr.prefix(), 0xb0bacafeb00b1e5a);
1272    }
1273
1274    #[test]
1275    fn base64_address() {
1276        let addr = "0:84545d4d2cada0ce811705d534c298ca42d29315d03a16eee794cefd191dfa79"
1277            .parse::<StdAddr>()
1278            .unwrap();
1279        assert_eq!(
1280            addr.display_base64(true).to_string(),
1281            "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw"
1282        );
1283        assert_eq!(
1284            StdAddr::from_str_ext(
1285                "EQCEVF1NLK2gzoEXBdU0wpjKQtKTFdA6Fu7nlM79GR36eWpw",
1286                StdAddrFormat::any()
1287            )
1288            .unwrap(),
1289            (addr, Base64StdAddrFlags {
1290                testnet: false,
1291                base64_url: false,
1292                bounceable: true,
1293            })
1294        );
1295
1296        let addr = "0:dddde93b1d3398f0b4305c08de9a032e0bc1b257c4ce2c72090aea1ff3e9ecfd"
1297            .parse::<StdAddr>()
1298            .unwrap();
1299        assert_eq!(
1300            addr.display_base64_url(false).to_string(),
1301            "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_Tyv"
1302        );
1303        assert_eq!(
1304            addr.display_base64(false).to_string(),
1305            "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv"
1306        );
1307
1308        assert_eq!(
1309            StdAddr::from_str_ext(
1310                "UQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/Tyv",
1311                StdAddrFormat::any()
1312            )
1313            .unwrap(),
1314            (addr.clone(), Base64StdAddrFlags {
1315                testnet: false,
1316                base64_url: false,
1317                bounceable: false,
1318            })
1319        );
1320
1321        assert_eq!(
1322            addr.display_base64_url(true).to_string(),
1323            "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq"
1324        );
1325        assert_eq!(
1326            addr.display_base64(true).to_string(),
1327            "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8+ns/WFq"
1328        );
1329
1330        assert_eq!(
1331            StdAddr::from_str_ext(
1332                "EQDd3ek7HTOY8LQwXAjemgMuC8GyV8TOLHIJCuof8-ns_WFq",
1333                StdAddrFormat::any()
1334            )
1335            .unwrap(),
1336            (addr, Base64StdAddrFlags {
1337                testnet: false,
1338                base64_url: true,
1339                bounceable: true,
1340            })
1341        );
1342    }
1343}