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 _;
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 crate::hashes::Hash;
27use bitcoin::base58;
28use bitcoin::PublicKey;
29use crate::internals::array::ArrayExt as _;
30use crate::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, WPubkeyHash, 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        let mut hash_engine = PubkeyHash::engine();
242        pk.write_into(&mut hash_engine)
243            .expect("engines don't error");
244
245        Address {
246            params,
247            payload: Payload::PubkeyHash(PubkeyHash::from_engine(hash_engine)),
248            blinding_pubkey: blinder,
249        }
250    }
251
252    /// Creates a pay to script hash P2SH address from a script
253    /// This address type was introduced with BIP16 and is the popular type to implement multi-sig these days.
254    #[inline]
255    pub fn p2sh(
256        script: &script::Script,
257        blinder: Option<secp256k1_zkp::PublicKey>,
258        params: &'static AddressParams,
259    ) -> Address {
260        Address {
261            params,
262            payload: Payload::ScriptHash(ScriptHash::hash(&script[..])),
263            blinding_pubkey: blinder,
264        }
265    }
266
267    /// Create a witness pay to public key address from a public key
268    /// This is the native segwit address type for an output redeemable with a single signature
269    pub fn p2wpkh(
270        pk: &PublicKey,
271        blinder: Option<secp256k1_zkp::PublicKey>,
272        params: &'static AddressParams,
273    ) -> Address {
274        let mut hash_engine = WPubkeyHash::engine();
275        pk.write_into(&mut hash_engine)
276            .expect("engines don't error");
277
278        Address {
279            params,
280            payload: Payload::WitnessProgram {
281                version: Fe32::Q,
282                program: WPubkeyHash::from_engine(hash_engine)[..].to_vec(),
283            },
284            blinding_pubkey: blinder,
285        }
286    }
287
288    /// Create a pay to script address that embeds a witness pay to public key
289    /// This is a segwit address type that looks familiar (as p2sh) to legacy clients
290    pub fn p2shwpkh(
291        pk: &PublicKey,
292        blinder: Option<secp256k1_zkp::PublicKey>,
293        params: &'static AddressParams,
294    ) -> Address {
295        let mut hash_engine = ScriptHash::engine();
296        pk.write_into(&mut hash_engine)
297            .expect("engines don't error");
298
299        let builder = script::Builder::new()
300            .push_int(0)
301            .push_slice(&ScriptHash::from_engine(hash_engine)[..]);
302
303        Address {
304            params,
305            payload: Payload::ScriptHash(ScriptHash::hash(builder.into_script().as_bytes())),
306            blinding_pubkey: blinder,
307        }
308    }
309
310    /// Create a witness pay to script hash address
311    pub fn p2wsh(
312        script: &script::Script,
313        blinder: Option<secp256k1_zkp::PublicKey>,
314        params: &'static AddressParams,
315    ) -> Address {
316        Address {
317            params,
318            payload: Payload::WitnessProgram {
319                version: Fe32::Q,
320                program: WScriptHash::hash(&script[..])[..].to_vec(),
321            },
322            blinding_pubkey: blinder,
323        }
324    }
325
326    /// Create a pay to script address that embeds a witness pay to script hash address
327    /// This is a segwit address type that looks familiar (as p2sh) to legacy clients
328    pub fn p2shwsh(
329        script: &script::Script,
330        blinder: Option<secp256k1_zkp::PublicKey>,
331        params: &'static AddressParams,
332    ) -> Address {
333        let ws = script::Builder::new()
334            .push_int(0)
335            .push_slice(&WScriptHash::hash(&script[..])[..])
336            .into_script();
337
338        Address {
339            params,
340            payload: Payload::ScriptHash(ScriptHash::hash(&ws[..])),
341            blinding_pubkey: blinder,
342        }
343    }
344
345    /// Creates a pay to taproot address from an untweaked key.
346    pub fn p2tr<C: Verification>(
347        secp: &Secp256k1<C>,
348        internal_key: UntweakedPublicKey,
349        merkle_root: Option<TapNodeHash>,
350        blinder: Option<secp256k1_zkp::PublicKey>,
351        params: &'static AddressParams,
352    ) -> Address {
353        Address {
354            params,
355            payload: {
356                let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root);
357                Payload::WitnessProgram {
358                    version: Fe32::P,
359                    program: output_key.into_inner().serialize().to_vec(),
360                }
361            },
362            blinding_pubkey: blinder,
363        }
364    }
365
366    /// Creates a pay to taproot address from a pre-tweaked output key.
367    ///
368    /// This method is not recommended for use, [`Address::p2tr()`] should be used where possible.
369    pub fn p2tr_tweaked(
370        output_key: TweakedPublicKey,
371        blinder: Option<secp256k1_zkp::PublicKey>,
372        params: &'static AddressParams,
373    ) -> Address {
374        Address {
375            params,
376            payload: Payload::WitnessProgram {
377                version: Fe32::P,
378                program: output_key.into_inner().serialize().to_vec(),
379            },
380            blinding_pubkey: blinder,
381        }
382    }
383
384    /// Get an [Address] from an output script.
385    pub fn from_script(
386        script: &script::Script,
387        blinder: Option<secp256k1_zkp::PublicKey>,
388        params: &'static AddressParams,
389    ) -> Option<Address> {
390        Some(Address {
391            payload: if script.is_p2pkh() {
392                Payload::PubkeyHash(Hash::from_slice(&script.as_bytes()[3..23]).unwrap())
393            } else if script.is_p2sh() {
394                Payload::ScriptHash(Hash::from_slice(&script.as_bytes()[2..22]).unwrap())
395            } else if script.is_v0_p2wpkh() {
396                Payload::WitnessProgram {
397                    version: Fe32::Q,
398                    program: script.as_bytes()[2..22].to_vec(),
399                }
400            } else if script.is_v0_p2wsh() {
401                Payload::WitnessProgram {
402                    version: Fe32::Q,
403                    program: script.as_bytes()[2..34].to_vec(),
404                }
405            } else if script.is_v1plus_p2witprog() {
406                Payload::WitnessProgram {
407                    version: Fe32::try_from(script.as_bytes()[0] - 0x50).expect("0<32"),
408                    program: script.as_bytes()[2..].to_vec(),
409                }
410            } else {
411                return None;
412            },
413            blinding_pubkey: blinder,
414            params,
415        })
416    }
417
418    /// Generates a script pubkey spending to this address
419    pub fn script_pubkey(&self) -> script::Script {
420        match self.payload {
421            Payload::PubkeyHash(ref hash) => script::Builder::new()
422                .push_opcode(opcodes::all::OP_DUP)
423                .push_opcode(opcodes::all::OP_HASH160)
424                .push_slice(&hash[..])
425                .push_opcode(opcodes::all::OP_EQUALVERIFY)
426                .push_opcode(opcodes::all::OP_CHECKSIG),
427            Payload::ScriptHash(ref hash) => script::Builder::new()
428                .push_opcode(opcodes::all::OP_HASH160)
429                .push_slice(&hash[..])
430                .push_opcode(opcodes::all::OP_EQUAL),
431            Payload::WitnessProgram {
432                version: witver,
433                program: ref witprog,
434            } => script::Builder::new()
435                .push_int(i64::from(witver.to_u8()))
436                .push_slice(witprog),
437        }
438        .into_script()
439    }
440
441    /// Convert this address to an unconfidential address.
442    #[must_use]
443    pub fn to_unconfidential(&self) -> Address {
444        Address {
445            params: self.params,
446            payload: self.payload.clone(),
447            blinding_pubkey: None,
448        }
449    }
450
451    /// Convert this address to a confidential address with the given blinding pubkey.
452    #[must_use]
453    pub fn to_confidential(&self, blinding_pubkey: secp256k1_zkp::PublicKey) -> Address {
454        Address {
455            params: self.params,
456            payload: self.payload.clone(),
457            blinding_pubkey: Some(blinding_pubkey),
458        }
459    }
460
461    fn from_bech32(
462        s: &str,
463        blinded: bool,
464        params: &'static AddressParams,
465    ) -> Result<Address, AddressError> {
466        let (version, data): (Fe32, Vec<u8>) = if blinded {
467            let hs = crate::blech32::decode::SegwitHrpstring::new(s)?;
468            (hs.witness_version(), hs.byte_iter().collect())
469        } else {
470            let hs = bech32::primitives::decode::SegwitHrpstring::new(s)?;
471            (hs.witness_version(), hs.byte_iter().collect())
472        };
473
474        let (blinding_pubkey, program) = match blinded {
475            true => {
476                let (pk, rest) = SliceExt::split_first_chunk::<33>(data.as_slice())
477                    .ok_or(AddressError::InvalidSegwitV0Encoding)?;
478                (
479                Some(
480                    secp256k1_zkp::PublicKey::from_slice(pk)
481                        .map_err(AddressError::InvalidBlindingPubKey)?,
482                    ),
483                    rest.to_vec(),
484                )
485            },
486            false => (None, data),
487        };
488
489        Ok(Address {
490            params,
491            payload: Payload::WitnessProgram { version, program },
492            blinding_pubkey,
493        })
494    }
495
496    // data.len() should be >= 1 when this method is called
497    fn from_base58(data: &[u8], params: &'static AddressParams) -> Result<Address, AddressError> {
498        let len_error = AddressError::InvalidLength(data.len());
499        // When unblinded, the structure is:
500        // <1: regular prefix> <20: hash160>
501        // When blinded, the structure is:
502        // <1: blinding prefix> <1: regular prefix> <33: blinding pubkey> <20: hash160>
503
504        let (blinding_prefix, blinded_data) = match data.split_first() {
505            Some(v) => v,
506            None => return Err(len_error),
507        };
508
509        let (prefix, blinding_pubkey, hash) = if *blinding_prefix == params.blinded_prefix {
510            let (prefix, pubkey_and_hash) = match blinded_data.split_first() {
511                Some(v) => v,
512                None => return Err(len_error),
513            };
514
515            let pubkey_and_hash = <&[u8; 53]>::try_from(pubkey_and_hash).map_err(|_| len_error)?;
516            let (pubkey, hash) = pubkey_and_hash.split_array::<33, 20>();
517
518            let blinding_pubkey = secp256k1_zkp::PublicKey::from_slice(pubkey)
519                .map_err(AddressError::InvalidBlindingPubKey)?;
520
521            (prefix, Some(blinding_pubkey), hash)
522        } else {
523            let hash = <&[u8; 20]>::try_from(blinded_data).map_err(|_| len_error)?;
524            (blinding_prefix, None, hash)
525        };
526
527        let payload = if *prefix == params.p2pkh_prefix {
528            Payload::PubkeyHash(PubkeyHash::from_byte_array(*hash))
529        } else if *prefix == params.p2sh_prefix {
530            Payload::ScriptHash(ScriptHash::from_byte_array(*hash))
531        } else {
532            return Err(AddressError::InvalidAddressVersion(*prefix));
533        };
534
535        Ok(Address {
536            params,
537            payload,
538            blinding_pubkey,
539        })
540    }
541
542    /// Parse the address using the given parameters.
543    /// When using the built-in parameters, you can use [`FromStr`].
544    pub fn parse_with_params(
545        s: &str,
546        params: &'static AddressParams,
547    ) -> Result<Address, AddressError> {
548        // Bech32.
549        let prefix = find_prefix(s);
550        let b32_ex = match_prefix(prefix, params.bech_hrp);
551        let b32_bl = match_prefix(prefix, params.blech_hrp);
552        if b32_ex || b32_bl {
553            return Address::from_bech32(s, b32_bl, params);
554        }
555
556        // Base58.
557        if s.len() > 150 {
558            return Err(AddressError::InvalidLength(s.len() * 11 / 15));
559        }
560        let data = base58::decode_check(s)?;
561        Address::from_base58(&data, params)
562    }
563}
564
565impl fmt::Display for Address {
566    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
567        match self.payload {
568            Payload::PubkeyHash(ref hash) => {
569                if let Some(ref blinder) = self.blinding_pubkey {
570                    let mut prefixed = [0; 55]; // 1 + 1 + 33 + 20
571                    prefixed[0] = self.params.blinded_prefix;
572                    prefixed[1] = self.params.p2pkh_prefix;
573                    prefixed[2..35].copy_from_slice(&blinder.serialize());
574                    prefixed[35..].copy_from_slice(&hash[..]);
575                    base58::encode_check_to_fmt(fmt, &prefixed[..])
576                } else {
577                    let mut prefixed = [0; 21];
578                    prefixed[0] = self.params.p2pkh_prefix;
579                    prefixed[1..].copy_from_slice(&hash[..]);
580                    base58::encode_check_to_fmt(fmt, &prefixed[..])
581                }
582            }
583            Payload::ScriptHash(ref hash) => {
584                if let Some(ref blinder) = self.blinding_pubkey {
585                    let mut prefixed = [0; 55]; // 1 + 1 + 33 + 20
586                    prefixed[0] = self.params.blinded_prefix;
587                    prefixed[1] = self.params.p2sh_prefix;
588                    prefixed[2..35].copy_from_slice(&blinder.serialize());
589                    prefixed[35..].copy_from_slice(&hash[..]);
590                    base58::encode_check_to_fmt(fmt, &prefixed[..])
591                } else {
592                    let mut prefixed = [0; 21];
593                    prefixed[0] = self.params.p2sh_prefix;
594                    prefixed[1..].copy_from_slice(&hash[..]);
595                    base58::encode_check_to_fmt(fmt, &prefixed[..])
596                }
597            }
598            Payload::WitnessProgram {
599                version: witver,
600                program: ref witprog,
601            } => {
602                let hrp = match self.blinding_pubkey.is_some() {
603                    true => self.params.blech_hrp,
604                    false => self.params.bech_hrp,
605                };
606
607                // FIXME: surely we can fix this logic to not be so repetitive.
608                if self.is_blinded() {
609                    if let Some(ref blinder) = self.blinding_pubkey {
610                        let byte_iter = IntoIterator::into_iter(blinder.serialize())
611                            .chain(witprog.iter().copied());
612                        let fe_iter = byte_iter.bytes_to_fes();
613                        if witver.to_u8() == 0 {
614                            for c in fe_iter
615                                .with_checksum::<Blech32>(&hrp)
616                                .with_witness_version(witver)
617                                .chars()
618                            {
619                                fmt.write_char(c)?;
620                            }
621                        } else {
622                            for c in fe_iter
623                                .with_checksum::<Blech32m>(&hrp)
624                                .with_witness_version(witver)
625                                .chars()
626                            {
627                                fmt.write_char(c)?;
628                            }
629                        }
630                        return Ok(());
631                    }
632                }
633
634                let byte_iter = witprog.iter().copied();
635                let fe_iter = byte_iter.bytes_to_fes();
636                if witver.to_u8() == 0 {
637                    for c in fe_iter
638                        .with_checksum::<Bech32>(&hrp)
639                        .with_witness_version(witver)
640                        .chars()
641                    {
642                        fmt.write_char(c)?;
643                    }
644                } else {
645                    for c in fe_iter
646                        .with_checksum::<Bech32m>(&hrp)
647                        .with_witness_version(witver)
648                        .chars()
649                    {
650                        fmt.write_char(c)?;
651                    }
652                }
653                Ok(())
654            }
655        }
656    }
657}
658
659impl fmt::Debug for Address {
660    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
661        fmt::Display::fmt(self, fmt)
662    }
663}
664
665/// Extract the bech32 prefix.
666/// Returns the same slice when no prefix is found.
667fn find_prefix(bech32: &str) -> &str {
668    // Split at the last occurrence of the separator character '1'.
669    match bech32.rfind('1') {
670        None => bech32,
671        Some(sep) => bech32.split_at(sep).0,
672    }
673}
674
675/// Checks if both prefixes match, regardless of case.
676/// The first prefix can be mixed case, but the second one is expected in
677/// lower case.
678fn match_prefix(prefix_mixed: &str, target: Hrp) -> bool {
679    target.len() == prefix_mixed.len() && target
680        .lowercase_char_iter()
681        .zip(prefix_mixed.chars())
682        .all(|(char_lower, char_mixed)| char_lower == char_mixed.to_ascii_lowercase())
683}
684
685impl FromStr for Address {
686    type Err = AddressError;
687
688    fn from_str(s: &str) -> Result<Address, AddressError> {
689        // shorthands
690        let liq = &AddressParams::LIQUID;
691        let ele = &AddressParams::ELEMENTS;
692        let liq_test = &AddressParams::LIQUID_TESTNET;
693
694        let net_arr = [liq, ele, liq_test];
695
696        let prefix = find_prefix(s);
697        for net in &net_arr {
698            // Bech32.
699            if match_prefix(prefix, net.bech_hrp) {
700                return Address::from_bech32(s, false, net);
701            }
702            if match_prefix(prefix, net.blech_hrp) {
703                return Address::from_bech32(s, true, net);
704            }
705        }
706
707        // Base58.
708        if s.len() > 150 {
709            return Err(AddressError::InvalidLength(s.len() * 11 / 15));
710        }
711        let data = base58::decode_check(s)?;
712        if data.is_empty() {
713            return Err(AddressError::InvalidLength(data.len()));
714        }
715
716        let p = data[0];
717        for net in &net_arr {
718            if p == net.p2pkh_prefix || p == net.p2sh_prefix || p == net.blinded_prefix {
719                return Address::from_base58(&data, net);
720            }
721        }
722
723        Err(AddressError::InvalidAddress(s.to_owned()))
724    }
725}
726
727#[cfg(feature = "serde")]
728impl<'de> serde::Deserialize<'de> for Address {
729    #[inline]
730    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
731    where
732        D: serde::Deserializer<'de>,
733    {
734        use std::fmt::Formatter;
735
736        struct Visitor;
737        impl<'de> serde::de::Visitor<'de> for Visitor {
738            type Value = Address;
739
740            fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
741                formatter.write_str("a Bitcoin address")
742            }
743
744            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
745            where
746                E: serde::de::Error,
747            {
748                Address::from_str(v).map_err(E::custom)
749            }
750
751            fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
752            where
753                E: serde::de::Error,
754            {
755                self.visit_str(v)
756            }
757
758            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
759            where
760                E: serde::de::Error,
761            {
762                self.visit_str(&v)
763            }
764        }
765
766        deserializer.deserialize_str(Visitor)
767    }
768}
769
770#[cfg(feature = "serde")]
771impl serde::Serialize for Address {
772    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
773    where
774        S: serde::Serializer,
775    {
776        serializer.serialize_str(&self.to_string())
777    }
778}
779
780#[cfg(test)]
781mod test {
782    use super::*;
783    use crate::Script;
784    use bitcoin::key;
785    use secp256k1_zkp::{PublicKey, Secp256k1};
786    #[cfg(feature = "serde")]
787    use serde_json;
788
789    fn roundtrips(addr: &Address) {
790        assert_eq!(
791            Address::from_str(&addr.to_string()).ok().as_ref(),
792            Some(addr),
793            "string round-trip failed for {}",
794            addr,
795        );
796        assert_eq!(
797            Address::from_script(&addr.script_pubkey(), addr.blinding_pubkey, addr.params).as_ref(),
798            Some(addr),
799            "script round-trip failed for {}",
800            addr,
801        );
802        #[cfg(feature = "serde")]
803        assert_eq!(
804            serde_json::from_value::<Address>(serde_json::to_value(addr).unwrap())
805                .ok()
806                .as_ref(),
807            Some(addr)
808        );
809    }
810
811    #[test]
812    fn regression_188() {
813        // Tests that the `tlq` prefix was not accidentally changed, e.g. to `tlg` :).
814        let addr = Address::from_str("tlq1qq2xvpcvfup5j8zscjq05u2wxxjcyewk7979f3mmz5l7uw5pqmx6xf5xy50hsn6vhkm5euwt72x878eq6zxx2z58hd7zrsg9qn").unwrap();
815        roundtrips(&addr);
816    }
817
818    #[test]
819    fn exhaustive() {
820        let blinder_hex = "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
821        let blinder = PublicKey::from_str(blinder_hex).unwrap();
822        let sk_wif = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy";
823        let sk = key::PrivateKey::from_wif(sk_wif).unwrap();
824        let pk = sk.public_key(&Secp256k1::new());
825        let script: Script = vec![1u8, 2, 42, 255, 196].into();
826
827        let vectors = [
828            /* #00 */ Address::p2pkh(&pk, None, &AddressParams::LIQUID),
829            /* #01 */ Address::p2pkh(&pk, None, &AddressParams::ELEMENTS),
830            /* #02 */ Address::p2pkh(&pk, Some(blinder), &AddressParams::LIQUID),
831            /* #03 */ Address::p2pkh(&pk, Some(blinder), &AddressParams::ELEMENTS),
832            /* #04 */ Address::p2sh(&script, None, &AddressParams::LIQUID),
833            /* #05 */ Address::p2sh(&script, None, &AddressParams::ELEMENTS),
834            /* #06 */ Address::p2sh(&script, Some(blinder), &AddressParams::LIQUID),
835            /* #07 */
836            Address::p2sh(&script, Some(blinder), &AddressParams::ELEMENTS),
837            /* #08 */ Address::p2wpkh(&pk, None, &AddressParams::LIQUID),
838            /* #09 */ Address::p2wpkh(&pk, None, &AddressParams::ELEMENTS),
839            /* #10 */ Address::p2wpkh(&pk, Some(blinder), &AddressParams::LIQUID),
840            /* #11 */ Address::p2wpkh(&pk, Some(blinder), &AddressParams::ELEMENTS),
841            /* #12 */ Address::p2shwpkh(&pk, None, &AddressParams::LIQUID),
842            /* #13 */ Address::p2shwpkh(&pk, None, &AddressParams::ELEMENTS),
843            /* #14 */ Address::p2shwpkh(&pk, Some(blinder), &AddressParams::LIQUID),
844            /* #15 */
845            Address::p2shwpkh(&pk, Some(blinder), &AddressParams::ELEMENTS),
846            /* #16 */ Address::p2wsh(&script, None, &AddressParams::LIQUID),
847            /* #17 */ Address::p2wsh(&script, None, &AddressParams::ELEMENTS),
848            /* #18 */ Address::p2wsh(&script, Some(blinder), &AddressParams::LIQUID),
849            /* #19 */
850            Address::p2wsh(&script, Some(blinder), &AddressParams::ELEMENTS),
851            /* #20 */ Address::p2shwsh(&script, None, &AddressParams::LIQUID),
852            /* #21 */ Address::p2shwsh(&script, None, &AddressParams::ELEMENTS),
853            /* #22 */
854            Address::p2shwsh(&script, Some(blinder), &AddressParams::LIQUID),
855            /* #23 */
856            Address::p2shwsh(&script, Some(blinder), &AddressParams::ELEMENTS),
857        ];
858
859        for addr in &vectors {
860            roundtrips(addr);
861        }
862    }
863
864    #[test]
865    fn test_actuals() {
866        // vectors: (address, blinded?, params)
867        let addresses = [
868            // Elements
869            ("2dxmEBXc2qMYcLSKiDBxdEePY3Ytixmnh4E", false, AddressParams::ELEMENTS),
870            ("CTEo6VKG8xbe7HnfVW9mQoWTgtgeRSPktwTLbELzGw5tV8Ngzu53EBiasFMQKVbWmKWWTAdN5AUf4M6Y", true, AddressParams::ELEMENTS),
871            ("ert1qwhh2n5qypypm0eufahm2pvj8raj9zq5c27cysu", false, AddressParams::ELEMENTS),
872            ("el1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsmxh4xcjh2rse", true, AddressParams::ELEMENTS),
873            // Liquid
874            ("GqiQRsPEyJLAsEBFB5R34KHuqxDNkG3zur", false, AddressParams::LIQUID),
875            ("VJLDwMVWXg8RKq4mRe3YFNTAEykVN6V8x5MRUKKoC3nfRnbpnZeiG3jygMC6A4Gw967GY5EotJ4Rau2F", true, AddressParams::LIQUID),
876            ("ex1q7gkeyjut0mrxc3j0kjlt7rmcnvsh0gt45d3fud", false, AddressParams::LIQUID),
877            ("lq1qqf8er278e6nyvuwtgf39e6ewvdcnjupn9a86rzpx655y5lhkt0walu3djf9cklkxd3ryld97hu8h3xepw7sh2rlu7q45dcew5", true, AddressParams::LIQUID),
878        ];
879
880        for &(a, blinded, ref params) in &addresses {
881            let result = a.parse();
882            assert!(
883                result.is_ok(),
884                "vector: {}, err: \"{}\"",
885                a,
886                result.unwrap_err()
887            );
888            let addr: Address = result.unwrap();
889            assert_eq!(a, &addr.to_string(), "vector: {}", a);
890            assert_eq!(blinded, addr.is_blinded());
891            assert_eq!(params, addr.params);
892            roundtrips(&addr);
893        }
894    }
895
896    #[test]
897    fn test_blech32_vectors() {
898        // taken from Elements test/functional/rpc_invalid_address_message.py
899        let address: Result<Address, _> = "el1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsmxh4xcjh2rse".parse();
900        assert!(address.is_ok());
901
902        let address: Result<Address, _> = "el1pq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsxguu9nrdg2pc".parse();
903        assert_eq!(
904            address.err().unwrap().to_string(),
905            "blech32 error: invalid checksum", // is valid blech32, but should be blech32m
906        );
907
908        let address: Result<Address, _> = "el1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsnnmzrstzt7de".parse();
909        assert_eq!(
910            address.err().unwrap().to_string(),
911            "blech32 error: invalid checksum", // is valid blech32m, but should be blech32
912        );
913
914        let address: Result<Address, _> =
915            "ert130xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqqu2tys".parse();
916        assert_eq!(
917            address.err().unwrap().to_string(),
918            "bech32 error: invalid segwit witness version: 17 (bech32 character: '3')",
919        );
920
921        let address: Result<Address, _> = "el1pq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpe9jfn0gypaj".parse();
922        assert_eq!(
923            address.err().unwrap().to_string(),
924            "blech32 error: invalid witness length",
925        );
926
927        // "invalid prefix" gives a weird error message because we do
928        // a dumb prefix check before even attempting bech32 decoding
929        let address: Result<Address, _> = "rrr1qq0umk3pez693jrrlxz9ndlkuwne93gdu9g83mhhzuyf46e3mdzfpva0w48gqgzgrklncnm0k5zeyw8my2ypfs2d9rp7meq4kg".parse();
930        assert_eq!(address.err().unwrap().to_string(), "base58 error: decode",);
931    }
932
933    #[test]
934    fn test_fixed_addresses() {
935        let pk = bitcoin::PublicKey::from_str(
936            "0212bf0ea45b733dfde8ecb5e896306c4165c666c99fc5d1ab887f71393a975cea",
937        )
938        .unwrap();
939        let script = Script::default();
940        let secp = Secp256k1::verification_only();
941        let internal_key = UntweakedPublicKey::from_str(
942            "93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51",
943        )
944        .unwrap();
945        let tap_node_hash = TapNodeHash::all_zeros();
946
947        let mut expected = IntoIterator::into_iter([
948            "2dszRCFv8Ub4ytKo1Q1vXXGgSx7mekNDwSJ",
949            "XToMocNywBYNSiXUe5xvoa2naAps9Ek1hq",
950            "ert1qew0l0emv7449u7hqgc8utzdzryhse79yhq2sxv",
951            "XZF6k8S6eoVxXMB4NpWjh2s7LjQUP7pw2R",
952            "ert1quwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2szaqlpq",
953            "ert1p8qs0qcn25l2y6yvtc5t95rr8w9pndcj64c8rkutnvkcvdp6gh02q2cqvj9",
954            "ert1pxrrurkg8j8pve97lffvv2y67cf7ux478h077c87qacqzhue7390sqkjp06",
955            "CTEkC79sYAvWNcxd8iTYnYo226FqRBbzBcMppq7L2dA8jVXJWoo1kKWB3UBLY6gBjiXf87ibs8c6mQyZ",
956            "AzpjUhKMLJi9y2oLt3ZdM3BP9nHdLPJfGMVxRBaRc2gDpeNqPMVpShTszJW7bX42vT2KoejYy8GtbcxH",
957            "el1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4jul7lnkeat2teawq3s0cky6yxf0pnu2gmz9ej9kyq5yc",
958            "AzpjUhKMLJi9y2oLt3ZdM3BP9nHdLPJfGMVxRBaRc2gDpeNvq6SLVpBVwtakF6nmUFundyW7YjUdVkpr",
959            "el1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4casc3pf3lquzjd0haxgn9hmjfp84eq7geymjdx2f9verdu99wz4h79u87cnxdzq",
960            "el1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5wpq7p3x4f75f5gch3gktgxxwu2rxm394tsw8dchxedsc6r53w75cj24fq2u2ls5",
961            "el1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5vx8c8vs0ywzejta7jjcc5f4asnacdtu0wlaas0upmsq90enaz2lhjd0k0q7qn4h",
962            "QFq3vvrr6Ub2KAyb3LdoCxEQvKukB6nN9i",
963            "GydeMhecNgrq17WMkyyTM4ETv1YubMVtLN",
964            "ex1qew0l0emv7449u7hqgc8utzdzryhse79ydjqgek",
965            "H55PJDhj6JpR5k9wViXGEX4nga8WmhXtnD",
966            "ex1quwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2s4sla8h",
967            "ex1p8qs0qcn25l2y6yvtc5t95rr8w9pndcj64c8rkutnvkcvdp6gh02qa4lw5j",
968            "ex1pxrrurkg8j8pve97lffvv2y67cf7ux478h077c87qacqzhue7390shmdrfd",
969            "VTptY6cqJbusNpL5xvo8VL38nLX9PGDjfYQfqhu9EaA7FtuidkWyQzMHY9jzZrpBcCXT437vM6V4N8kh",
970            "VJL64Ep3rcngP4cScRme15q9i8MCNiuqWeiG3YbtduUidVyorg7nRsgmmF714QtH3sNpWB2CqsVVciQh",
971            "lq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4jul7lnkeat2teawq3s0cky6yxf0pnu2gs2923tg58xcz",
972            "VJL64Ep3rcngP4cScRme15q9i8MCNiuqWeiG3YbtduUidVyuJR4JUzQPiqBdhzd1bgGHLVnmRUjfHc68",
973            "lq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4casc3pf3lquzjd0haxgn9hmjfp84eq7geymjdx2f9verdu99wz47jmkmgmr9a4s",
974            "lq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5wpq7p3x4f75f5gch3gktgxxwu2rxm394tsw8dchxedsc6r53w75375l4kfvf08y",
975            "lq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5vx8c8vs0ywzejta7jjcc5f4asnacdtu0wlaas0upmsq90enaz2l77n92erwrrz8",
976            "FojPFeboBgrd953mXXe72KWthjVwHWozqN",
977            "8vsafXgrB5bJeSidGbK5eYnjKvQ3RiB4BB",
978            "tex1qew0l0emv7449u7hqgc8utzdzryhse79yh5jp9a",
979            "92KKc3jxthYtj5ND1KrtY1d46UyeWV6XbP",
980            "tex1quwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2s5fd6kc",
981            "tex1p8qs0qcn25l2y6yvtc5t95rr8w9pndcj64c8rkutnvkcvdp6gh02quvdf9a",
982            "tex1pxrrurkg8j8pve97lffvv2y67cf7ux478h077c87qacqzhue7390skzlycz",
983            "vtS71VhcpFt978sha5d1L2gCzp3UL5kXacRpb3N4GTW5MwvBzz5HwxYyB8Pns4yM2dd2osmQkHSkp88u",
984            "vjTuLJ76nGi8PUopBVmGK8bLKPfBpaBWf6wKfn8z9Vdz6ubVhpvmMr6TK2RcqAYiujN1g1uwg8kejrM3",
985            "tlq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4jul7lnkeat2teawq3s0cky6yxf0pnu2gq8g2kuxfj8ft",
986            "vjTuLJ76nGi8PUopBVmGK8bLKPfBpaBWf6wKfn8z9Vdz6ubb9ZsHQxp5GcWFUkHTTYFUWLgWFk1DN5Fe",
987            "tlq1qqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww4casc3pf3lquzjd0haxgn9hmjfp84eq7geymjdx2f9verdu99wz4e6vcdfcyp5m8",
988            "tlq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5wpq7p3x4f75f5gch3gktgxxwu2rxm394tsw8dchxedsc6r53w75kkr3rh2tdxfn",
989            "tlq1pqgft7r4ytdenml0gaj67393sd3qkt3nxex0ut5dt3plhzwf6jaww5vx8c8vs0ywzejta7jjcc5f4asnacdtu0wlaas0upmsq90enaz2lekytucqf82vs",
990        ]);
991
992        for params in [
993            &AddressParams::ELEMENTS,
994            &AddressParams::LIQUID,
995            &AddressParams::LIQUID_TESTNET,
996        ] {
997            for blinder in [None, Some(pk.inner)] {
998                let addr = Address::p2pkh(&pk, blinder, params);
999                assert_eq!(&addr.to_string(), expected.next().unwrap());
1000
1001                let addr = Address::p2sh(&script, blinder, params);
1002                assert_eq!(&addr.to_string(), expected.next().unwrap());
1003
1004                let addr = Address::p2wpkh(&pk, blinder, params);
1005                assert_eq!(&addr.to_string(), expected.next().unwrap());
1006
1007                let addr = Address::p2shwpkh(&pk, blinder, params);
1008                assert_eq!(&addr.to_string(), expected.next().unwrap());
1009
1010                let addr = Address::p2wsh(&script, blinder, params);
1011                assert_eq!(&addr.to_string(), expected.next().unwrap());
1012
1013                let addr = Address::p2tr(&secp, internal_key, None, blinder, params);
1014                assert_eq!(&addr.to_string(), expected.next().unwrap());
1015
1016                let addr = Address::p2tr(&secp, internal_key, Some(tap_node_hash), blinder, params);
1017                assert_eq!(&addr.to_string(), expected.next().unwrap());
1018            }
1019        }
1020    }
1021}