massa_models/
address.rs

1// Copyright (c) 2022 MASSA LABS <info@massa.net>
2
3use crate::error::ModelsError;
4use crate::prehash::PreHashed;
5use massa_hash::{Hash, HashDeserializer, HASH_SIZE_BYTES};
6use massa_serialization::{
7    DeserializeError, Deserializer, SerializeError, Serializer, U64VarIntDeserializer,
8    U64VarIntSerializer,
9};
10use massa_signature::{PublicKey, PublicKeyV0};
11use nom::error::{context, ContextError, ErrorKind, ParseError};
12use nom::{IResult, Parser};
13use serde::{Deserialize, Serialize};
14use std::ops::Bound::{Excluded, Included};
15use std::str::FromStr;
16use transition::Versioned;
17
18/// Top level address representation that can differentiate between User and SC address
19#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
20pub enum Address {
21    #[allow(missing_docs)]
22    User(UserAddress),
23    #[allow(missing_docs)]
24    SC(SCAddress),
25}
26
27#[allow(missing_docs)]
28/// Derived from a public key.
29#[transition::versioned(versions("0"))]
30#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
31pub struct SCAddress(pub Hash);
32
33#[allow(missing_docs)]
34/// Derived from a public key.
35#[transition::versioned(versions("0"))]
36#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
37pub struct UserAddress(pub Hash);
38
39const ADDRESS_PREFIX: char = 'A';
40// serialized with varint
41const USER_PREFIX: u64 = 0;
42const SC_PREFIX: u64 = 1;
43
44impl std::fmt::Display for Address {
45    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46        match self {
47            Address::User(address) => address.fmt(f),
48            Address::SC(address) => address.fmt(f),
49        }
50    }
51}
52
53impl std::fmt::Display for UserAddress {
54    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
55        match self {
56            UserAddress::UserAddressV0(address) => address.fmt(f),
57        }
58    }
59}
60
61impl std::fmt::Display for SCAddress {
62    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63        match self {
64            SCAddress::SCAddressV0(address) => address.fmt(f),
65        }
66    }
67}
68
69#[transition::impl_version(versions("0"))]
70impl std::fmt::Display for UserAddress {
71    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
72        let u64_serializer = U64VarIntSerializer::new();
73        let mut bytes: Vec<u8> = Vec::new();
74        u64_serializer
75            .serialize(&Self::VERSION, &mut bytes)
76            .map_err(|_| std::fmt::Error)?;
77        bytes.extend(self.0.to_bytes());
78        write!(
79            f,
80            "{}U{}",
81            ADDRESS_PREFIX,
82            bs58::encode(bytes).with_check().into_string()
83        )
84    }
85}
86
87#[transition::impl_version(versions("0"))]
88impl std::fmt::Display for SCAddress {
89    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
90        let u64_serializer = U64VarIntSerializer::new();
91        let mut bytes: Vec<u8> = Vec::new();
92        u64_serializer
93            .serialize(&Self::VERSION, &mut bytes)
94            .map_err(|_| std::fmt::Error)?;
95        bytes.extend(self.0.to_bytes());
96        write!(
97            f,
98            "{}S{}",
99            ADDRESS_PREFIX,
100            bs58::encode(bytes).with_check().into_string()
101        )
102    }
103}
104
105// See https://github.com/massalabs/massa/pull/3479#issuecomment-1408694720
106// as to why more information is not provided
107impl std::fmt::Debug for Address {
108    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
109        write!(f, "{}", self)
110    }
111}
112
113impl ::serde::Serialize for Address {
114    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
115        match self {
116            Address::User(address) => address.serialize(s),
117            Address::SC(address) => address.serialize(s),
118        }
119    }
120}
121
122impl ::serde::Serialize for UserAddress {
123    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
124        match self {
125            UserAddress::UserAddressV0(address) => address.serialize(s),
126        }
127    }
128}
129
130impl ::serde::Serialize for SCAddress {
131    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
132        match self {
133            SCAddress::SCAddressV0(address) => address.serialize(s),
134        }
135    }
136}
137
138#[transition::impl_version(versions("0"))]
139impl ::serde::Serialize for UserAddress {
140    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
141        if s.is_human_readable() {
142            s.collect_str(&self.to_string())
143        } else {
144            s.serialize_bytes(&self.to_prefixed_bytes())
145        }
146    }
147}
148
149#[transition::impl_version(versions("0"))]
150impl ::serde::Serialize for SCAddress {
151    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
152        if s.is_human_readable() {
153            s.collect_str(&self.to_string())
154        } else {
155            s.serialize_bytes(&self.to_prefixed_bytes())
156        }
157    }
158}
159
160impl<'de> ::serde::Deserialize<'de> for Address {
161    fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Address, D::Error> {
162        if d.is_human_readable() {
163            struct AddressVisitor;
164
165            impl<'de> ::serde::de::Visitor<'de> for AddressVisitor {
166                type Value = Address;
167
168                fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
169                    formatter.write_str("A + {U | S} + base58::encode(version + hash)")
170                }
171
172                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
173                where
174                    E: ::serde::de::Error,
175                {
176                    if let Ok(v_str) = std::str::from_utf8(v) {
177                        Address::from_str(v_str).map_err(E::custom)
178                    } else {
179                        Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
180                    }
181                }
182
183                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
184                where
185                    E: ::serde::de::Error,
186                {
187                    Address::from_str(v).map_err(E::custom)
188                }
189            }
190            d.deserialize_str(AddressVisitor)
191        } else {
192            struct BytesVisitor;
193
194            impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
195                type Value = Address;
196
197                fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
198                    formatter.write_str("[u64varint-of-addr-variant][u64varint-of-version][bytes]")
199                }
200
201                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
202                where
203                    E: ::serde::de::Error,
204                {
205                    AddressDeserializer::new()
206                        .deserialize::<DeserializeError>(v)
207                        .map_err(E::custom)
208                        .map(|r| r.1)
209                }
210            }
211
212            d.deserialize_bytes(BytesVisitor)
213        }
214    }
215}
216
217impl FromStr for Address {
218    type Err = ModelsError;
219    fn from_str(s: &str) -> Result<Self, Self::Err> {
220        let prefix_err = Err(ModelsError::AddressParseError(
221            "Invalid address: Address prefix 'AU' or 'AS' not found".to_string(),
222        ));
223
224        // Handle the prefix ("A{U|S}")
225        let mut chars = s.chars();
226        let Some(ADDRESS_PREFIX) = chars.next() else {
227            return prefix_err;
228        };
229        let Some(pref) = chars.next() else {
230            return prefix_err;
231        };
232
233        let res = match pref {
234            'U' => Address::User(UserAddress::from_str_without_prefixed_type(chars.as_str())?),
235            'S' => Address::SC(SCAddress::from_str_without_prefixed_type(chars.as_str())?),
236            _ => return prefix_err,
237        };
238        Ok(res)
239    }
240}
241
242impl Address {
243    /// Gets the associated thread. Depends on the `thread_count`
244    /// Returns None for SC addresses, even though we may want to get_thread on them in the future
245    pub fn get_thread(&self, thread_count: u8) -> u8 {
246        match self {
247            Address::User(addr) => addr.get_thread(thread_count),
248            // TODO: tmp behaviour, discuss how we would want this to work
249            Address::SC(_addr) => 0,
250        }
251    }
252
253    /// Computes the address associated with the given public key.
254    /// Depends on the Public Key version
255    pub fn from_public_key(public_key: &PublicKey) -> Self {
256        Address::User(UserAddress::from_public_key(public_key))
257    }
258
259    /// Serialize the address as bytes. Includes the type and version prefixes
260    pub fn to_prefixed_bytes(self) -> Vec<u8> {
261        match self {
262            Address::User(addr) => addr.to_prefixed_bytes(),
263            Address::SC(addr) => addr.to_prefixed_bytes(),
264        }
265    }
266}
267
268impl UserAddress {
269    /// Gets the associated thread. Depends on the `thread_count`
270    fn get_thread(&self, thread_count: u8) -> u8 {
271        match self {
272            UserAddress::UserAddressV0(addr) => addr.get_thread(thread_count),
273        }
274    }
275
276    /// Computes the address associated with the given public key
277    fn from_public_key(public_key: &PublicKey) -> Self {
278        match public_key {
279            PublicKey::PublicKeyV0(pk) => {
280                UserAddressVariant!["0"](<UserAddress!["0"]>::from_public_key(pk))
281            }
282        }
283    }
284
285    fn from_str_without_prefixed_type(s: &str) -> Result<Self, ModelsError> {
286        let decoded_bs58_check = bs58::decode(s).with_check(None).into_vec().map_err(|err| {
287            ModelsError::AddressParseError(format!(
288                "in UserAddress from_str_without_prefixed_type: {}",
289                err
290            ))
291        })?;
292        let u64_deserializer = U64VarIntDeserializer::new(Included(0), Included(u64::MAX));
293        let (rest, version) = u64_deserializer
294            .deserialize::<DeserializeError>(&decoded_bs58_check[..])
295            .map_err(|err| {
296                ModelsError::AddressParseError(format!(
297                    "in UserAddress from_str_without_prefixed_type: {}",
298                    err
299                ))
300            })?;
301
302        match version {
303            <UserAddress!["0"]>::VERSION => Ok(UserAddressVariant!["0"](
304                <UserAddress!["0"]>::from_bytes(rest)?,
305            )),
306            unhandled_version => Err(ModelsError::AddressParseError(format!(
307                "version {} is not handled for UserAddress",
308                unhandled_version
309            ))),
310        }
311    }
312
313    /// Serialize the address as bytes. Includes the type and version prefixes
314    pub fn to_prefixed_bytes(self) -> Vec<u8> {
315        match self {
316            UserAddress::UserAddressV0(addr) => addr.to_prefixed_bytes(),
317        }
318    }
319}
320
321#[transition::impl_version(versions("0"))]
322impl UserAddress {
323    /// Fetches the version of the UserAddress
324    pub fn get_version(&self) -> u64 {
325        Self::VERSION
326    }
327
328    /// Serialize the address as bytes. Includes the type and version prefixes
329    fn to_prefixed_bytes(self) -> Vec<u8> {
330        let mut buff = vec![];
331        let addr_type_ser = U64VarIntSerializer::new();
332        let addr_vers_ser = U64VarIntSerializer::new();
333        addr_type_ser
334            .serialize(&USER_PREFIX, &mut buff)
335            .expect("impl always returns Ok(())");
336        addr_vers_ser
337            .serialize(&Self::VERSION, &mut buff)
338            .expect("impl always returns Ok(())");
339        buff.extend_from_slice(&self.0.to_bytes()[..]);
340        buff
341    }
342
343    /// Gets the associated thread. Depends on the `thread_count`
344    fn get_thread(&self, thread_count: u8) -> u8 {
345        (self.0.to_bytes()[0])
346            .checked_shr(8 - thread_count.trailing_zeros())
347            .unwrap_or(0)
348    }
349
350    /// Deserialize the address without considering the version byte
351    fn from_bytes(data: &[u8]) -> Result<UserAddress, ModelsError> {
352        Ok(UserAddress(Hash::from_bytes(&data.try_into().map_err(
353            |_| {
354                ModelsError::BufferError(format!(
355                    "expected a buffer of size {}, but found a size of {}",
356                    HASH_SIZE_BYTES,
357                    &data.len()
358                ))
359            },
360        )?)))
361    }
362}
363
364#[transition::impl_version(versions("0"), structures("UserAddress", "PublicKey"))]
365impl UserAddress {
366    /// Computes address associated with given public key
367    pub fn from_public_key(public_key: &PublicKey) -> Self {
368        UserAddress(Hash::compute_from(&public_key.to_bytes()))
369    }
370}
371
372#[transition::impl_version(versions("0"))]
373impl UserAddress {}
374
375impl SCAddress {
376    fn from_str_without_prefixed_type(s: &str) -> Result<Self, ModelsError> {
377        let decoded_bs58_check = bs58::decode(s).with_check(None).into_vec().map_err(|err| {
378            ModelsError::AddressParseError(format!(
379                "in SCAddress from_str_without_prefixed_type: {}",
380                err
381            ))
382        })?;
383        let u64_deserializer = U64VarIntDeserializer::new(Included(0), Included(u64::MAX));
384        let (rest, version) = u64_deserializer
385            .deserialize::<DeserializeError>(&decoded_bs58_check[..])
386            .map_err(|err| {
387                ModelsError::AddressParseError(format!(
388                    "in SCAddress from_str_without_prefixed_type: {}",
389                    err
390                ))
391            })?;
392
393        match version {
394            <SCAddress!["0"]>::VERSION => {
395                Ok(SCAddressVariant!["0"](<SCAddress!["0"]>::from_bytes(rest)?))
396            }
397            unhandled_version => Err(ModelsError::AddressParseError(format!(
398                "version {} is not handled for SCAddress",
399                unhandled_version
400            ))),
401        }
402    }
403
404    /// Serialize the address as bytes. Includes the type and version prefixes
405    pub fn to_prefixed_bytes(self) -> Vec<u8> {
406        match self {
407            SCAddress::SCAddressV0(addr) => addr.to_prefixed_bytes(),
408        }
409    }
410}
411
412#[transition::impl_version(versions("0"))]
413impl SCAddress {
414    /// Fetches the version of the SC Address
415    pub fn get_version(&self) -> u64 {
416        Self::VERSION
417    }
418}
419
420#[transition::impl_version(versions("0"))]
421impl SCAddress {
422    /// Serialize the address as bytes. Includes the type and version prefixes
423    pub fn to_prefixed_bytes(self) -> Vec<u8> {
424        let mut buff = vec![];
425        let addr_type_ser = U64VarIntSerializer::new();
426        let addr_vers_ser = U64VarIntSerializer::new();
427        addr_type_ser
428            .serialize(&SC_PREFIX, &mut buff)
429            .expect("impl always returns Ok(())");
430        addr_vers_ser
431            .serialize(&Self::VERSION, &mut buff)
432            .expect("impl always returns Ok(())");
433        buff.extend_from_slice(&self.0.to_bytes()[..]);
434        buff
435    }
436
437    /// Deserialize the address without considering the version byte
438    fn from_bytes(data: &[u8]) -> Result<SCAddress, ModelsError> {
439        Ok(SCAddress(Hash::from_bytes(&data.try_into().map_err(
440            |_| {
441                ModelsError::BufferError(format!(
442                    "expected a buffer of size {}, but found a size of {}",
443                    HASH_SIZE_BYTES,
444                    &data.len()
445                ))
446            },
447        )?)))
448    }
449}
450
451/* /!\ SCAddressV1 not prehashed! */
452impl PreHashed for Address {}
453
454/// Serializer for `Address`
455#[derive(Default, Clone)]
456pub struct AddressSerializer {
457    type_serializer: U64VarIntSerializer,
458    version_serializer: U64VarIntSerializer,
459}
460
461impl AddressSerializer {
462    /// Serializes an `Address` into a `Vec<u8>`
463    pub fn new() -> Self {
464        Self {
465            type_serializer: U64VarIntSerializer::new(),
466            version_serializer: U64VarIntSerializer::new(),
467        }
468    }
469}
470
471impl Serializer<Address> for AddressSerializer {
472    fn serialize(&self, value: &Address, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
473        match value {
474            Address::User(addr) => self.serialize(addr, buffer),
475            Address::SC(addr) => self.serialize(addr, buffer),
476        }
477    }
478}
479
480impl Serializer<UserAddress> for AddressSerializer {
481    fn serialize(&self, value: &UserAddress, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
482        self.type_serializer.serialize(&USER_PREFIX, buffer)?;
483        match value {
484            UserAddress::UserAddressV0(addr) => self.serialize(addr, buffer),
485        }
486    }
487}
488
489#[transition::impl_version(versions("0"), structures("UserAddress"))]
490impl Serializer<UserAddress> for AddressSerializer {
491    fn serialize(&self, value: &UserAddress, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
492        self.version_serializer
493            .serialize(&value.get_version(), buffer)?;
494        buffer.extend_from_slice(&value.0.into_bytes());
495        Ok(())
496    }
497}
498
499impl Serializer<SCAddress> for AddressSerializer {
500    fn serialize(&self, value: &SCAddress, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
501        self.type_serializer.serialize(&SC_PREFIX, buffer)?;
502        match value {
503            SCAddress::SCAddressV0(addr) => self.serialize(addr, buffer),
504        }
505    }
506}
507
508#[transition::impl_version(versions("0"), structures("SCAddress"))]
509impl Serializer<SCAddress> for AddressSerializer {
510    fn serialize(&self, value: &SCAddress, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
511        self.version_serializer
512            .serialize(&value.get_version(), buffer)?;
513        buffer.extend_from_slice(&value.0.into_bytes());
514        Ok(())
515    }
516}
517
518/// Deserializer for `Address`
519#[derive(Clone)]
520pub struct AddressDeserializer {
521    type_deserializer: U64VarIntDeserializer,
522    version_deserializer: U64VarIntDeserializer,
523    hash_deserializer: HashDeserializer,
524}
525
526impl Default for AddressDeserializer {
527    fn default() -> Self {
528        AddressDeserializer::new()
529    }
530}
531
532impl AddressDeserializer {
533    /// Creates a new deserializer for `Address`
534    pub const fn new() -> Self {
535        Self {
536            type_deserializer: U64VarIntDeserializer::new(Included(0), Included(1)),
537            version_deserializer: U64VarIntDeserializer::new(Included(0), Excluded(u64::MAX)),
538            hash_deserializer: HashDeserializer::new(),
539        }
540    }
541}
542
543impl Deserializer<Address> for AddressDeserializer {
544    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
545        &self,
546        buffer: &'a [u8],
547    ) -> IResult<&'a [u8], Address, E> {
548        // Verify that we at least have a version and something else
549        if buffer.len() < 2 {
550            return Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof)));
551        }
552        let (rest, addr_type) =
553            self.type_deserializer
554                .deserialize(buffer)
555                .map_err(|_: nom::Err<E>| {
556                    nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))
557                })?;
558        match addr_type {
559            USER_PREFIX => {
560                let (rest, addr) = self.deserialize(rest)?;
561                Ok((rest, Address::User(addr)))
562            }
563            SC_PREFIX => {
564                let (rest, addr) = self.deserialize(rest)?;
565                Ok((rest, Address::SC(addr)))
566            }
567            _ => Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))),
568        }
569    }
570}
571
572impl Deserializer<UserAddress> for AddressDeserializer {
573    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
574        &self,
575        buffer: &'a [u8],
576    ) -> IResult<&'a [u8], UserAddress, E> {
577        // Verify that we at least have a version and something else
578        if buffer.len() < 2 {
579            return Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof)));
580        }
581        let (rest, addr_vers) =
582            self.version_deserializer
583                .deserialize(buffer)
584                .map_err(|_: nom::Err<E>| {
585                    nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))
586                })?;
587        match addr_vers {
588            <UserAddress!["0"]>::VERSION => {
589                let (rest, addr) = self.deserialize(rest)?;
590                Ok((rest, UserAddressVariant!["0"](addr)))
591            }
592            _ => Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))),
593        }
594    }
595}
596
597#[transition::impl_version(versions("0"), structures("UserAddress"))]
598impl Deserializer<UserAddress> for AddressDeserializer {
599    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
600        &self,
601        buffer: &'a [u8],
602    ) -> IResult<&'a [u8], UserAddress, E> {
603        context("Failed UserAddress deserialization", |input| {
604            self.hash_deserializer.deserialize(input)
605        })
606        .map(UserAddress)
607        .parse(buffer)
608    }
609}
610
611impl Deserializer<SCAddress> for AddressDeserializer {
612    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
613        &self,
614        buffer: &'a [u8],
615    ) -> IResult<&'a [u8], SCAddress, E> {
616        // Verify that we at least have a version and something else
617        if buffer.len() < 2 {
618            return Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof)));
619        }
620        let (rest, addr_vers) =
621            self.version_deserializer
622                .deserialize(buffer)
623                .map_err(|_: nom::Err<E>| {
624                    nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))
625                })?;
626        match addr_vers {
627            <SCAddress!["0"]>::VERSION => {
628                let (rest, addr) = self.deserialize(rest)?;
629                Ok((rest, SCAddressVariant!["0"](addr)))
630            }
631            _ => Err(nom::Err::Error(E::from_error_kind(buffer, ErrorKind::Eof))),
632        }
633    }
634}
635
636#[transition::impl_version(versions("0"), structures("SCAddress"))]
637impl Deserializer<SCAddress> for AddressDeserializer {
638    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
639        &self,
640        buffer: &'a [u8],
641    ) -> IResult<&'a [u8], SCAddress, E> {
642        context("Failed SCAddress deserialization", |input| {
643            self.hash_deserializer.deserialize(input)
644        })
645        .map(SCAddress)
646        .parse(buffer)
647    }
648}
649
650/// Info for a given address on a given cycle
651#[derive(Clone, Debug, Serialize, Deserialize)]
652pub struct ExecutionAddressCycleInfo {
653    /// cycle number
654    pub cycle: u64,
655    /// true if that cycle is final
656    pub is_final: bool,
657    /// `ok_count` blocks were created by this address during that cycle
658    pub ok_count: u64,
659    /// `ok_count` blocks were missed by this address during that cycle
660    pub nok_count: u64,
661    /// number of active rolls the address had at that cycle (if still available)
662    pub active_rolls: Option<u64>,
663}
664
665#[cfg(test)]
666mod test {
667    use crate::config::THREAD_COUNT;
668
669    use super::*;
670
671    #[test]
672    fn test_address() {
673        let expected_user_addr =
674            Address::from_str("AU12fZLkHnLED3okr8Lduyty7dz9ZKkd24xMCc2JJWPcdmfn2eUEx").unwrap();
675        let expected_sc_addr =
676            Address::from_str("AS12fZLkHnLED3okr8Lduyty7dz9ZKkd24xMCc2JJWPcdmfn2eUEx").unwrap();
677
678        let hash = massa_hash::Hash::compute_from("ADDR".as_bytes());
679        let actual_user_addr = Address::User(UserAddress::UserAddressV0(UserAddressV0(hash)));
680        let actual_sc_addr = Address::SC(SCAddress::SCAddressV0(SCAddressV0(hash)));
681
682        assert_eq!(actual_user_addr, expected_user_addr);
683        assert_eq!(actual_sc_addr, expected_sc_addr);
684    }
685
686    #[test]
687    fn test_address_errors() {
688        let expected_error_0 =
689            "address parsing error: Invalid address: Address prefix 'AU' or 'AS' not found"
690                .to_string();
691        let actual_error_0 = Address::from_str("UnexpectedAddress")
692            .unwrap_err()
693            .to_string();
694
695        let expected_error_1 = "address parsing error: in SCAddress from_str_without_prefixed_type: invalid checksum, calculated checksum: '[255, 246, 254, 58]', expected checksum: [188, 126, 221, 98]".to_string();
696        let actual_error_1 = Address::from_str("ASSomeUnexpectedAddress")
697            .unwrap_err()
698            .to_string();
699
700        let expected_error_2 = "address parsing error: in SCAddress from_str_without_prefixed_type: provided string contained invalid character '_' at byte 0".to_string();
701        let actual_error_2 = Address::from_str("AS_SomeUnexpectedAddress")
702            .unwrap_err()
703            .to_string();
704
705        let expected_error_3 = "address parsing error: in UserAddress from_str_without_prefixed_type: invalid checksum, calculated checksum: '[255, 246, 254, 58]', expected checksum: [188, 126, 221, 98]".to_string();
706        let actual_error_3 = Address::from_str("AUSomeUnexpectedAddress")
707            .unwrap_err()
708            .to_string();
709
710        let expected_error_4 = "address parsing error: in UserAddress from_str_without_prefixed_type: provided string contained invalid character '_' at byte 0".to_string();
711        let actual_error_4 = Address::from_str("AU_SomeUnexpectedAddress")
712            .unwrap_err()
713            .to_string();
714
715        assert_eq!(actual_error_0, expected_error_0);
716        assert_eq!(actual_error_1, expected_error_1);
717        assert_eq!(actual_error_2, expected_error_2);
718        assert_eq!(actual_error_3, expected_error_3);
719        assert_eq!(actual_error_4, expected_error_4);
720    }
721
722    #[test]
723    fn test_address_get_thread() {
724        let hash = massa_hash::Hash::compute_from("ADDR".as_bytes());
725
726        let user_addr_0 = Address::User(UserAddress::UserAddressV0(UserAddressV0(hash)));
727        let thread_addr_0 = user_addr_0.get_thread(THREAD_COUNT);
728        let hash = massa_hash::Hash::compute_from("ADDR2".as_bytes());
729
730        let user_addr_1 = Address::User(UserAddress::UserAddressV0(UserAddressV0(hash)));
731        let thread_addr_1 = user_addr_1.get_thread(THREAD_COUNT);
732
733        assert_ne!(thread_addr_0, thread_addr_1);
734    }
735
736    #[test]
737    fn test_address_serde() {
738        let expected_addr =
739            Address::from_str("AU12fZLkHnLED3okr8Lduyty7dz9ZKkd24xMCc2JJWPcdmfn2eUEx").unwrap();
740
741        let serialized = serde_json::to_string(&expected_addr).unwrap();
742        let actual_addr: Address = serde_json::from_str(&serialized).unwrap();
743
744        assert_eq!(actual_addr, expected_addr);
745    }
746}