Skip to main content

elements/
address.rs

1// Rust Elements Library
2// Written by
3//   The Elements developers
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! # Addresses
16//!
17
18use std::convert::{TryFrom as _, TryInto as _};
19use std::error;
20use std::fmt;
21use std::fmt::Write as _;
22use std::str::FromStr;
23
24use bech32::{Bech32, Bech32m, ByteIterExt, Fe32, Fe32IterExt, Hrp};
25use crate::blech32::{Blech32, Blech32m};
26use bitcoin::base58;
27use bitcoin::hashes::Hash as _;
28use bitcoin::PublicKey;
29use internals::array::ArrayExt as _;
30use internals::slice::SliceExt;
31use secp256k1_zkp;
32use secp256k1_zkp::Secp256k1;
33use secp256k1_zkp::Verification;
34#[cfg(feature = "serde")]
35use serde;
36
37use crate::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
38use crate::taproot::TapNodeHash;
39
40use crate::{opcodes, script};
41use crate::{PubkeyHash, ScriptHash, WScriptHash};
42
43/// Encoding error
44#[derive(Debug, PartialEq)]
45pub enum AddressError {
46    /// Base58 encoding error
47    Base58(base58::Error),
48    /// Bech32 encoding error
49    Bech32(bech32::primitives::decode::SegwitHrpstringError),
50    /// Blech32 encoding error
51    Blech32(crate::blech32::decode::SegwitHrpstringError),
52    /// Was unable to parse the address.
53    InvalidAddress(String),
54    /// Script version must be 0 to 16 inclusive
55    InvalidWitnessVersion(u8),
56    /// The witness program must be between 2 and 40 bytes in length.
57    InvalidWitnessProgramLength(usize),
58    /// A v0 witness program must be either of length 20 or 32.
59    InvalidSegwitV0ProgramLength(usize),
60    /// A v1+ witness program must use b(l)ech32m not b(l)ech32
61    InvalidWitnessEncoding,
62    /// A v0 witness program must use b(l)ech32 not b(l)ech32m
63    InvalidSegwitV0Encoding,
64
65    /// An invalid blinding pubkey was encountered.
66    InvalidBlindingPubKey(secp256k1_zkp::UpstreamError),
67
68    /// The length (in bytes) of the object was not correct.
69    InvalidLength(usize),
70
71    /// Address version byte were not recognized.
72    InvalidAddressVersion(u8),
73}
74
75impl From<bech32::primitives::decode::SegwitHrpstringError> for AddressError {
76    fn from(e: bech32::primitives::decode::SegwitHrpstringError) -> Self {
77        AddressError::Bech32(e)
78    }
79}
80
81impl From<crate::blech32::decode::SegwitHrpstringError> for AddressError {
82    fn from(e: crate::blech32::decode::SegwitHrpstringError) -> Self {
83        AddressError::Blech32(e)
84    }
85}
86
87impl fmt::Display for AddressError {
88    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89        match *self {
90            AddressError::Base58(ref e) => write!(f, "base58 error: {}", e),
91            AddressError::Bech32(ref e) => write!(f, "bech32 error: {}", e),
92            AddressError::Blech32(ref e) => write!(f, "blech32 error: {}", e),
93            AddressError::InvalidAddress(ref a) => {
94                write!(f, "was unable to parse the address: {}", a)
95            }
96            AddressError::InvalidWitnessVersion(ref wver) => {
97                write!(f, "invalid witness script version: {}", wver)
98            }
99            AddressError::InvalidWitnessProgramLength(ref len) => {
100                write!(
101                    f,
102                    "the witness program must be between 2 and 40 bytes in length, not {}",
103                    len
104                )
105            }
106            AddressError::InvalidSegwitV0ProgramLength(ref len) => {
107                write!(
108                    f,
109                    "a v0 witness program must be length 20 or 32, not {}",
110                    len
111                )
112            }
113            AddressError::InvalidBlindingPubKey(ref e) => {
114                write!(f, "an invalid blinding pubkey was encountered: {}", e)
115            }
116            AddressError::InvalidWitnessEncoding => {
117                write!(f, "v1+ witness program must use b(l)ech32m not b(l)ech32")
118            }
119            AddressError::InvalidSegwitV0Encoding => {
120                write!(f, "v0 witness program must use b(l)ech32 not b(l)ech32m")
121            }
122            AddressError::InvalidLength(len) => {
123                write!(f, "Address data has invalid length {}", len)
124            }
125            AddressError::InvalidAddressVersion(v) => {
126                write!(f, "address version {} is invalid for this type", v)
127            }
128        }
129    }
130}
131
132impl error::Error for AddressError {
133    fn cause(&self) -> Option<&dyn error::Error> {
134        match *self {
135            AddressError::Base58(ref e) => Some(e),
136            AddressError::Bech32(ref e) => Some(e),
137            AddressError::Blech32(ref e) => Some(e),
138            AddressError::InvalidBlindingPubKey(ref e) => Some(e),
139            _ => None,
140        }
141    }
142}
143
144#[doc(hidden)]
145impl From<base58::Error> for AddressError {
146    fn from(e: base58::Error) -> AddressError {
147        AddressError::Base58(e)
148    }
149}
150
151/// The parameters to derive addresses.
152#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub struct AddressParams {
154    /// The base58 prefix for p2pkh addresses.
155    pub p2pkh_prefix: u8,
156    /// The base58 prefix for p2sh addresses.
157    pub p2sh_prefix: u8,
158    /// The base58 prefix for blinded addresses.
159    pub blinded_prefix: u8,
160    /// The bech32 HRP for unblinded segwit addresses.
161    pub bech_hrp: Hrp,
162    /// The bech32 HRP for blinded segwit addresses.
163    pub blech_hrp: Hrp,
164}
165
166impl AddressParams {
167    /// The Liquid network address parameters.
168    pub const LIQUID: AddressParams = AddressParams {
169        p2pkh_prefix: 57,
170        p2sh_prefix: 39,
171        blinded_prefix: 12,
172        bech_hrp: Hrp::parse_unchecked("ex"),
173        blech_hrp: Hrp::parse_unchecked("lq"),
174    };
175
176    /// The default Elements network address parameters.
177    pub const ELEMENTS: AddressParams = AddressParams {
178        p2pkh_prefix: 235,
179        p2sh_prefix: 75,
180        blinded_prefix: 4,
181        bech_hrp: Hrp::parse_unchecked("ert"),
182        blech_hrp: Hrp::parse_unchecked("el"),
183    };
184
185    /// The default liquid testnet network address parameters.
186    pub const LIQUID_TESTNET: AddressParams = AddressParams {
187        p2pkh_prefix: 36,
188        p2sh_prefix: 19,
189        blinded_prefix: 23,
190        bech_hrp: Hrp::parse_unchecked("tex"),
191        blech_hrp: Hrp::parse_unchecked("tlq"),
192    };
193}
194
195/// The method used to produce an address
196#[derive(Debug, Clone, PartialEq, Eq, Hash)]
197pub enum Payload {
198    /// pay-to-pkhash address
199    PubkeyHash(PubkeyHash),
200    /// P2SH address
201    ScriptHash(ScriptHash),
202    /// Segwit address
203    WitnessProgram {
204        /// The segwit version.
205        version: Fe32,
206        /// The segwit program.
207        program: Vec<u8>,
208    },
209}
210
211/// An Elements address.
212#[derive(Clone, PartialEq, Eq, Hash)]
213pub struct Address {
214    /// the network
215    pub params: &'static AddressParams,
216    /// the traditional non-confidential payload
217    pub payload: Payload,
218    /// the blinding pubkey
219    pub blinding_pubkey: Option<secp256k1_zkp::PublicKey>,
220}
221
222impl Address {
223    /// Inspect if the address is a blinded address.
224    pub fn is_blinded(&self) -> bool {
225        self.blinding_pubkey.is_some()
226    }
227
228    /// Return if the address is for the Liquid network
229    pub fn is_liquid(&self) -> bool {
230        self.params == &AddressParams::LIQUID
231    }
232
233    /// Creates a pay to (compressed) public key hash address from a public key
234    /// This is the preferred non-witness type address
235    #[inline]
236    pub fn p2pkh(
237        pk: &PublicKey,
238        blinder: Option<secp256k1_zkp::PublicKey>,
239        params: &'static AddressParams,
240    ) -> Address {
241        Address {
242            params,
243            payload: Payload::PubkeyHash(pk.pubkey_hash()),
244            blinding_pubkey: blinder,
245        }
246    }
247
248    /// Creates a pay to script hash P2SH address from a script
249    /// This address type was introduced with BIP16 and is the popular type to implement multi-sig these days.
250    #[inline]
251    pub fn p2sh(
252        script: &script::Script,
253        blinder: Option<secp256k1_zkp::PublicKey>,
254        params: &'static AddressParams,
255    ) -> Address {
256        Address {
257            params,
258            payload: Payload::ScriptHash(ScriptHash::hash_script(script)),
259            blinding_pubkey: blinder,
260        }
261    }
262
263    /// Create a witness pay to public key address from a public key
264    /// This is the native segwit address type for an output redeemable with a single signature
265    ///
266    /// # Panics
267    ///
268    /// Panics if the provided public key is not compressed.
269    pub fn p2wpkh(
270        pk: &PublicKey,
271        blinder: Option<secp256k1_zkp::PublicKey>,
272        params: &'static AddressParams,
273    ) -> Address {
274        Address {
275            params,
276            payload: Payload::WitnessProgram {
277                version: Fe32::Q,
278                program: pk.wpubkey_hash().expect("public key must be compressed").as_byte_array().to_vec(),
279            },
280            blinding_pubkey: blinder,
281        }
282    }
283
284    /// Create a pay to script address that embeds a witness pay to public key
285    /// This is a segwit address type that looks familiar (as p2sh) to legacy clients
286    ///
287    /// # Panics
288    ///
289    /// Panics if the provided public key is not compressed.
290    pub fn p2shwpkh(
291        pk: &PublicKey,
292        blinder: Option<secp256k1_zkp::PublicKey>,
293        params: &'static AddressParams,
294    ) -> Address {
295        let pkh = pk.wpubkey_hash().expect("public key must be compressed");
296        let builder = script::Builder::new()
297            .push_int(0)
298            .push_slice(pkh.as_ref());
299
300        Address {
301            params,
302            payload: Payload::ScriptHash(ScriptHash::hash_script(&builder.into_script())),
303            blinding_pubkey: blinder,
304        }
305    }
306
307    /// Create a witness pay to script hash address
308    pub fn p2wsh(
309        script: &script::Script,
310        blinder: Option<secp256k1_zkp::PublicKey>,
311        params: &'static AddressParams,
312    ) -> Address {
313        Address {
314            params,
315            payload: Payload::WitnessProgram {
316                version: Fe32::Q,
317                program: WScriptHash::hash_script(script).as_byte_array().to_vec(),
318            },
319            blinding_pubkey: blinder,
320        }
321    }
322
323    /// Create a pay to script address that embeds a witness pay to script hash address
324    /// This is a segwit address type that looks familiar (as p2sh) to legacy clients
325    pub fn p2shwsh(
326        script: &script::Script,
327        blinder: Option<secp256k1_zkp::PublicKey>,
328        params: &'static AddressParams,
329    ) -> Address {
330        let ws = script::Builder::new()
331            .push_int(0)
332            .push_slice(WScriptHash::hash_script(script).as_ref())
333            .into_script();
334
335        Address {
336            params,
337            payload: Payload::ScriptHash(ScriptHash::hash_script(&ws)),
338            blinding_pubkey: blinder,
339        }
340    }
341
342    /// Creates a pay to taproot address from an untweaked key.
343    pub fn p2tr<C: Verification>(
344        secp: &Secp256k1<C>,
345        internal_key: UntweakedPublicKey,
346        merkle_root: Option<TapNodeHash>,
347        blinder: Option<secp256k1_zkp::PublicKey>,
348        params: &'static AddressParams,
349    ) -> Address {
350        Address {
351            params,
352            payload: {
353                let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root);
354                Payload::WitnessProgram {
355                    version: Fe32::P,
356                    program: output_key.into_inner().serialize().to_vec(),
357                }
358            },
359            blinding_pubkey: blinder,
360        }
361    }
362
363    /// Creates a pay to taproot address from a pre-tweaked output key.
364    ///
365    /// This method is not recommended for use, [`Address::p2tr()`] should be used where possible.
366    pub fn p2tr_tweaked(
367        output_key: TweakedPublicKey,
368        blinder: Option<secp256k1_zkp::PublicKey>,
369        params: &'static AddressParams,
370    ) -> Address {
371        Address {
372            params,
373            payload: Payload::WitnessProgram {
374                version: Fe32::P,
375                program: output_key.into_inner().serialize().to_vec(),
376            },
377            blinding_pubkey: blinder,
378        }
379    }
380
381    /// Get an [Address] from an output script.
382    pub fn from_script(
383        script: &script::Script,
384        blinder: Option<secp256k1_zkp::PublicKey>,
385        params: &'static AddressParams,
386    ) -> Option<Address> {
387        Some(Address {
388            payload: if script.is_p2pkh() {
389                Payload::PubkeyHash(PubkeyHash::from_byte_array(script.as_bytes()[3..23].try_into().unwrap()))
390            } else if script.is_p2sh() {
391                Payload::ScriptHash(ScriptHash::from_byte_array(script.as_bytes()[2..22].try_into().unwrap()))
392            } else if script.is_v0_p2wpkh() {
393                Payload::WitnessProgram {
394                    version: Fe32::Q,
395                    program: script.as_bytes()[2..22].to_vec(),
396                }
397            } else if script.is_v0_p2wsh() {
398                Payload::WitnessProgram {
399                    version: Fe32::Q,
400                    program: script.as_bytes()[2..34].to_vec(),
401                }
402            } else if script.is_v1plus_p2witprog() {
403                Payload::WitnessProgram {
404                    version: Fe32::try_from(script.as_bytes()[0] - 0x50).expect("0<32"),
405                    program: script.as_bytes()[2..].to_vec(),
406                }
407            } else {
408                return None;
409            },
410            blinding_pubkey: blinder,
411            params,
412        })
413    }
414
415    /// Generates a script pubkey spending to this address
416    pub fn script_pubkey(&self) -> script::Script {
417        match self.payload {
418            Payload::PubkeyHash(ref hash) => script::Builder::new()
419                .push_opcode(opcodes::all::OP_DUP)
420                .push_opcode(opcodes::all::OP_HASH160)
421                .push_slice(hash.as_ref())
422                .push_opcode(opcodes::all::OP_EQUALVERIFY)
423                .push_opcode(opcodes::all::OP_CHECKSIG),
424            Payload::ScriptHash(ref hash) => script::Builder::new()
425                .push_opcode(opcodes::all::OP_HASH160)
426                .push_slice(hash.as_byte_array())
427                .push_opcode(opcodes::all::OP_EQUAL),
428            Payload::WitnessProgram {
429                version: witver,
430                program: ref witprog,
431            } => script::Builder::new()
432                .push_int(i64::from(witver.to_u8()))
433                .push_slice(witprog),
434        }
435        .into_script()
436    }
437
438    /// Convert this address to an unconfidential address.
439    #[must_use]
440    pub fn to_unconfidential(&self) -> Address {
441        Address {
442            params: self.params,
443            payload: self.payload.clone(),
444            blinding_pubkey: None,
445        }
446    }
447
448    /// Convert this address to a confidential address with the given blinding pubkey.
449    #[must_use]
450    pub fn to_confidential(&self, blinding_pubkey: secp256k1_zkp::PublicKey) -> Address {
451        Address {
452            params: self.params,
453            payload: self.payload.clone(),
454            blinding_pubkey: Some(blinding_pubkey),
455        }
456    }
457
458    fn from_bech32(
459        s: &str,
460        blinded: bool,
461        params: &'static AddressParams,
462    ) -> Result<Address, AddressError> {
463        let (version, data): (Fe32, Vec<u8>) = if blinded {
464            let hs = crate::blech32::decode::SegwitHrpstring::new(s)?;
465            (hs.witness_version(), hs.byte_iter().collect())
466        } else {
467            let hs = bech32::primitives::decode::SegwitHrpstring::new(s)?;
468            (hs.witness_version(), hs.byte_iter().collect())
469        };
470
471        let (blinding_pubkey, program) = match blinded {
472            true => {
473                let (pk, rest) = SliceExt::split_first_chunk::<33>(data.as_slice())
474                    .ok_or(AddressError::InvalidSegwitV0Encoding)?;
475                (
476                Some(
477                    secp256k1_zkp::PublicKey::from_slice(pk)
478                        .map_err(AddressError::InvalidBlindingPubKey)?,
479                    ),
480                    rest.to_vec(),
481                )
482            },
483            false => (None, data),
484        };
485
486        Ok(Address {
487            params,
488            payload: Payload::WitnessProgram { version, program },
489            blinding_pubkey,
490        })
491    }
492
493    // data.len() should be >= 1 when this method is called
494    fn from_base58(data: &[u8], params: &'static AddressParams) -> Result<Address, AddressError> {
495        let len_error = AddressError::InvalidLength(data.len());
496        // When unblinded, the structure is:
497        // <1: regular prefix> <20: hash160>
498        // When blinded, the structure is:
499        // <1: blinding prefix> <1: regular prefix> <33: blinding pubkey> <20: hash160>
500
501        let Some((blinding_prefix, blinded_data)) = data.split_first() else {
502            return Err(len_error);
503        };
504
505        let (prefix, blinding_pubkey, hash) = if *blinding_prefix == params.blinded_prefix {
506            let Some((prefix, pubkey_and_hash)) = blinded_data.split_first() else {
507                return Err(len_error);
508            };
509
510            let pubkey_and_hash = <&[u8; 53]>::try_from(pubkey_and_hash).map_err(|_| len_error)?;
511            let (pubkey, hash) = pubkey_and_hash.split_array::<33, 20>();
512
513            let blinding_pubkey = secp256k1_zkp::PublicKey::from_slice(pubkey)
514                .map_err(AddressError::InvalidBlindingPubKey)?;
515
516            (prefix, Some(blinding_pubkey), hash)
517        } else {
518            let hash = <&[u8; 20]>::try_from(blinded_data).map_err(|_| len_error)?;
519            (blinding_prefix, None, hash)
520        };
521
522        let payload = if *prefix == params.p2pkh_prefix {
523            Payload::PubkeyHash(PubkeyHash::from_byte_array(*hash))
524        } else if *prefix == params.p2sh_prefix {
525            Payload::ScriptHash(ScriptHash::from_byte_array(*hash))
526        } else {
527            return Err(AddressError::InvalidAddressVersion(*prefix));
528        };
529
530        Ok(Address {
531            params,
532            payload,
533            blinding_pubkey,
534        })
535    }
536
537    /// Parse the address using the given parameters.
538    /// When using the built-in parameters, you can use [`FromStr`].
539    pub fn parse_with_params(
540        s: &str,
541        params: &'static AddressParams,
542    ) -> Result<Address, AddressError> {
543        // Bech32.
544        let prefix = find_prefix(s);
545        let b32_ex = match_prefix(prefix, params.bech_hrp);
546        let b32_bl = match_prefix(prefix, params.blech_hrp);
547        if b32_ex || b32_bl {
548            return Address::from_bech32(s, b32_bl, params);
549        }
550
551        // Base58.
552        if s.len() > 150 {
553            return Err(AddressError::InvalidLength(s.len() * 11 / 15));
554        }
555        let data = base58::decode_check(s)?;
556        Address::from_base58(&data, params)
557    }
558}
559
560impl fmt::Display for Address {
561    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
562        match self.payload {
563            Payload::PubkeyHash(ref hash) => {
564                if let Some(ref blinder) = self.blinding_pubkey {
565                    let mut prefixed = [0; 55]; // 1 + 1 + 33 + 20
566                    prefixed[0] = self.params.blinded_prefix;
567                    prefixed[1] = self.params.p2pkh_prefix;
568                    prefixed[2..35].copy_from_slice(&blinder.serialize());
569                    prefixed[35..].copy_from_slice(hash.as_ref());
570                    base58::encode_check_to_fmt(fmt, &prefixed[..])
571                } else {
572                    let mut prefixed = [0; 21];
573                    prefixed[0] = self.params.p2pkh_prefix;
574                    prefixed[1..].copy_from_slice(hash.as_ref());
575                    base58::encode_check_to_fmt(fmt, &prefixed[..])
576                }
577            }
578            Payload::ScriptHash(ref hash) => {
579                if let Some(ref blinder) = self.blinding_pubkey {
580                    let mut prefixed = [0; 55]; // 1 + 1 + 33 + 20
581                    prefixed[0] = self.params.blinded_prefix;
582                    prefixed[1] = self.params.p2sh_prefix;
583                    prefixed[2..35].copy_from_slice(&blinder.serialize());
584                    prefixed[35..].copy_from_slice(hash.as_byte_array());
585                    base58::encode_check_to_fmt(fmt, &prefixed[..])
586                } else {
587                    let mut prefixed = [0; 21];
588                    prefixed[0] = self.params.p2sh_prefix;
589                    prefixed[1..].copy_from_slice(hash.as_byte_array());
590                    base58::encode_check_to_fmt(fmt, &prefixed[..])
591                }
592            }
593            Payload::WitnessProgram {
594                version: witver,
595                program: ref witprog,
596            } => {
597                let hrp = match self.blinding_pubkey.is_some() {
598                    true => self.params.blech_hrp,
599                    false => self.params.bech_hrp,
600                };
601
602                // FIXME: surely we can fix this logic to not be so repetitive.
603                if self.is_blinded() {
604                    if let Some(ref blinder) = self.blinding_pubkey {
605                        let byte_iter = IntoIterator::into_iter(blinder.serialize())
606                            .chain(witprog.iter().copied());
607                        let fe_iter = byte_iter.bytes_to_fes();
608                        if witver.to_u8() == 0 {
609                            for c in fe_iter
610                                .with_checksum::<Blech32>(&hrp)
611                                .with_witness_version(witver)
612                                .chars()
613                            {
614                                fmt.write_char(c)?;
615                            }
616                        } else {
617                            for c in fe_iter
618                                .with_checksum::<Blech32m>(&hrp)
619                                .with_witness_version(witver)
620                                .chars()
621                            {
622                                fmt.write_char(c)?;
623                            }
624                        }
625                        return Ok(());
626                    }
627                }
628
629                let byte_iter = witprog.iter().copied();
630                let fe_iter = byte_iter.bytes_to_fes();
631                if witver.to_u8() == 0 {
632                    for c in fe_iter
633                        .with_checksum::<Bech32>(&hrp)
634                        .with_witness_version(witver)
635                        .chars()
636                    {
637                        fmt.write_char(c)?;
638                    }
639                } else {
640                    for c in fe_iter
641                        .with_checksum::<Bech32m>(&hrp)
642                        .with_witness_version(witver)
643                        .chars()
644                    {
645                        fmt.write_char(c)?;
646                    }
647                }
648                Ok(())
649            }
650        }
651    }
652}
653
654impl fmt::Debug for Address {
655    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
656        fmt::Display::fmt(self, fmt)
657    }
658}
659
660/// Extract the bech32 prefix.
661/// Returns the same slice when no prefix is found.
662fn find_prefix(bech32: &str) -> &str {
663    // Split at the last occurrence of the separator character '1'.
664    match bech32.rfind('1') {
665        None => bech32,
666        Some(sep) => bech32.split_at(sep).0,
667    }
668}
669
670/// Checks if both prefixes match, regardless of case.
671/// The first prefix can be mixed case, but the second one is expected in
672/// lower case.
673fn match_prefix(prefix_mixed: &str, target: Hrp) -> bool {
674    target.len() == prefix_mixed.len() && target
675        .lowercase_char_iter()
676        .zip(prefix_mixed.chars())
677        .all(|(char_lower, char_mixed)| char_lower == char_mixed.to_ascii_lowercase())
678}
679
680impl FromStr for Address {
681    type Err = AddressError;
682
683    fn from_str(s: &str) -> Result<Address, AddressError> {
684        // shorthands
685        let liq = &AddressParams::LIQUID;
686        let ele = &AddressParams::ELEMENTS;
687        let liq_test = &AddressParams::LIQUID_TESTNET;
688
689        let net_arr = [liq, ele, liq_test];
690
691        let prefix = find_prefix(s);
692        for net in &net_arr {
693            // Bech32.
694            if match_prefix(prefix, net.bech_hrp) {
695                return Address::from_bech32(s, false, net);
696            }
697            if match_prefix(prefix, net.blech_hrp) {
698                return Address::from_bech32(s, true, net);
699            }
700        }
701
702        // Base58.
703        if s.len() > 150 {
704            return Err(AddressError::InvalidLength(s.len() * 11 / 15));
705        }
706        let data = base58::decode_check(s)?;
707        if data.is_empty() {
708            return Err(AddressError::InvalidLength(data.len()));
709        }
710
711        let p = data[0];
712        for net in &net_arr {
713            if p == net.p2pkh_prefix || p == net.p2sh_prefix || p == net.blinded_prefix {
714                return Address::from_base58(&data, net);
715            }
716        }
717
718        Err(AddressError::InvalidAddress(s.to_owned()))
719    }
720}
721
722#[cfg(feature = "serde")]
723impl<'de> serde::Deserialize<'de> for Address {
724    #[inline]
725    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
726    where
727        D: serde::Deserializer<'de>,
728    {
729        use std::fmt::Formatter;
730
731        struct Visitor;
732        impl<'de> serde::de::Visitor<'de> for Visitor {
733            type Value = Address;
734
735            fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
736                formatter.write_str("a Bitcoin address")
737            }
738
739            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
740            where
741                E: serde::de::Error,
742            {
743                Address::from_str(v).map_err(E::custom)
744            }
745
746            fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
747            where
748                E: serde::de::Error,
749            {
750                self.visit_str(v)
751            }
752
753            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
754            where
755                E: serde::de::Error,
756            {
757                self.visit_str(&v)
758            }
759        }
760
761        deserializer.deserialize_str(Visitor)
762    }
763}
764
765#[cfg(feature = "serde")]
766impl serde::Serialize for Address {
767    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
768    where
769        S: serde::Serializer,
770    {
771        serializer.serialize_str(&self.to_string())
772    }
773}
774
775#[cfg(test)]
776mod test {
777    use super::*;
778    use crate::Script;
779    use bitcoin::key;
780    use secp256k1_zkp::{PublicKey, Secp256k1};
781    #[cfg(feature = "serde")]
782    use serde_json;
783
784    fn roundtrips(addr: &Address) {
785        assert_eq!(
786            Address::from_str(&addr.to_string()).ok().as_ref(),
787            Some(addr),
788            "string round-trip failed for {}",
789            addr,
790        );
791        assert_eq!(
792            Address::from_script(&addr.script_pubkey(), addr.blinding_pubkey, addr.params).as_ref(),
793            Some(addr),
794            "script round-trip failed for {}",
795            addr,
796        );
797        #[cfg(feature = "serde")]
798        assert_eq!(
799            serde_json::from_value::<Address>(serde_json::to_value(addr).unwrap())
800                .ok()
801                .as_ref(),
802            Some(addr)
803        );
804    }
805
806    #[test]
807    fn regression_188() {
808        // Tests that the `tlq` prefix was not accidentally changed, e.g. to `tlg` :).
809        let addr = Address::from_str("tlq1qq2xvpcvfup5j8zscjq05u2wxxjcyewk7979f3mmz5l7uw5pqmx6xf5xy50hsn6vhkm5euwt72x878eq6zxx2z58hd7zrsg9qn").unwrap();
810        roundtrips(&addr);
811    }
812
813    #[test]
814    fn exhaustive() {
815        let blinder_hex = "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
816        let blinder = PublicKey::from_str(blinder_hex).unwrap();
817        let sk_wif = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy";
818        let sk = key::PrivateKey::from_wif(sk_wif).unwrap();
819        let pk = sk.public_key(&Secp256k1::new());
820        let script: Script = vec![1u8, 2, 42, 255, 196].into();
821
822        let vectors = [
823            /* #00 */ Address::p2pkh(&pk, None, &AddressParams::LIQUID),
824            /* #01 */ Address::p2pkh(&pk, None, &AddressParams::ELEMENTS),
825            /* #02 */ Address::p2pkh(&pk, Some(blinder), &AddressParams::LIQUID),
826            /* #03 */ Address::p2pkh(&pk, Some(blinder), &AddressParams::ELEMENTS),
827            /* #04 */ Address::p2sh(&script, None, &AddressParams::LIQUID),
828            /* #05 */ Address::p2sh(&script, None, &AddressParams::ELEMENTS),
829            /* #06 */ Address::p2sh(&script, Some(blinder), &AddressParams::LIQUID),
830            /* #07 */
831            Address::p2sh(&script, Some(blinder), &AddressParams::ELEMENTS),
832            /* #08 */ Address::p2wpkh(&pk, None, &AddressParams::LIQUID),
833            /* #09 */ Address::p2wpkh(&pk, None, &AddressParams::ELEMENTS),
834            /* #10 */ Address::p2wpkh(&pk, Some(blinder), &AddressParams::LIQUID),
835            /* #11 */ Address::p2wpkh(&pk, Some(blinder), &AddressParams::ELEMENTS),
836            /* #12 */ Address::p2shwpkh(&pk, None, &AddressParams::LIQUID),
837            /* #13 */ Address::p2shwpkh(&pk, None, &AddressParams::ELEMENTS),
838            /* #14 */ Address::p2shwpkh(&pk, Some(blinder), &AddressParams::LIQUID),
839            /* #15 */
840            Address::p2shwpkh(&pk, Some(blinder), &AddressParams::ELEMENTS),
841            /* #16 */ Address::p2wsh(&script, None, &AddressParams::LIQUID),
842            /* #17 */ Address::p2wsh(&script, None, &AddressParams::ELEMENTS),
843            /* #18 */ Address::p2wsh(&script, Some(blinder), &AddressParams::LIQUID),
844            /* #19 */
845            Address::p2wsh(&script, Some(blinder), &AddressParams::ELEMENTS),
846            /* #20 */ Address::p2shwsh(&script, None, &AddressParams::LIQUID),
847            /* #21 */ Address::p2shwsh(&script, None, &AddressParams::ELEMENTS),
848            /* #22 */
849            Address::p2shwsh(&script, Some(blinder), &AddressParams::LIQUID),
850            /* #23 */
851            Address::p2shwsh(&script, Some(blinder), &AddressParams::ELEMENTS),
852        ];
853
854        for addr in &vectors {
855            roundtrips(addr);
856        }
857    }
858
859    #[test]
860    fn test_actuals() {
861        // vectors: (address, blinded?, params)
862        let addresses = [
863            // Elements
864            ("2dxmEBXc2qMYcLSKiDBxdEePY3Ytixmnh4E", false, AddressParams::ELEMENTS),
865            ("CTEo6VKG8xbe7HnfVW9mQoWTgtgeRSPktwTLbELzGw5tV8Ngzu53EBiasFMQKVbWmKWWTAdN5AUf4M6Y", true, AddressParams::ELEMENTS),
866            ("ert1qwhh2n5qypypm0eufahm2pvj8raj9zq5c27cysu", false, AddressParams::ELEMENTS),
867            ("el1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsmxh4xcjh2rse", true, AddressParams::ELEMENTS),
868            // Liquid
869            ("GqiQRsPEyJLAsEBFB5R34KHuqxDNkG3zur", false, AddressParams::LIQUID),
870            ("VJLDwMVWXg8RKq4mRe3YFNTAEykVN6V8x5MRUKKoC3nfRnbpnZeiG3jygMC6A4Gw967GY5EotJ4Rau2F", true, AddressParams::LIQUID),
871            ("ex1q7gkeyjut0mrxc3j0kjlt7rmcnvsh0gt45d3fud", false, AddressParams::LIQUID),
872            ("lq1qqf8er278e6nyvuwtgf39e6ewvdcnjupn9a86rzpx655y5lhkt0walu3djf9cklkxd3ryld97hu8h3xepw7sh2rlu7q45dcew5", true, AddressParams::LIQUID),
873        ];
874
875        for &(a, blinded, ref params) in &addresses {
876            let result = a.parse();
877            assert!(
878                result.is_ok(),
879                "vector: {}, err: \"{}\"",
880                a,
881                result.unwrap_err()
882            );
883            let addr: Address = result.unwrap();
884            assert_eq!(a, &addr.to_string(), "vector: {}", a);
885            assert_eq!(blinded, addr.is_blinded());
886            assert_eq!(params, addr.params);
887            roundtrips(&addr);
888        }
889    }
890
891    #[test]
892    fn test_blech32_vectors() {
893        // taken from Elements test/functional/rpc_invalid_address_message.py
894        let address: Result<Address, _> = "el1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsmxh4xcjh2rse".parse();
895        assert!(address.is_ok());
896
897        let address: Result<Address, _> = "el1pq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsxguu9nrdg2pc".parse();
898        assert_eq!(
899            address.err().unwrap().to_string(),
900            "blech32 error: invalid checksum", // is valid blech32, but should be blech32m
901        );
902
903        let address: Result<Address, _> = "el1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsnnmzrstzt7de".parse();
904        assert_eq!(
905            address.err().unwrap().to_string(),
906            "blech32 error: invalid checksum", // is valid blech32m, but should be blech32
907        );
908
909        let address: Result<Address, _> =
910            "ert130xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqqu2tys".parse();
911        assert_eq!(
912            address.err().unwrap().to_string(),
913            "bech32 error: invalid segwit witness version: 17 (bech32 character: '3')",
914        );
915
916        let address: Result<Address, _> = "el1pq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpe9jfn0gypaj".parse();
917        assert_eq!(
918            address.err().unwrap().to_string(),
919            "blech32 error: invalid witness length",
920        );
921
922        // "invalid prefix" gives a weird error message because we do
923        // a dumb prefix check before even attempting bech32 decoding
924        let address: Result<Address, _> = "rrr1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfs2d9rp7meq4kg".parse();
925        assert_eq!(address.err().unwrap().to_string(), "base58 error: decode",);
926    }
927
928    #[test]
929    fn test_fixed_addresses() {
930        let pk = bitcoin::PublicKey::from_str(
931            "0212bf0ea45b733dfde8ecb5e896306c4165c666c99fc5d1ab887f71393a975cea",
932        )
933        .unwrap();
934        let script = Script::default();
935        let secp = Secp256k1::verification_only();
936        let internal_key = UntweakedPublicKey::from_str(
937            "93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51",
938        )
939        .unwrap();
940        let tap_node_hash = TapNodeHash::from_byte_array([0; 32]);
941
942        let mut expected = IntoIterator::into_iter([
943            "2dszRCFv8Ub4ytKo1Q1vXXGgSx7mekNDwSJ",
944            "XToMocNywBYNSiXUe5xvoa2naAps9Ek1hq",
945            "ert1qew0l0emv7449u7hqgc8utzdzryhse79yhq2sxv",
946            "XZF6k8S6eoVxXMB4NpWjh2s7LjQUP7pw2R",
947            "ert1quwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2szaqlpq",
948            "ert1p8qs0qcn25l2y6yvtc5t95rr8w9pndcj64c8rkutnvkcvdp6gh02q2cqvj9",
949            "ert1pxrrurkg8j8pve97lffvv2y67cf7ux478h077c87qacqzhue7390sqkjp06",
950            "CTEkC79sYAvWNcxd8iTYnYo226FqRBbzBcMppq7L2dA8jVXJWoo1kKWB3UBLY6gBjiXf87ibs8c6mQyZ",
951            "AzpjUhKMLJi9y2oLt3ZdM3BP9nHdLPJfGMVxRBaRc2gDpeNqPMVpShTszJW7bX42vT2KoejYy8GtbcxH",
952            "el1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4jul7lnkeat2teawq3s0cky6yxf0pnu2gmz9ej9kyq5yc",
953            "AzpjUhKMLJi9y2oLt3ZdM3BP9nHdLPJfGMVxRBaRc2gDpeNvq6SLVpBVwtakF6nmUFundyW7YjUdVkpr",
954            "el1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4casc3pf3lquzjd0haxgn9hmjfp84eq7geymjdx2f9verdu99wz4h79u87cnxdzq",
955            "el1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5wpq7p3x4f75f5gch3gktgxxwu2rxm394tsw8dchxedsc6r53w75cj24fq2u2ls5",
956            "el1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5vx8c8vs0ywzejta7jjcc5f4asnacdtu0wlaas0upmsq90enaz2lhjd0k0q7qn4h",
957            "QFq3vvrr6Ub2KAyb3LdoCxEQvKukB6nN9i",
958            "GydeMhecNgrq17WMkyyTM4ETv1YubMVtLN",
959            "ex1qew0l0emv7449u7hqgc8utzdzryhse79ydjqgek",
960            "H55PJDhj6JpR5k9wViXGEX4nga8WmhXtnD",
961            "ex1quwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2s4sla8h",
962            "ex1p8qs0qcn25l2y6yvtc5t95rr8w9pndcj64c8rkutnvkcvdp6gh02qa4lw5j",
963            "ex1pxrrurkg8j8pve97lffvv2y67cf7ux478h077c87qacqzhue7390shmdrfd",
964            "VTptY6cqJbusNpL5xvo8VL38nLX9PGDjfYQfqhu9EaA7FtuidkWyQzMHY9jzZrpBcCXT437vM6V4N8kh",
965            "VJL64Ep3rcngP4cScRme15q9i8MCNiuqWeiG3YbtduUidVyorg7nRsgmmF714QtH3sNpWB2CqsVVciQh",
966            "lq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4jul7lnkeat2teawq3s0cky6yxf0pnu2gs2923tg58xcz",
967            "VJL64Ep3rcngP4cScRme15q9i8MCNiuqWeiG3YbtduUidVyuJR4JUzQPiqBdhzd1bgGHLVnmRUjfHc68",
968            "lq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4casc3pf3lquzjd0haxgn9hmjfp84eq7geymjdx2f9verdu99wz47jmkmgmr9a4s",
969            "lq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5wpq7p3x4f75f5gch3gktgxxwu2rxm394tsw8dchxedsc6r53w75375l4kfvf08y",
970            "lq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5vx8c8vs0ywzejta7jjcc5f4asnacdtu0wlaas0upmsq90enaz2l77n92erwrrz8",
971            "FojPFeboBgrd953mXXe72KWthjVwHWozqN",
972            "8vsafXgrB5bJeSidGbK5eYnjKvQ3RiB4BB",
973            "tex1qew0l0emv7449u7hqgc8utzdzryhse79yh5jp9a",
974            "92KKc3jxthYtj5ND1KrtY1d46UyeWV6XbP",
975            "tex1quwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2s5fd6kc",
976            "tex1p8qs0qcn25l2y6yvtc5t95rr8w9pndcj64c8rkutnvkcvdp6gh02quvdf9a",
977            "tex1pxrrurkg8j8pve97lffvv2y67cf7ux478h077c87qacqzhue7390skzlycz",
978            "vtS71VhcpFt978sha5d1L2gCzp3UL5kXacRpb3N4GTW5MwvBzz5HwxYyB8Pns4yM2dd2osmQkHSkp88u",
979            "vjTuLJ76nGi8PUopBVmGK8bLKPfBpaBWf6wKfn8z9Vdz6ubVhpvmMr6TK2RcqAYiujN1g1uwg8kejrM3",
980            "tlq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4jul7lnkeat2teawq3s0cky6yxf0pnu2gq8g2kuxfj8ft",
981            "vjTuLJ76nGi8PUopBVmGK8bLKPfBpaBWf6wKfn8z9Vdz6ubb9ZsHQxp5GcWFUkHTTYFUWLgWFk1DN5Fe",
982            "tlq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4casc3pf3lquzjd0haxgn9hmjfp84eq7geymjdx2f9verdu99wz4e6vcdfcyp5m8",
983            "tlq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5wpq7p3x4f75f5gch3gktgxxwu2rxm394tsw8dchxedsc6r53w75kkr3rh2tdxfn",
984            "tlq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5vx8c8vs0ywzejta7jjcc5f4asnacdtu0wlaas0upmsq90enaz2lekytucqf82vs",
985        ]);
986
987        for params in [
988            &AddressParams::ELEMENTS,
989            &AddressParams::LIQUID,
990            &AddressParams::LIQUID_TESTNET,
991        ] {
992            for blinder in [None, Some(pk.inner)] {
993                let addr = Address::p2pkh(&pk, blinder, params);
994                assert_eq!(&addr.to_string(), expected.next().unwrap());
995
996                let addr = Address::p2sh(&script, blinder, params);
997                assert_eq!(&addr.to_string(), expected.next().unwrap());
998
999                let addr = Address::p2wpkh(&pk, blinder, params);
1000                assert_eq!(&addr.to_string(), expected.next().unwrap());
1001
1002                let addr = Address::p2shwpkh(&pk, blinder, params);
1003                assert_eq!(&addr.to_string(), expected.next().unwrap());
1004
1005                let addr = Address::p2wsh(&script, blinder, params);
1006                assert_eq!(&addr.to_string(), expected.next().unwrap());
1007
1008                let addr = Address::p2tr(&secp, internal_key, None, blinder, params);
1009                assert_eq!(&addr.to_string(), expected.next().unwrap());
1010
1011                let addr = Address::p2tr(&secp, internal_key, Some(tap_node_hash), blinder, params);
1012                assert_eq!(&addr.to_string(), expected.next().unwrap());
1013            }
1014        }
1015    }
1016}