cml_chain/
address.rs

1use crate::byron::{ByronAddress, ByronAddressError};
2use crate::genesis::network_info::NetworkInfo;
3use bech32::ToBase32;
4use cbor_event::{de::Deserializer, se::Serializer};
5use derivative::Derivative;
6use schemars::JsonSchema;
7use std::convert::{TryFrom, TryInto};
8use std::io::{BufRead, Write};
9
10#[cfg(not(feature = "used_from_wasm"))]
11use noop_proc_macro::wasm_bindgen;
12#[cfg(feature = "used_from_wasm")]
13use wasm_bindgen::prelude::wasm_bindgen;
14
15use cml_crypto::{Ed25519KeyHash, ScriptHash};
16
17use crate::certs::StakeCredential;
18
19use cml_core::{
20    error::{DeserializeError, DeserializeFailure},
21    serialization::{Deserialize, LenEncoding, Serialize, StringEncoding},
22    CertificateIndex, Slot, TransactionIndex,
23};
24
25// returns (Number represented, bytes read) if valid encoding
26// or None if decoding prematurely finished
27fn variable_nat_decode(bytes: &[u8]) -> Option<(num_bigint::BigUint, usize)> {
28    let mut output = num_bigint::BigUint::from(0u64);
29    let mut bytes_read = 0;
30    for byte in bytes {
31        output = (output * 128u8) + (byte & 0x7F);
32        bytes_read += 1;
33        if (byte & 0x80) == 0 {
34            return Some((output, bytes_read));
35        }
36    }
37    None
38}
39
40fn variable_nat_encode(mut num: num_bigint::BigUint) -> Vec<u8> {
41    use num_integer::Integer;
42    let zero = num_bigint::BigUint::from(0u64);
43    let divider = num_bigint::BigUint::from(128u64);
44    let (next, chunk) = num.div_rem(&divider);
45    let chunk_byte: u8 = chunk.try_into().unwrap();
46    let mut output = vec![chunk_byte];
47    num = next;
48    while num > zero {
49        let (next, chunk) = num.div_rem(&divider);
50        let chunk_byte: u8 = chunk.try_into().unwrap();
51        num = next;
52        output.push(chunk_byte | 0x80);
53    }
54    output.reverse();
55    output
56}
57
58#[wasm_bindgen]
59#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
60pub enum AddressKind {
61    Base,
62    Ptr,
63    Enterprise,
64    Reward,
65    Byron,
66}
67
68#[derive(Debug, thiserror::Error)]
69pub enum AddressError {
70    #[error("Bech32: {0}")]
71    Bech32(#[from] bech32::Error),
72    #[error("ByronError: {0}")]
73    Byron(#[from] ByronAddressError),
74    #[error("CBOR: {0}")]
75    CBOR(#[from] DeserializeError),
76    #[error("WrongKind: {:?}", 0)]
77    WrongKind(AddressKind),
78}
79
80#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd, Hash)]
81pub enum Address {
82    Base(BaseAddress),
83    Ptr(PointerAddress),
84    Enterprise(EnterpriseAddress),
85    Reward(RewardAddress),
86    Byron(ByronAddress),
87}
88
89impl serde::Serialize for Address {
90    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91    where
92        S: serde::Serializer,
93    {
94        let bech32 = self
95            .to_bech32(None)
96            .map_err(|e| serde::ser::Error::custom(format!("to_bech32: {e:?}")))?;
97        serializer.serialize_str(&bech32)
98    }
99}
100
101impl<'de> serde::de::Deserialize<'de> for Address {
102    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
103    where
104        D: serde::de::Deserializer<'de>,
105    {
106        let bech32 = <String as serde::de::Deserialize>::deserialize(deserializer)?;
107        Address::from_bech32(&bech32).map_err(|_e| {
108            serde::de::Error::invalid_value(
109                serde::de::Unexpected::Str(&bech32),
110                &"bech32 address string",
111            )
112        })
113    }
114}
115
116impl JsonSchema for Address {
117    fn schema_name() -> String {
118        String::from("Address")
119    }
120    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
121        String::json_schema(gen)
122    }
123    fn is_referenceable() -> bool {
124        String::is_referenceable()
125    }
126}
127
128/// Careful: this enum doesn't include the network ID part of the header
129/// ex: base address isn't 0b0000_0000 but instead 0b0000
130/// Use `header_matches_kind` if you don't want to implement the bitwise operators yourself
131#[wasm_bindgen]
132#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
133#[repr(u8)]
134pub enum AddressHeaderKind {
135    // 1001-1101 are left for future formats
136    BasePaymentKeyStakeKey = 0b0000,
137    BasePaymentScriptStakeKey = 0b0001,
138    BasePaymentKeyStakeScript = 0b0010,
139    BasePaymentScriptStakeScript = 0b0011,
140    PointerKey = 0b0100,
141    PointerScript = 0b0101,
142    EnterpriseKey = 0b0110,
143    EnterpriseScript = 0b0111,
144    Byron = 0b1000,
145    RewardKey = 0b1110,
146    RewardScript = 0b1111,
147}
148
149impl Address {
150    /// header has 4 bits addr type discrim then 4 bits network discrim.
151    /// Copied from shelley.cddl:
152    ///
153    /// base address
154    /// bits 7-6: 00
155    /// bit 5: stake cred is keyhash/scripthash
156    /// bit 4: payment cred is keyhash/scripthash
157    /// bits 3-0: network id
158    ///
159    /// pointer address
160    /// bits 7-5: 010
161    /// bit 4: payment cred is keyhash/scripthash
162    /// bits 3-0: network id
163    ///
164    /// enterprise address
165    /// bits 7-5: 010
166    /// bit 4: payment cred is keyhash/scripthash
167    /// bits 3-0: network id
168    ///
169    /// reward addresses:
170    /// bits 7-5: 111
171    /// bit 4: credential is keyhash/scripthash
172    /// bits 3-0: network id
173    ///
174    /// byron addresses:
175    /// bits 7-4: 1000
176    /// bits 3-0: unrelated data (recall: no network ID in Byron addresses)
177    pub fn header(&self) -> u8 {
178        fn stake_cred_bit(cred: &StakeCredential) -> u8 {
179            match cred {
180                StakeCredential::PubKey { .. } => 0,
181                StakeCredential::Script { .. } => 1,
182            }
183        }
184        match self {
185            Self::Base(base) => {
186                (stake_cred_bit(&base.payment) << 4)
187                    | (stake_cred_bit(&base.stake) << 5)
188                    | (base.network & 0xF)
189            }
190            Self::Ptr(ptr) => {
191                0b0100_0000 | (stake_cred_bit(&ptr.payment) << 4) | (ptr.network & 0xF)
192            }
193            Self::Enterprise(enterprise) => {
194                0b0110_0000
195                    | (stake_cred_bit(&enterprise.payment) << 4)
196                    | (enterprise.network & 0xF)
197            }
198            Self::Byron(_) => 0b1000 << 4, // note: no network ID for Byron
199            Self::Reward(reward) => {
200                0b1110_0000 | (stake_cred_bit(&reward.payment) << 4) | (reward.network & 0xF)
201            }
202        }
203    }
204
205    pub fn header_matches_kind(header: u8, kind: AddressHeaderKind) -> bool {
206        (header >> 4) == kind as u8
207    }
208
209    pub fn to_hex(&self) -> String {
210        hex::encode(self.to_raw_bytes())
211    }
212
213    pub fn from_hex(hex: &str) -> Result<Address, DeserializeError> {
214        hex::decode(hex)
215            .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
216            .and_then(|bytes| Self::from_raw_bytes(&bytes))
217    }
218
219    /// The raw bytes of the Address - does not include any wrapping CBOR
220    pub fn to_raw_bytes(&self) -> Vec<u8> {
221        let mut buf = Vec::new();
222        match self {
223            Self::Base(base) => {
224                buf.push(self.header());
225                buf.extend(base.payment.to_raw_bytes());
226                buf.extend(base.stake.to_raw_bytes());
227            }
228            Self::Ptr(ptr) => {
229                buf.push(self.header());
230                buf.extend(ptr.payment.to_raw_bytes());
231                buf.extend(variable_nat_encode(ptr.stake.slot.clone()));
232                buf.extend(variable_nat_encode(ptr.stake.tx_index.clone()));
233                buf.extend(variable_nat_encode(ptr.stake.cert_index.clone()));
234            }
235            Self::Enterprise(enterprise) => {
236                buf.push(self.header());
237                buf.extend(enterprise.payment.to_raw_bytes());
238            }
239            Self::Reward(reward) => {
240                buf.push(self.header());
241                buf.extend(reward.payment.to_raw_bytes());
242            }
243            Self::Byron(byron) => {
244                use cml_core::serialization::ToBytes;
245                buf.extend(byron.to_bytes())
246            }
247        }
248        if let Some(Some(trailing_bytes)) = self.encoding().map(|enc| &enc.trailing) {
249            buf.extend(trailing_bytes.iter());
250        }
251        buf
252    }
253
254    pub fn from_raw_bytes(data: &[u8]) -> Result<Address, DeserializeError> {
255        Self::from_bytes_impl(data, None)
256    }
257
258    pub(crate) fn from_bytes_impl(
259        data: &[u8],
260        bytes_encoding: Option<StringEncoding>,
261    ) -> Result<Address, DeserializeError> {
262        const TRAILING_WHITELIST: [&[u8]; 8] = [
263            &[
264                203, 87, 175, 176, 179, 95, 200, 156, 99, 6, 28, 153, 20, 224, 85, 0, 26, 81, 140,
265                117, 22,
266            ],
267            &[
268                19, 213, 244, 163, 254, 4, 120, 178, 36, 30, 1, 104, 227, 203, 165, 0, 26, 34, 193,
269                90, 17,
270            ],
271            &[0],
272            &[
273                106, 51, 48, 102, 53, 97, 109, 107, 119, 104, 119, 113, 97, 52, 119, 118, 102, 121,
274                106, 100, 101, 122, 121, 97, 101, 108, 109, 110, 110, 103, 100, 54, 100, 52, 101,
275            ],
276            &[
277                53, 97, 99, 121, 50, 114, 48, 101, 107, 114, 112, 113, 122, 113, 106, 108, 113,
278                100, 107, 56, 108, 122, 113, 110, 53, 114, 52, 53, 110,
279            ],
280            &[
281                6, 29, 7, 12, 13, 4, 27, 7, 2, 15, 11, 13, 11, 15, 2, 9, 18, 5, 29, 28, 16, 9, 17,
282                4, 14, 31, 7, 19, 17, 3, 1, 0, 11, 16, 22, 0,
283            ],
284            &[
285                18, 110, 119, 53, 51, 53, 103, 54, 118, 115, 112, 55, 120, 55, 102, 104, 120, 112,
286                113, 50, 112, 116, 115, 104, 57, 103, 107, 114,
287            ],
288            &[44],
289        ];
290        (|| -> Result<Self, DeserializeError> {
291            let header = data[0];
292            let network = header & 0x0F;
293            const HASH_LEN: usize = Ed25519KeyHash::BYTE_COUNT;
294            // should be static assert but it's maybe not worth importing a whole external crate for it now
295            assert_eq!(ScriptHash::BYTE_COUNT, HASH_LEN);
296            // checks the /bit/ bit of the header for key vs scripthash then reads the credential starting at byte position /pos/
297            let read_addr_cred = |bit: u8, pos: usize| {
298                let hash_bytes: [u8; HASH_LEN] = data[pos..pos + HASH_LEN].try_into().unwrap();
299                if header & (1 << bit) == 0 {
300                    StakeCredential::new_pub_key(Ed25519KeyHash::from(hash_bytes))
301                } else {
302                    StakeCredential::new_script(ScriptHash::from(hash_bytes))
303                }
304            };
305            fn make_encoding(
306                bytes_encoding: Option<StringEncoding>,
307                trailing: Option<Vec<u8>>,
308            ) -> Result<Option<AddressEncoding>, DeserializeError> {
309                if trailing.is_some() || bytes_encoding.is_some() {
310                    if let Some(trailing) = &trailing {
311                        let mut found = false;
312                        for ending in TRAILING_WHITELIST.iter() {
313                            if trailing.as_slice() == *ending {
314                                found = true;
315                            }
316                        }
317                        if !found {
318                            return Err(cbor_event::Error::TrailingData.into());
319                        }
320                    }
321                    Ok(Some(AddressEncoding {
322                        trailing,
323                        bytes_encoding: bytes_encoding.unwrap_or_default(),
324                    }))
325                } else {
326                    Ok(None)
327                }
328            }
329            fn len_check_trailing(
330                data: &[u8],
331                addr_size: usize,
332            ) -> Result<Option<Vec<u8>>, DeserializeFailure> {
333                match data.len().cmp(&addr_size) {
334                    std::cmp::Ordering::Less => Err(DeserializeFailure::CBOR(
335                        cbor_event::Error::NotEnough(data.len(), addr_size),
336                    )),
337                    std::cmp::Ordering::Greater => Ok(Some(data[addr_size..].to_vec())),
338                    std::cmp::Ordering::Equal => Ok(None),
339                }
340            }
341            match (header & 0xF0) >> 4 {
342                // base
343                #[allow(clippy::manual_range_patterns)]
344                0b0000 | 0b0001 | 0b0010 | 0b0011 => {
345                    const BASE_ADDR_SIZE: usize = 1 + HASH_LEN * 2;
346                    let trailing = len_check_trailing(data, BASE_ADDR_SIZE)?;
347                    Ok(Address::Base(BaseAddress {
348                        network,
349                        payment: read_addr_cred(4, 1),
350                        stake: read_addr_cred(5, 1 + HASH_LEN),
351                        encoding: make_encoding(bytes_encoding, trailing)?,
352                    }))
353                }
354                // pointer
355                0b0100 | 0b0101 => {
356                    // header + keyhash + 3 natural numbers (min 1 byte each)
357                    const PTR_ADDR_MIN_SIZE: usize = 1 + HASH_LEN + 1 + 1 + 1;
358                    if data.len() < PTR_ADDR_MIN_SIZE {
359                        // possibly more, but depends on how many bytes the natural numbers are for the pointer
360                        return Err(
361                            cbor_event::Error::NotEnough(data.len(), PTR_ADDR_MIN_SIZE).into()
362                        );
363                    }
364                    let mut byte_index = 1;
365                    let payment_cred = read_addr_cred(4, 1);
366                    byte_index += HASH_LEN;
367                    let (slot, slot_bytes) =
368                        variable_nat_decode(&data[byte_index..]).ok_or_else(|| {
369                            DeserializeError::new(
370                                "Address.Pointer.slot",
371                                DeserializeFailure::VariableLenNatDecodeFailed,
372                            )
373                        })?;
374                    byte_index += slot_bytes;
375                    let (tx_index, tx_bytes) = variable_nat_decode(&data[byte_index..])
376                        .ok_or_else(|| {
377                            DeserializeError::new(
378                                "Address.Pointer.tx_index",
379                                DeserializeFailure::VariableLenNatDecodeFailed,
380                            )
381                        })?;
382                    byte_index += tx_bytes;
383                    let (cert_index, cert_bytes) = variable_nat_decode(&data[byte_index..])
384                        .ok_or_else(|| {
385                            DeserializeError::new(
386                                "Address.Pointer.cert_index",
387                                DeserializeFailure::VariableLenNatDecodeFailed,
388                            )
389                        })?;
390                    byte_index += cert_bytes;
391                    let trailing = if byte_index < data.len() {
392                        Some(data[byte_index..].to_vec())
393                    } else {
394                        None
395                    };
396                    Ok(Address::Ptr(PointerAddress {
397                        network,
398                        payment: payment_cred,
399                        stake: Pointer {
400                            slot,
401                            tx_index,
402                            cert_index,
403                        },
404                        encoding: make_encoding(bytes_encoding, trailing)?,
405                    }))
406                }
407                // enterprise
408                0b0110 | 0b0111 => {
409                    const ENTERPRISE_ADDR_SIZE: usize = 1 + HASH_LEN;
410                    let trailing = len_check_trailing(data, ENTERPRISE_ADDR_SIZE)?;
411                    Ok(Address::Enterprise(EnterpriseAddress {
412                        network,
413                        payment: read_addr_cred(4, 1),
414                        encoding: make_encoding(bytes_encoding, trailing)?,
415                    }))
416                }
417                // reward
418                0b1110 | 0b1111 => {
419                    const REWARD_ADDR_SIZE: usize = 1 + HASH_LEN;
420                    let trailing = len_check_trailing(data, REWARD_ADDR_SIZE)?;
421                    Ok(Address::Reward(RewardAddress {
422                        network,
423                        payment: read_addr_cred(4, 1),
424                        encoding: make_encoding(bytes_encoding, trailing)?,
425                    }))
426                }
427                // byron
428                0b1000 => {
429                    // note: 0b1000 was chosen because all existing Byron addresses actually start with 0b1000
430                    // Therefore you can re-use Byron addresses as-is
431                    ByronAddress::from_cbor_bytes(data)
432                        .map(Address::Byron)
433                        .map_err(|e| DeserializeFailure::InvalidStructure(Box::new(e)).into())
434                }
435                _ => Err(DeserializeFailure::BadAddressType(header).into()),
436            }
437        })()
438        .map_err(|e| e.annotate("Address"))
439    }
440
441    pub fn to_bech32(&self, prefix: Option<String>) -> Result<String, AddressError> {
442        let final_prefix = match prefix {
443            Some(prefix) => prefix,
444            None => {
445                // see CIP5 for bech32 prefix rules
446                let prefix_header = match self {
447                    Self::Reward(_) => "stake",
448                    _ => "addr",
449                };
450                let prefix_tail = match self.network_id()? {
451                    id if id == NetworkInfo::testnet().network_id() => "_test",
452                    _ => "",
453                };
454                format!("{prefix_header}{prefix_tail}")
455            }
456        };
457        bech32::encode(&final_prefix, self.to_raw_bytes().to_base32()).map_err(|e| e.into())
458    }
459
460    pub fn from_bech32(bech_str: &str) -> Result<Address, AddressError> {
461        let (_hrp, u5data) = bech32::decode(bech_str)?;
462        let data: Vec<u8> = bech32::FromBase32::from_base32(&u5data).unwrap();
463        Ok(Self::from_bytes_impl(data.as_ref(), None)?)
464    }
465
466    /**
467     * Note: bech32-encoded Byron addresses will also pass validation here
468     */
469    pub fn is_valid_bech32(bech_str: &str) -> bool {
470        match Self::from_bech32(bech_str) {
471            Ok(_v) => true,
472            Err(_err) => false,
473        }
474    }
475
476    pub fn is_valid_byron(base58: &str) -> bool {
477        ByronAddress::is_valid(base58)
478    }
479
480    pub fn is_valid(bech_str: &str) -> bool {
481        Self::is_valid_bech32(bech_str) || Self::is_valid_byron(bech_str)
482    }
483
484    pub fn kind(&self) -> AddressKind {
485        match self {
486            Self::Base(_) => AddressKind::Base,
487            Self::Byron(_) => AddressKind::Byron,
488            Self::Enterprise(_) => AddressKind::Enterprise,
489            Self::Ptr(_) => AddressKind::Ptr,
490            Self::Reward(_) => AddressKind::Reward,
491        }
492    }
493
494    pub fn network_id(&self) -> Result<u8, AddressError> {
495        match self {
496            Self::Base(a) => Ok(a.network),
497            Self::Enterprise(a) => Ok(a.network),
498            Self::Ptr(a) => Ok(a.network),
499            Self::Reward(a) => Ok(a.network),
500            Self::Byron(a) => a.content.network_id().map_err(Into::into),
501        }
502    }
503
504    /// Note: by convention, the key inside reward addresses are considered payment credentials
505    pub fn payment_cred(&self) -> Option<&StakeCredential> {
506        match self {
507            Self::Base(a) => Some(&a.payment),
508            Self::Enterprise(a) => Some(&a.payment),
509            Self::Ptr(a) => Some(&a.payment),
510            Self::Reward(a) => Some(&a.payment),
511            Self::Byron(_) => None,
512        }
513    }
514
515    /// Note: by convention, the key inside reward addresses are NOT considered staking credentials
516    /// Note: None is returned pointer addresses as the chain history is required to resolve its associated cred
517    pub fn staking_cred(&self) -> Option<&StakeCredential> {
518        match self {
519            Self::Base(a) => Some(&a.stake),
520            Self::Enterprise(_) => None,
521            Self::Ptr(_) => None,
522            Self::Reward(_) => None,
523            Self::Byron(_) => None,
524        }
525    }
526
527    pub(crate) fn encoding(&self) -> Option<&AddressEncoding> {
528        match self {
529            Self::Base(a) => a.encoding.as_ref(),
530            Self::Enterprise(a) => a.encoding.as_ref(),
531            Self::Ptr(a) => a.encoding.as_ref(),
532            Self::Reward(a) => a.encoding.as_ref(),
533            // byron is canonical and follows a specific format with its own quirks
534            Self::Byron(_a) => None,
535        }
536    }
537}
538
539#[derive(Debug, Clone, Derivative)]
540#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
541pub struct BaseAddress {
542    pub network: u8,
543    pub payment: StakeCredential,
544    pub stake: StakeCredential,
545    #[derivative(
546        PartialEq = "ignore",
547        Ord = "ignore",
548        PartialOrd = "ignore",
549        Hash = "ignore"
550    )]
551    pub(crate) encoding: Option<AddressEncoding>,
552}
553
554impl BaseAddress {
555    pub fn new(network: u8, payment: StakeCredential, stake: StakeCredential) -> Self {
556        Self {
557            network,
558            payment,
559            stake,
560            encoding: None,
561        }
562    }
563
564    pub fn to_address(self) -> Address {
565        self.into()
566    }
567
568    pub fn from_address(addr: &Address) -> Option<Self> {
569        match addr {
570            Address::Base(base) => Some(base.clone()),
571            _ => None,
572        }
573    }
574}
575
576impl TryFrom<Address> for BaseAddress {
577    type Error = AddressError;
578
579    fn try_from(addr: Address) -> Result<Self, Self::Error> {
580        match addr {
581            Address::Base(base) => Ok(base),
582            _ => Err(AddressError::WrongKind(addr.kind())),
583        }
584    }
585}
586
587impl From<BaseAddress> for Address {
588    fn from(enterprise: BaseAddress) -> Self {
589        Self::Base(enterprise)
590    }
591}
592
593#[derive(Debug, Clone, Derivative)]
594#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
595pub struct EnterpriseAddress {
596    pub network: u8,
597    pub payment: StakeCredential,
598    #[derivative(
599        PartialEq = "ignore",
600        Ord = "ignore",
601        PartialOrd = "ignore",
602        Hash = "ignore"
603    )]
604    pub(crate) encoding: Option<AddressEncoding>,
605}
606
607impl EnterpriseAddress {
608    pub fn new(network: u8, payment: StakeCredential) -> Self {
609        Self {
610            network,
611            payment,
612            encoding: None,
613        }
614    }
615
616    pub fn to_address(self) -> Address {
617        self.into()
618    }
619
620    pub fn from_address(addr: &Address) -> Option<Self> {
621        match addr {
622            Address::Enterprise(enterprise) => Some(enterprise.clone()),
623            _ => None,
624        }
625    }
626}
627
628impl TryFrom<Address> for EnterpriseAddress {
629    type Error = AddressError;
630
631    fn try_from(addr: Address) -> Result<Self, Self::Error> {
632        match addr {
633            Address::Enterprise(enterprise) => Ok(enterprise),
634            _ => Err(AddressError::WrongKind(addr.kind())),
635        }
636    }
637}
638
639impl From<EnterpriseAddress> for Address {
640    fn from(enterprise: EnterpriseAddress) -> Self {
641        Self::Enterprise(enterprise)
642    }
643}
644
645pub type RewardAccount = RewardAddress;
646
647#[derive(Debug, Clone, Derivative)]
648#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
649pub struct RewardAddress {
650    pub network: u8,
651    pub payment: StakeCredential,
652    #[derivative(
653        PartialEq = "ignore",
654        Ord = "ignore",
655        PartialOrd = "ignore",
656        Hash = "ignore"
657    )]
658    pub(crate) encoding: Option<AddressEncoding>,
659}
660
661impl RewardAddress {
662    pub fn new(network: u8, payment: StakeCredential) -> Self {
663        Self {
664            network,
665            payment,
666            encoding: None,
667        }
668    }
669
670    pub fn to_address(self) -> Address {
671        self.into()
672    }
673
674    pub fn from_address(addr: &Address) -> Option<Self> {
675        match addr {
676            Address::Reward(reward) => Some(reward.clone()),
677            _ => None,
678        }
679    }
680}
681
682impl TryFrom<Address> for RewardAddress {
683    type Error = AddressError;
684
685    fn try_from(addr: Address) -> Result<Self, Self::Error> {
686        match addr {
687            Address::Reward(reward) => Ok(reward),
688            _ => Err(AddressError::WrongKind(addr.kind())),
689        }
690    }
691}
692
693impl From<RewardAddress> for Address {
694    fn from(reward: RewardAddress) -> Self {
695        Self::Reward(reward)
696    }
697}
698
699impl serde::Serialize for RewardAddress {
700    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
701    where
702        S: serde::Serializer,
703    {
704        let bech32 = self
705            .clone()
706            .to_address()
707            .to_bech32(None)
708            .map_err(|e| serde::ser::Error::custom(format!("to_bech32: {e:?}")))?;
709        serializer.serialize_str(&bech32)
710    }
711}
712
713impl<'de> serde::de::Deserialize<'de> for RewardAddress {
714    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
715    where
716        D: serde::de::Deserializer<'de>,
717    {
718        let bech32 = <String as serde::de::Deserialize>::deserialize(deserializer)?;
719        match Address::from_bech32(&bech32)
720            .ok()
721            .map(|addr| RewardAddress::from_address(&addr))
722        {
723            Some(Some(ra)) => Ok(ra),
724            _ => Err(serde::de::Error::invalid_value(
725                serde::de::Unexpected::Str(&bech32),
726                &"bech32 reward address string",
727            )),
728        }
729    }
730}
731
732impl JsonSchema for RewardAddress {
733    fn schema_name() -> String {
734        String::from("RewardAddress")
735    }
736    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
737        String::json_schema(gen)
738    }
739    fn is_referenceable() -> bool {
740        String::is_referenceable()
741    }
742}
743
744#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd, Hash)]
745pub struct Pointer {
746    slot: num_bigint::BigUint,
747    tx_index: num_bigint::BigUint,
748    cert_index: num_bigint::BigUint,
749}
750
751impl Pointer {
752    pub fn new(slot: Slot, tx_index: TransactionIndex, cert_index: CertificateIndex) -> Self {
753        Self {
754            slot: num_bigint::BigUint::from(slot),
755            tx_index: num_bigint::BigUint::from(tx_index),
756            cert_index: num_bigint::BigUint::from(cert_index),
757        }
758    }
759
760    /// This will be truncated if above u64::MAX
761    pub fn slot(&self) -> Slot {
762        self.slot.clone().try_into().unwrap_or(u64::MAX)
763    }
764
765    /// This will be truncated if above u64::MAX
766    pub fn tx_index(&self) -> Slot {
767        self.tx_index.clone().try_into().unwrap_or(u64::MAX)
768    }
769
770    /// This will be truncated if above u64::MAX
771    pub fn cert_index(&self) -> Slot {
772        self.cert_index.clone().try_into().unwrap_or(u64::MAX)
773    }
774}
775
776#[derive(Debug, Clone, Derivative)]
777#[derivative(Eq, PartialEq, Ord, PartialOrd, Hash)]
778pub struct PointerAddress {
779    pub network: u8,
780    pub payment: StakeCredential,
781    pub stake: Pointer,
782    #[derivative(
783        PartialEq = "ignore",
784        Ord = "ignore",
785        PartialOrd = "ignore",
786        Hash = "ignore"
787    )]
788    pub(crate) encoding: Option<AddressEncoding>,
789}
790
791impl PointerAddress {
792    pub fn new(network: u8, payment: StakeCredential, stake: Pointer) -> Self {
793        Self {
794            network,
795            payment,
796            stake,
797            encoding: None,
798        }
799    }
800
801    pub fn to_address(self) -> Address {
802        self.into()
803    }
804
805    pub fn from_address(addr: &Address) -> Option<Self> {
806        match addr {
807            Address::Ptr(pointer) => Some(pointer.clone()),
808            _ => None,
809        }
810    }
811}
812
813impl TryFrom<Address> for PointerAddress {
814    type Error = AddressError;
815
816    fn try_from(addr: Address) -> Result<Self, Self::Error> {
817        match addr {
818            Address::Ptr(pointer) => Ok(pointer),
819            _ => Err(AddressError::WrongKind(addr.kind())),
820        }
821    }
822}
823
824impl From<PointerAddress> for Address {
825    fn from(pointer: PointerAddress) -> Self {
826        Self::Ptr(pointer)
827    }
828}
829
830// serialization
831#[derive(Clone, Debug)]
832pub struct AddressEncoding {
833    // Some addresses were able to make it onchain with trailing data
834    pub(crate) trailing: Option<Vec<u8>>,
835    pub(crate) bytes_encoding: StringEncoding,
836}
837
838#[derive(Clone, Debug, Default)]
839pub struct StakeCredentialEncoding {
840    pub len_encoding: LenEncoding,
841    pub index_0_encoding: Option<cbor_event::Sz>,
842}
843
844impl Serialize for Address {
845    fn serialize<'se, W: Write>(
846        &self,
847        serializer: &'se mut Serializer<W>,
848        force_canonical: bool,
849    ) -> cbor_event::Result<&'se mut Serializer<W>> {
850        let raw_bytes = self.to_raw_bytes();
851        serializer.write_bytes_sz(
852            &raw_bytes,
853            self.encoding()
854                .map(|encs| encs.bytes_encoding.clone())
855                .unwrap_or_default()
856                .to_str_len_sz(raw_bytes.len() as u64, force_canonical),
857        )
858    }
859}
860
861impl Deserialize for Address {
862    fn deserialize<R: BufRead>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
863        let (raw_bytes, encoding) = raw.bytes_sz()?;
864        Self::from_bytes_impl(raw_bytes.as_ref(), Some(encoding.into()))
865    }
866}
867
868impl Serialize for RewardAccount {
869    fn serialize<'se, W: Write>(
870        &self,
871        serializer: &'se mut Serializer<W>,
872        force_canonical: bool,
873    ) -> cbor_event::Result<&'se mut Serializer<W>> {
874        Address::from(self.clone()).serialize(serializer, force_canonical)
875    }
876}
877
878impl Deserialize for RewardAccount {
879    fn deserialize<R: BufRead>(raw: &mut Deserializer<R>) -> Result<Self, DeserializeError> {
880        let (raw_bytes, encoding) = raw.bytes_sz()?;
881        match Address::from_bytes_impl(raw_bytes.as_ref(), Some(encoding.into()))? {
882            Address::Reward(reward_address) => Ok(reward_address),
883            // first byte must exist or else from_bytes_impl would have errored
884            _ => Err(DeserializeFailure::BadAddressType(raw_bytes[0]).into()),
885        }
886    }
887}
888
889#[cfg(test)]
890mod tests {
891    use crate::{byron::AddressContent, transaction::NativeScript};
892
893    use super::*;
894    use cml_core::serialization::ToBytes;
895    use cml_crypto::*;
896
897    #[test]
898    fn variable_nat_encoding() {
899        let cases = [0u64, 127u64, 128u64, 255u64, 256275757658493284u64];
900        for case in cases.iter() {
901            let case_biguint = num_bigint::BigUint::from(*case);
902            let encoded = variable_nat_encode(case_biguint.clone());
903            let decoded = variable_nat_decode(&encoded).unwrap().0;
904            assert_eq!(case_biguint, decoded);
905        }
906    }
907
908    #[test]
909    fn base_serialize_consistency() {
910        let base = BaseAddress::new(
911            5,
912            StakeCredential::new_pub_key(Ed25519KeyHash::from([23; Ed25519KeyHash::BYTE_COUNT])),
913            StakeCredential::new_script(ScriptHash::from([42; ScriptHash::BYTE_COUNT])),
914        );
915        let addr = base.to_address();
916        let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
917        assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
918    }
919
920    #[test]
921    fn ptr_serialize_consistency() {
922        let ptr = PointerAddress::new(
923            25,
924            StakeCredential::new_pub_key(Ed25519KeyHash::from([23; Ed25519KeyHash::BYTE_COUNT])),
925            Pointer::new(2354556573, 127, 0),
926        );
927        let addr = ptr.to_address();
928        let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
929        assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
930    }
931
932    #[test]
933    fn enterprise_serialize_consistency() {
934        let enterprise = EnterpriseAddress::new(
935            64,
936            StakeCredential::new_pub_key(Ed25519KeyHash::from([23; Ed25519KeyHash::BYTE_COUNT])),
937        );
938        let addr = enterprise.to_address();
939        let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
940        assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
941    }
942
943    #[test]
944    fn reward_serialize_consistency() {
945        let reward = RewardAddress::new(
946            9,
947            StakeCredential::new_script(ScriptHash::from([127; Ed25519KeyHash::BYTE_COUNT])),
948        );
949        let addr = reward.to_address();
950        let addr2 = Address::from_cbor_bytes(&addr.to_cbor_bytes()).unwrap();
951        assert_eq!(addr.to_cbor_bytes(), addr2.to_cbor_bytes());
952    }
953
954    #[test]
955    fn address_header_matching() {
956        let reward = RewardAddress::new(
957            0b1001,
958            StakeCredential::new_script(ScriptHash::from([127; Ed25519KeyHash::BYTE_COUNT])),
959        )
960        .to_address();
961        assert_eq!(reward.header(), 0b1111_1001);
962        assert!(Address::header_matches_kind(
963            reward.header(),
964            AddressHeaderKind::RewardScript
965        ))
966    }
967
968    fn root_key_12() -> Bip32PrivateKey {
969        // test walk nut penalty hip pave soap entry language right filter choice
970        let entropy = [
971            0xdf, 0x9e, 0xd2, 0x5e, 0xd1, 0x46, 0xbf, 0x43, 0x33, 0x6a, 0x5d, 0x7c, 0xf7, 0x39,
972            0x59, 0x94,
973        ];
974        Bip32PrivateKey::from_bip39_entropy(&entropy, &[])
975    }
976
977    fn root_key_15() -> Bip32PrivateKey {
978        // art forum devote street sure rather head chuckle guard poverty release quote oak craft enemy
979        let entropy = [
980            0x0c, 0xcb, 0x74, 0xf3, 0x6b, 0x7d, 0xa1, 0x64, 0x9a, 0x81, 0x44, 0x67, 0x55, 0x22,
981            0xd4, 0xd8, 0x09, 0x7c, 0x64, 0x12,
982        ];
983        Bip32PrivateKey::from_bip39_entropy(&entropy, &[])
984    }
985
986    fn root_key_24() -> Bip32PrivateKey {
987        let entropy = [
988            0x4e, 0x82, 0x8f, 0x9a, 0x67, 0xdd, 0xcf, 0xf0, 0xe6, 0x39, 0x1a, 0xd4, 0xf2, 0x6d,
989            0xdb, 0x75, 0x79, 0xf5, 0x9b, 0xa1, 0x4b, 0x6d, 0xd4, 0xba, 0xf6, 0x3d, 0xcf, 0xdb,
990            0x9d, 0x24, 0x20, 0xda,
991        ];
992        Bip32PrivateKey::from_bip39_entropy(&entropy, &[])
993    }
994
995    fn harden(index: u32) -> u32 {
996        index | 0x80_00_00_00
997    }
998
999    #[test]
1000    fn bech32_parsing() {
1001        let addr =
1002            Address::from_bech32("addr1u8pcjgmx7962w6hey5hhsd502araxp26kdtgagakhaqtq8sxy9w7g")
1003                .unwrap();
1004        assert_eq!(
1005            addr.to_bech32(Some("foobar".to_string())).unwrap(),
1006            "foobar1u8pcjgmx7962w6hey5hhsd502araxp26kdtgagakhaqtq8s92n4tm"
1007        );
1008    }
1009
1010    #[test]
1011    fn bip32_12_base() {
1012        let spend = root_key_12()
1013            .derive(harden(1852))
1014            .derive(harden(1815))
1015            .derive(harden(0))
1016            .derive(0)
1017            .derive(0)
1018            .to_public();
1019        let stake = root_key_12()
1020            .derive(harden(1852))
1021            .derive(harden(1815))
1022            .derive(harden(0))
1023            .derive(2)
1024            .derive(0)
1025            .to_public();
1026        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1027        let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1028        let addr_net_0 = BaseAddress::new(
1029            NetworkInfo::testnet().network_id(),
1030            spend_cred.clone(),
1031            stake_cred.clone(),
1032        )
1033        .to_address();
1034        assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwq2ytjqp");
1035        let addr_net_3 =
1036            BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1037                .to_address();
1038        assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwqfjkjv7");
1039    }
1040
1041    #[test]
1042    fn bip32_12_enterprise() {
1043        let spend = root_key_12()
1044            .derive(harden(1852))
1045            .derive(harden(1815))
1046            .derive(harden(0))
1047            .derive(0)
1048            .derive(0)
1049            .to_public();
1050        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1051        let addr_net_0 =
1052            EnterpriseAddress::new(NetworkInfo::testnet().network_id(), spend_cred.clone())
1053                .to_address();
1054        assert_eq!(
1055            addr_net_0.to_bech32(None).unwrap(),
1056            "addr_test1vz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerspjrlsz"
1057        );
1058        let addr_net_3 =
1059            EnterpriseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred).to_address();
1060        assert_eq!(
1061            addr_net_3.to_bech32(None).unwrap(),
1062            "addr1vx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzers66hrl8"
1063        );
1064    }
1065
1066    #[test]
1067    fn bip32_12_pointer() {
1068        let spend = root_key_12()
1069            .derive(harden(1852))
1070            .derive(harden(1815))
1071            .derive(harden(0))
1072            .derive(0)
1073            .derive(0)
1074            .to_public();
1075        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1076        let addr_net_0 = PointerAddress::new(
1077            NetworkInfo::testnet().network_id(),
1078            spend_cred.clone(),
1079            Pointer::new(1, 2, 3),
1080        )
1081        .to_address();
1082        assert_eq!(
1083            addr_net_0.to_bech32(None).unwrap(),
1084            "addr_test1gz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerspqgpsqe70et"
1085        );
1086        let addr_net_3 = PointerAddress::new(
1087            NetworkInfo::mainnet().network_id(),
1088            spend_cred,
1089            Pointer::new(24157, 177, 42),
1090        )
1091        .to_address();
1092        assert_eq!(
1093            addr_net_3.to_bech32(None).unwrap(),
1094            "addr1gx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer5ph3wczvf2w8lunk"
1095        );
1096    }
1097
1098    #[test]
1099    fn bip32_15_base() {
1100        let spend = root_key_15()
1101            .derive(harden(1852))
1102            .derive(harden(1815))
1103            .derive(harden(0))
1104            .derive(0)
1105            .derive(0)
1106            .to_public();
1107        let stake = root_key_15()
1108            .derive(harden(1852))
1109            .derive(harden(1815))
1110            .derive(harden(0))
1111            .derive(2)
1112            .derive(0)
1113            .to_public();
1114        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1115        let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1116        let addr_net_0 = BaseAddress::new(
1117            NetworkInfo::testnet().network_id(),
1118            spend_cred.clone(),
1119            stake_cred.clone(),
1120        )
1121        .to_address();
1122        assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5ewvxwdrt70qlcpeeagscasafhffqsxy36t90ldv06wqrk2qum8x5w");
1123        let addr_net_3 =
1124            BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1125                .to_address();
1126        assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1q9u5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5ewvxwdrt70qlcpeeagscasafhffqsxy36t90ldv06wqrk2qld6xc3");
1127    }
1128
1129    #[test]
1130    fn bip32_15_enterprise() {
1131        let spend = root_key_15()
1132            .derive(harden(1852))
1133            .derive(harden(1815))
1134            .derive(harden(0))
1135            .derive(0)
1136            .derive(0)
1137            .to_public();
1138        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1139        let addr_net_0 =
1140            EnterpriseAddress::new(NetworkInfo::testnet().network_id(), spend_cred.clone())
1141                .to_address();
1142        assert_eq!(
1143            addr_net_0.to_bech32(None).unwrap(),
1144            "addr_test1vpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5eg57c2qv"
1145        );
1146        let addr_net_3 =
1147            EnterpriseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred).to_address();
1148        assert_eq!(
1149            addr_net_3.to_bech32(None).unwrap(),
1150            "addr1v9u5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5eg0kvk0f"
1151        );
1152    }
1153
1154    #[test]
1155    fn bip32_15_pointer() {
1156        let spend = root_key_15()
1157            .derive(harden(1852))
1158            .derive(harden(1815))
1159            .derive(harden(0))
1160            .derive(0)
1161            .derive(0)
1162            .to_public();
1163        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1164        let addr_net_0 = PointerAddress::new(
1165            NetworkInfo::testnet().network_id(),
1166            spend_cred.clone(),
1167            Pointer::new(1, 2, 3),
1168        )
1169        .to_address();
1170        assert_eq!(
1171            addr_net_0.to_bech32(None).unwrap(),
1172            "addr_test1gpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5egpqgpsdhdyc0"
1173        );
1174        let addr_net_3 = PointerAddress::new(
1175            NetworkInfo::mainnet().network_id(),
1176            spend_cred,
1177            Pointer::new(24157, 177, 42),
1178        )
1179        .to_address();
1180        assert_eq!(
1181            addr_net_3.to_bech32(None).unwrap(),
1182            "addr1g9u5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5evph3wczvf2kd5vam"
1183        );
1184    }
1185
1186    #[test]
1187    fn bip32_15_byron() {
1188        let byron_key = root_key_15()
1189            .derive(harden(44))
1190            .derive(harden(1815))
1191            .derive(harden(0))
1192            .derive(0)
1193            .derive(0)
1194            .to_public();
1195        let byron_addr =
1196            AddressContent::icarus_from_key(byron_key, NetworkInfo::mainnet().protocol_magic());
1197        assert_eq!(
1198            byron_addr.to_address().to_base58(),
1199            "Ae2tdPwUPEZHtBmjZBF4YpMkK9tMSPTE2ADEZTPN97saNkhG78TvXdp3GDk"
1200        );
1201        assert!(ByronAddress::is_valid(
1202            "Ae2tdPwUPEZHtBmjZBF4YpMkK9tMSPTE2ADEZTPN97saNkhG78TvXdp3GDk"
1203        ));
1204        assert_eq!(byron_addr.network_id().unwrap(), 0b0001);
1205
1206        // round-trip from generic address type and back
1207        let generic_addr = Address::from_raw_bytes(&byron_addr.to_address().to_bytes()).unwrap();
1208        let byron_addr_2 = ByronAddress::from_address(&generic_addr).unwrap();
1209        assert_eq!(
1210            byron_addr.to_address().to_base58(),
1211            byron_addr_2.to_base58()
1212        );
1213    }
1214
1215    #[test]
1216    fn bip32_24_base() {
1217        let spend = root_key_24()
1218            .derive(harden(1852))
1219            .derive(harden(1815))
1220            .derive(harden(0))
1221            .derive(0)
1222            .derive(0)
1223            .to_public();
1224        let stake = root_key_24()
1225            .derive(harden(1852))
1226            .derive(harden(1815))
1227            .derive(harden(0))
1228            .derive(2)
1229            .derive(0)
1230            .to_public();
1231        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1232        let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1233        let addr_net_0 = BaseAddress::new(
1234            NetworkInfo::testnet().network_id(),
1235            spend_cred.clone(),
1236            stake_cred.clone(),
1237        )
1238        .to_address();
1239        assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qqy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmn8k8ttq8f3gag0h89aepvx3xf69g0l9pf80tqv7cve0l33sw96paj");
1240        let addr_net_3 =
1241            BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1242                .to_address();
1243        assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1qyy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmn8k8ttq8f3gag0h89aepvx3xf69g0l9pf80tqv7cve0l33sdn8p3d");
1244    }
1245
1246    #[test]
1247    fn bip32_24_enterprise() {
1248        let spend = root_key_24()
1249            .derive(harden(1852))
1250            .derive(harden(1815))
1251            .derive(harden(0))
1252            .derive(0)
1253            .derive(0)
1254            .to_public();
1255        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1256        let addr_net_0 =
1257            EnterpriseAddress::new(NetworkInfo::testnet().network_id(), spend_cred.clone())
1258                .to_address();
1259        assert_eq!(
1260            addr_net_0.to_bech32(None).unwrap(),
1261            "addr_test1vqy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnqtjtf68"
1262        );
1263        let addr_net_3 =
1264            EnterpriseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred).to_address();
1265        assert_eq!(
1266            addr_net_3.to_bech32(None).unwrap(),
1267            "addr1vyy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnqs6l44z"
1268        );
1269    }
1270
1271    #[test]
1272    fn bip32_24_pointer() {
1273        let spend = root_key_24()
1274            .derive(harden(1852))
1275            .derive(harden(1815))
1276            .derive(harden(0))
1277            .derive(0)
1278            .derive(0)
1279            .to_public();
1280        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1281        let addr_net_0 = PointerAddress::new(
1282            NetworkInfo::testnet().network_id(),
1283            spend_cred.clone(),
1284            Pointer::new(1, 2, 3),
1285        )
1286        .to_address();
1287        assert_eq!(
1288            addr_net_0.to_bech32(None).unwrap(),
1289            "addr_test1gqy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnqpqgps5mee0p"
1290        );
1291        let addr_net_3 = PointerAddress::new(
1292            NetworkInfo::mainnet().network_id(),
1293            spend_cred,
1294            Pointer::new(24157, 177, 42),
1295        )
1296        .to_address();
1297        assert_eq!(
1298            addr_net_3.to_bech32(None).unwrap(),
1299            "addr1gyy6nhfyks7wdu3dudslys37v252w2nwhv0fw2nfawemmnyph3wczvf2dqflgt"
1300        );
1301    }
1302
1303    #[test]
1304    fn bip32_12_reward() {
1305        let staking_key = root_key_12()
1306            .derive(harden(1852))
1307            .derive(harden(1815))
1308            .derive(harden(0))
1309            .derive(2)
1310            .derive(0)
1311            .to_public();
1312        let staking_cred = StakeCredential::new_pub_key(staking_key.to_raw_key().hash());
1313        let addr_net_0 =
1314            RewardAddress::new(NetworkInfo::testnet().network_id(), staking_cred.clone())
1315                .to_address();
1316        assert_eq!(
1317            addr_net_0.to_bech32(None).unwrap(),
1318            "stake_test1uqevw2xnsc0pvn9t9r9c7qryfqfeerchgrlm3ea2nefr9hqp8n5xl"
1319        );
1320        let addr_net_3 =
1321            RewardAddress::new(NetworkInfo::mainnet().network_id(), staking_cred).to_address();
1322        assert_eq!(
1323            addr_net_3.to_bech32(None).unwrap(),
1324            "stake1uyevw2xnsc0pvn9t9r9c7qryfqfeerchgrlm3ea2nefr9hqxdekzz"
1325        );
1326    }
1327
1328    #[test]
1329    fn bip32_24_base_multisig_hd_derivation() {
1330        let spend = root_key_24()
1331            .derive(harden(1854))
1332            .derive(harden(1815))
1333            .derive(harden(0))
1334            .derive(0)
1335            .derive(0)
1336            .to_public();
1337        let stake = root_key_24()
1338            .derive(harden(1854))
1339            .derive(harden(1815))
1340            .derive(harden(0))
1341            .derive(2)
1342            .derive(0)
1343            .to_public();
1344        let spend_cred = StakeCredential::new_pub_key(spend.to_raw_key().hash());
1345        let stake_cred = StakeCredential::new_pub_key(stake.to_raw_key().hash());
1346        let addr_net_0 = BaseAddress::new(
1347            NetworkInfo::testnet().network_id(),
1348            spend_cred.clone(),
1349            stake_cred.clone(),
1350        )
1351        .to_address();
1352        assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1qz8fg2e9yn0ga6sav0760cxmx0antql96mfuhqgzcc5swugw2jqqlugnx9qjep9xvcx40z0zfyep55r2t3lav5smyjrs96cusg");
1353        let addr_net_3 =
1354            BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1355                .to_address();
1356        assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1qx8fg2e9yn0ga6sav0760cxmx0antql96mfuhqgzcc5swugw2jqqlugnx9qjep9xvcx40z0zfyep55r2t3lav5smyjrsxv9uuh");
1357    }
1358
1359    #[test]
1360    fn multisig_from_script() {
1361        let spend = root_key_24()
1362            .derive(harden(1852))
1363            .derive(harden(1815))
1364            .derive(harden(0))
1365            .derive(0)
1366            .derive(0)
1367            .to_public();
1368
1369        let mut pubkey_native_scripts = Vec::new();
1370
1371        let spending_hash = spend.to_raw_key().hash();
1372        pubkey_native_scripts.push(NativeScript::new_script_pubkey(spending_hash));
1373        let oneof_native_script = NativeScript::new_script_n_of_k(1, pubkey_native_scripts);
1374
1375        let script_hash =
1376            ScriptHash::from_raw_bytes(oneof_native_script.hash().to_raw_bytes()).unwrap();
1377
1378        let spend_cred = StakeCredential::new_script(script_hash);
1379        let stake_cred = StakeCredential::new_script(script_hash);
1380        let addr_net_0 = BaseAddress::new(
1381            NetworkInfo::testnet().network_id(),
1382            spend_cred.clone(),
1383            stake_cred.clone(),
1384        )
1385        .to_address();
1386        assert_eq!(addr_net_0.to_bech32(None).unwrap(), "addr_test1xr0de0mz3m9xmgtlmqqzu06s0uvfsczskdec8k7v4jhr7077mjlk9rk2dkshlkqq9cl4qlccnps9pvmns0duet9w8uls8flvxc");
1387        let addr_net_3 =
1388            BaseAddress::new(NetworkInfo::mainnet().network_id(), spend_cred, stake_cred)
1389                .to_address();
1390        assert_eq!(addr_net_3.to_bech32(None).unwrap(), "addr1x80de0mz3m9xmgtlmqqzu06s0uvfsczskdec8k7v4jhr7077mjlk9rk2dkshlkqq9cl4qlccnps9pvmns0duet9w8ulsylzv28");
1391    }
1392
1393    #[test]
1394    fn pointer_address_big() {
1395        let addr = Address::from_bech32("addr_test1grqe6lg9ay8wkcu5k5e38lne63c80h3nq6xxhqfmhewf645pllllllllllll7lupllllllllllll7lupllllllllllll7lc9wayvj").unwrap();
1396        let ptr = PointerAddress::from_address(&addr).unwrap().stake;
1397        let u64_max = num_bigint::BigUint::from(u64::MAX);
1398        assert_eq!(u64_max, ptr.slot);
1399        assert_eq!(u64_max, ptr.tx_index);
1400        assert_eq!(u64_max, ptr.cert_index);
1401    }
1402
1403    #[test]
1404    fn long_address() {
1405        let long = Address::from_bech32("addr1q9d66zzs27kppmx8qc8h43q7m4hkxp5d39377lvxefvxd8j7eukjsdqc5c97t2zg5guqadepqqx6rc9m7wtnxy6tajjvk4a0kze4ljyuvvrpexg5up2sqxj33363v35gtew").unwrap();
1406        let long_trimmed = Address::from_bech32("addr1q9d66zzs27kppmx8qc8h43q7m4hkxp5d39377lvxefvxd8j7eukjsdqc5c97t2zg5guqadepqqx6rc9m7wtnxy6tajjq6r54x9").unwrap();
1407        assert_eq!(long, long_trimmed);
1408        assert_eq!(
1409            long.encoding().unwrap().trailing,
1410            Some(vec![
1411                203u8, 87, 175, 176, 179, 95, 200, 156, 99, 6, 28, 153, 20, 224, 85, 0, 26, 81,
1412                140, 117, 22
1413            ])
1414        );
1415        assert_eq!(
1416            long_trimmed.encoding().and_then(|enc| enc.trailing.clone()),
1417            None
1418        );
1419        assert_eq!(
1420            hex::encode(long.to_raw_bytes()),
1421            "015bad085057ac10ecc7060f7ac41edd6f63068d8963ef7d86ca58669e5ecf2d283418a60be5a848a2380eb721000da1e0bbf39733134beca4cb57afb0b35fc89c63061c9914e055001a518c7516"
1422        );
1423        let long_not_whitelisted = Address::from_bech32(
1424            "addr_test1vqt3w9chzut3w9chzut3w9chzut3w9chzut3w9chzut3w9cqqspqvqcqsmxqdssg97",
1425        );
1426        assert!(long_not_whitelisted.is_err());
1427    }
1428
1429    #[test]
1430    fn ptr_addr_huge_slot() {
1431        let addr_bytes: Vec<u8> = vec![
1432            64, 193, 157, 125, 5, 233, 14, 235, 99, 148, 181, 51, 19, 254, 121, 212, 112, 119, 222,
1433            51, 6, 140, 107, 129, 59, 190, 92, 157, 86, 129, 255, 255, 255, 255, 255, 255, 255,
1434            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1435            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1436            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1437            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1438            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1439            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1440            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1441            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1442            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1443            255, 255, 255, 255, 255, 255, 255, 255, 127, 129, 255, 255, 255, 255, 255, 255, 255,
1444            255, 127, 129, 255, 255, 255, 255, 255, 255, 255, 255, 127,
1445        ];
1446        let addr = Address::from_raw_bytes(&addr_bytes).unwrap();
1447        assert_eq!(addr_bytes, addr.to_raw_bytes());
1448    }
1449}