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