bdkffi/
descriptor.rs

1use crate::bitcoin::DescriptorId;
2use crate::bitcoin::DescriptorType;
3use crate::bitcoin::{Address, NetworkKind};
4use crate::error::DescriptorError;
5use crate::error::MiniscriptError;
6use crate::keys::DescriptorPublicKey;
7use crate::keys::DescriptorSecretKey;
8use crate::types::KeychainKind;
9
10use bdk_wallet::bitcoin::bip32::Fingerprint;
11use bdk_wallet::bitcoin::key::Secp256k1;
12use bdk_wallet::bitcoin::Network;
13use bdk_wallet::chain::DescriptorExt;
14use bdk_wallet::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
15use bdk_wallet::keys::DescriptorPublicKey as BdkDescriptorPublicKey;
16use bdk_wallet::keys::{DescriptorSecretKey as BdkDescriptorSecretKey, KeyMap};
17use bdk_wallet::miniscript::descriptor::ConversionError;
18use bdk_wallet::miniscript::Miniscript as BDKMiniscript;
19use bdk_wallet::template::{
20    Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, Bip86, Bip86Public,
21    DescriptorTemplate,
22};
23
24use std::fmt::Display;
25use std::str::FromStr;
26use std::sync::Arc;
27
28/// An expression of how to derive output scripts: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md
29#[derive(Debug, uniffi::Object)]
30#[uniffi::export(Debug, Display)]
31pub struct Descriptor {
32    pub extended_descriptor: ExtendedDescriptor,
33    pub key_map: KeyMap,
34}
35
36#[uniffi::export]
37impl Descriptor {
38    /// Parse a string as a descriptor for the given network.
39    #[uniffi::constructor]
40    pub fn new(descriptor: String, network_kind: NetworkKind) -> Result<Self, DescriptorError> {
41        let secp = Secp256k1::new();
42        let (extended_descriptor, key_map) =
43            descriptor.into_wallet_descriptor(&secp, network_kind)?;
44        Ok(Self {
45            extended_descriptor,
46            key_map,
47        })
48    }
49
50    /// Multi-account hierarchy descriptor: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
51    #[uniffi::constructor]
52    pub fn new_bip44(
53        secret_key: &DescriptorSecretKey,
54        keychain_kind: KeychainKind,
55        network_kind: NetworkKind,
56    ) -> Self {
57        let derivable_key = &secret_key.0;
58
59        match derivable_key {
60            BdkDescriptorSecretKey::Single(_) => {
61                unreachable!()
62            }
63            BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
64                let derivable_key = descriptor_x_key.xkey;
65                let (extended_descriptor, key_map, _) = Bip44(derivable_key, keychain_kind)
66                    .build(network_kind)
67                    .unwrap();
68                Self {
69                    extended_descriptor,
70                    key_map,
71                }
72            }
73            BdkDescriptorSecretKey::MultiXPrv(_) => {
74                unreachable!()
75            }
76        }
77    }
78
79    /// Multi-account hierarchy descriptor: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
80    #[uniffi::constructor]
81    pub fn new_bip44_public(
82        public_key: &DescriptorPublicKey,
83        fingerprint: String,
84        keychain_kind: KeychainKind,
85        network_kind: NetworkKind,
86    ) -> Result<Self, DescriptorError> {
87        let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
88            DescriptorError::Bip32 {
89                error_message: error.to_string(),
90            }
91        })?;
92        let derivable_key = &public_key.0;
93
94        match derivable_key {
95            BdkDescriptorPublicKey::Single(_) => {
96                unreachable!()
97            }
98            BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
99                let derivable_key = descriptor_x_key.xkey;
100                let (extended_descriptor, key_map, _) =
101                    Bip44Public(derivable_key, fingerprint, keychain_kind)
102                        .build(network_kind)
103                        .map_err(DescriptorError::from)?;
104
105                Ok(Self {
106                    extended_descriptor,
107                    key_map,
108                })
109            }
110            BdkDescriptorPublicKey::MultiXPub(_) => {
111                unreachable!()
112            }
113        }
114    }
115
116    /// P2SH nested P2WSH descriptor: https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki
117    #[uniffi::constructor]
118    pub fn new_bip49(
119        secret_key: &DescriptorSecretKey,
120        keychain_kind: KeychainKind,
121        network_kind: NetworkKind,
122    ) -> Self {
123        let derivable_key = &secret_key.0;
124
125        match derivable_key {
126            BdkDescriptorSecretKey::Single(_) => {
127                unreachable!()
128            }
129            BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
130                let derivable_key = descriptor_x_key.xkey;
131                let (extended_descriptor, key_map, _) = Bip49(derivable_key, keychain_kind)
132                    .build(network_kind)
133                    .unwrap();
134                Self {
135                    extended_descriptor,
136                    key_map,
137                }
138            }
139            BdkDescriptorSecretKey::MultiXPrv(_) => {
140                unreachable!()
141            }
142        }
143    }
144
145    /// P2SH nested P2WSH descriptor: https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki
146    #[uniffi::constructor]
147    pub fn new_bip49_public(
148        public_key: &DescriptorPublicKey,
149        fingerprint: String,
150        keychain_kind: KeychainKind,
151        network_kind: NetworkKind,
152    ) -> Result<Self, DescriptorError> {
153        let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
154            DescriptorError::Bip32 {
155                error_message: error.to_string(),
156            }
157        })?;
158        let derivable_key = &public_key.0;
159
160        match derivable_key {
161            BdkDescriptorPublicKey::Single(_) => {
162                unreachable!()
163            }
164            BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
165                let derivable_key = descriptor_x_key.xkey;
166                let (extended_descriptor, key_map, _) =
167                    Bip49Public(derivable_key, fingerprint, keychain_kind)
168                        .build(network_kind)
169                        .map_err(DescriptorError::from)?;
170
171                Ok(Self {
172                    extended_descriptor,
173                    key_map,
174                })
175            }
176            BdkDescriptorPublicKey::MultiXPub(_) => {
177                unreachable!()
178            }
179        }
180    }
181
182    /// Pay to witness PKH descriptor: https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki
183    #[uniffi::constructor]
184    pub fn new_bip84(
185        secret_key: &DescriptorSecretKey,
186        keychain_kind: KeychainKind,
187        network_kind: NetworkKind,
188    ) -> Self {
189        let derivable_key = &secret_key.0;
190
191        match derivable_key {
192            BdkDescriptorSecretKey::Single(_) => {
193                unreachable!()
194            }
195            BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
196                let derivable_key = descriptor_x_key.xkey;
197                let (extended_descriptor, key_map, _) = Bip84(derivable_key, keychain_kind)
198                    .build(network_kind)
199                    .unwrap();
200                Self {
201                    extended_descriptor,
202                    key_map,
203                }
204            }
205            BdkDescriptorSecretKey::MultiXPrv(_) => {
206                unreachable!()
207            }
208        }
209    }
210
211    /// Pay to witness PKH descriptor: https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki
212    #[uniffi::constructor]
213    pub fn new_bip84_public(
214        public_key: &DescriptorPublicKey,
215        fingerprint: String,
216        keychain_kind: KeychainKind,
217        network_kind: NetworkKind,
218    ) -> Result<Self, DescriptorError> {
219        let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
220            DescriptorError::Bip32 {
221                error_message: error.to_string(),
222            }
223        })?;
224        let derivable_key = &public_key.0;
225
226        match derivable_key {
227            BdkDescriptorPublicKey::Single(_) => {
228                unreachable!()
229            }
230            BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
231                let derivable_key = descriptor_x_key.xkey;
232                let (extended_descriptor, key_map, _) =
233                    Bip84Public(derivable_key, fingerprint, keychain_kind)
234                        .build(network_kind)
235                        .map_err(DescriptorError::from)?;
236
237                Ok(Self {
238                    extended_descriptor,
239                    key_map,
240                })
241            }
242            BdkDescriptorPublicKey::MultiXPub(_) => {
243                unreachable!()
244            }
245        }
246    }
247
248    /// Single key P2TR descriptor: https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
249    #[uniffi::constructor]
250    pub fn new_bip86(
251        secret_key: &DescriptorSecretKey,
252        keychain_kind: KeychainKind,
253        network_kind: NetworkKind,
254    ) -> Self {
255        let derivable_key = &secret_key.0;
256
257        match derivable_key {
258            BdkDescriptorSecretKey::Single(_) => {
259                unreachable!()
260            }
261            BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
262                let derivable_key = descriptor_x_key.xkey;
263                let (extended_descriptor, key_map, _) = Bip86(derivable_key, keychain_kind)
264                    .build(network_kind)
265                    .unwrap();
266                Self {
267                    extended_descriptor,
268                    key_map,
269                }
270            }
271            BdkDescriptorSecretKey::MultiXPrv(_) => {
272                unreachable!()
273            }
274        }
275    }
276
277    /// Single key P2TR descriptor: https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
278    #[uniffi::constructor]
279    pub fn new_bip86_public(
280        public_key: &DescriptorPublicKey,
281        fingerprint: String,
282        keychain_kind: KeychainKind,
283        network_kind: NetworkKind,
284    ) -> Result<Self, DescriptorError> {
285        let fingerprint = Fingerprint::from_str(fingerprint.as_str()).map_err(|error| {
286            DescriptorError::Bip32 {
287                error_message: error.to_string(),
288            }
289        })?;
290        let derivable_key = &public_key.0;
291
292        match derivable_key {
293            BdkDescriptorPublicKey::Single(_) => {
294                unreachable!()
295            }
296            BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
297                let derivable_key = descriptor_x_key.xkey;
298                let (extended_descriptor, key_map, _) =
299                    Bip86Public(derivable_key, fingerprint, keychain_kind)
300                        .build(network_kind)
301                        .map_err(DescriptorError::from)?;
302
303                Ok(Self {
304                    extended_descriptor,
305                    key_map,
306                })
307            }
308            BdkDescriptorPublicKey::MultiXPub(_) => {
309                unreachable!()
310            }
311        }
312    }
313
314    /// Create a new wsh sorted multi descriptor
315    /// Errors when miniscript exceeds resource limits under p2sh context
316    #[uniffi::constructor]
317    pub fn new_wsh_sortedmulti(k: u32, pks: Vec<String>) -> Result<Self, DescriptorError> {
318        let bdk_pks: Vec<BdkDescriptorPublicKey> = pks
319            .iter()
320            .map(|pk| {
321                BdkDescriptorPublicKey::from_str(pk).map_err(|e| DescriptorError::Key {
322                    error_message: e.to_string(),
323                })
324            })
325            .collect::<Result<Vec<BdkDescriptorPublicKey>, DescriptorError>>()?;
326        let miniscript_descriptor =
327            match bdk_wallet::miniscript::Descriptor::new_wsh_sortedmulti(k as usize, bdk_pks) {
328                Ok(descriptor) => descriptor,
329                Err(e) => {
330                    return Err(DescriptorError::Miniscript {
331                        error_message: e.to_string(),
332                    })
333                }
334            };
335        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
336
337        Ok(Self {
338            extended_descriptor,
339            key_map: KeyMap::new(),
340        })
341    }
342
343    /// Create a new sh sortedmulti descriptor with threshold k and Vec of pks.
344    /// Errors when miniscript exceeds resource limits under p2sh context
345    #[uniffi::constructor]
346    pub fn new_sh_sortedmulti(k: u32, pks: Vec<String>) -> Result<Self, DescriptorError> {
347        let bdk_pks: Vec<BdkDescriptorPublicKey> = pks
348            .iter()
349            .map(|pk| {
350                BdkDescriptorPublicKey::from_str(pk).map_err(|e| DescriptorError::Key {
351                    error_message: e.to_string(),
352                })
353            })
354            .collect::<Result<Vec<BdkDescriptorPublicKey>, DescriptorError>>()?;
355        let miniscript_descriptor =
356            match bdk_wallet::miniscript::Descriptor::new_sh_sortedmulti(k as usize, bdk_pks) {
357                Ok(descriptor) => descriptor,
358                Err(e) => {
359                    return Err(DescriptorError::Miniscript {
360                        error_message: e.to_string(),
361                    })
362                }
363            };
364        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
365
366        Ok(Self {
367            extended_descriptor,
368            key_map: KeyMap::new(),
369        })
370    }
371
372    /// Create a new sh wrapped wsh sortedmulti descriptor from threshold k and Vec of pks
373    /// Errors when miniscript exceeds resource limits under segwit context
374    #[uniffi::constructor]
375    pub fn new_sh_wsh_sortedmulti(k: u32, pks: Vec<String>) -> Result<Self, DescriptorError> {
376        let bdk_pks: Vec<BdkDescriptorPublicKey> = pks
377            .iter()
378            .map(|pk| {
379                BdkDescriptorPublicKey::from_str(pk).map_err(|e| DescriptorError::Key {
380                    error_message: e.to_string(),
381                })
382            })
383            .collect::<Result<Vec<BdkDescriptorPublicKey>, DescriptorError>>()?;
384        let miniscript_descriptor =
385            match bdk_wallet::miniscript::Descriptor::new_sh_wsh_sortedmulti(k as usize, bdk_pks) {
386                Ok(descriptor) => descriptor,
387                Err(e) => {
388                    return Err(DescriptorError::Miniscript {
389                        error_message: e.to_string(),
390                    })
391                }
392            };
393        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
394
395        Ok(Self {
396            extended_descriptor,
397            key_map: KeyMap::new(),
398        })
399    }
400
401    /// Create a new pay-to-pubkey descriptor from a public key string.
402    #[uniffi::constructor]
403    pub fn new_pk(pk: String) -> Result<Self, DescriptorError> {
404        let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
405            error_message: e.to_string(),
406        })?;
407
408        let miniscript_descriptor = bdk_wallet::miniscript::Descriptor::new_pk(key);
409        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
410
411        Ok(Self {
412            extended_descriptor,
413            key_map: KeyMap::new(),
414        })
415    }
416
417    /// Create a new PkH descriptor
418    #[uniffi::constructor]
419    pub fn new_pkh(pk: String) -> Result<Self, DescriptorError> {
420        let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
421            error_message: e.to_string(),
422        })?;
423
424        let miniscript_descriptor = match bdk_wallet::miniscript::Descriptor::new_pkh(key) {
425            Ok(descriptor) => descriptor,
426            Err(e) => {
427                return Err(DescriptorError::Miniscript {
428                    error_message: e.to_string(),
429                })
430            }
431        };
432        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
433
434        Ok(Self {
435            extended_descriptor,
436            key_map: KeyMap::new(),
437        })
438    }
439
440    /// Create a new Wpkh descriptor Will return Err if uncompressed key is used
441    #[uniffi::constructor]
442    pub fn new_wpkh(pk: String) -> Result<Self, DescriptorError> {
443        let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
444            error_message: e.to_string(),
445        })?;
446
447        let miniscript_descriptor = match bdk_wallet::miniscript::Descriptor::new_wpkh(key) {
448            Ok(descriptor) => descriptor,
449            Err(e) => {
450                return Err(DescriptorError::Miniscript {
451                    error_message: e.to_string(),
452                })
453            }
454        };
455        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
456
457        Ok(Self {
458            extended_descriptor,
459            key_map: KeyMap::new(),
460        })
461    }
462
463    /// Create a new sh wrapped wpkh from Pk. Errors when uncompressed keys are supplied
464    #[uniffi::constructor]
465    pub fn new_sh_wpkh(pk: String) -> Result<Self, DescriptorError> {
466        let key = BdkDescriptorPublicKey::from_str(&pk).map_err(|e| DescriptorError::Key {
467            error_message: e.to_string(),
468        })?;
469
470        let miniscript_descriptor = match bdk_wallet::miniscript::Descriptor::new_sh_wpkh(key) {
471            Ok(descriptor) => descriptor,
472            Err(e) => {
473                return Err(DescriptorError::Miniscript {
474                    error_message: e.to_string(),
475                })
476            }
477        };
478        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
479
480        Ok(Self {
481            extended_descriptor,
482            key_map: KeyMap::new(),
483        })
484    }
485
486    /// Create a new wsh descriptor from witness script Errors when miniscript exceeds resource limits
487    /// under p2sh context or does not type check at the top level
488    #[uniffi::constructor]
489    pub fn new_wsh(mini_script: String) -> Result<Self, DescriptorError> {
490        let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
491            Ok(miniscript) => miniscript,
492            Err(e) => {
493                return Err(DescriptorError::Miniscript {
494                    error_message: e.to_string(),
495                });
496            }
497        };
498
499        let miniscript_descriptor =
500            match bdk_wallet::miniscript::Descriptor::new_wsh(parsed_miniscript) {
501                Ok(descriptor) => descriptor,
502                Err(e) => {
503                    return Err(DescriptorError::Miniscript {
504                        error_message: e.to_string(),
505                    })
506                }
507            };
508        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
509
510        Ok(Self {
511            extended_descriptor,
512            key_map: KeyMap::new(),
513        })
514    }
515
516    /// Create a new sh wrapped wsh descriptor with witness script Errors when miniscript exceeds resource limits
517    /// under wsh context or does not type check at the top level
518    #[uniffi::constructor]
519    pub fn new_sh_wsh(mini_script: String) -> Result<Self, DescriptorError> {
520        let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
521            Ok(miniscript) => miniscript,
522            Err(e) => {
523                return Err(DescriptorError::Miniscript {
524                    error_message: e.to_string(),
525                });
526            }
527        };
528
529        let miniscript_descriptor =
530            match bdk_wallet::miniscript::Descriptor::new_sh_wsh(parsed_miniscript) {
531                Ok(descriptor) => descriptor,
532                Err(e) => {
533                    return Err(DescriptorError::Miniscript {
534                        error_message: e.to_string(),
535                    })
536                }
537            };
538        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
539
540        Ok(Self {
541            extended_descriptor,
542            key_map: KeyMap::new(),
543        })
544    }
545
546    /// Create a new sh for a given redeem script Errors when miniscript exceeds resource limits under p2sh context or does not type check at the top level
547    #[uniffi::constructor]
548    pub fn new_sh(mini_script: String) -> Result<Self, DescriptorError> {
549        let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
550            Ok(miniscript) => miniscript,
551            Err(e) => {
552                return Err(DescriptorError::Miniscript {
553                    error_message: e.to_string(),
554                });
555            }
556        };
557
558        let miniscript_descriptor =
559            match bdk_wallet::miniscript::Descriptor::new_sh(parsed_miniscript) {
560                Ok(descriptor) => descriptor,
561                Err(e) => {
562                    return Err(DescriptorError::Miniscript {
563                        error_message: e.to_string(),
564                    })
565                }
566            };
567        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
568
569        Ok(Self {
570            extended_descriptor,
571            key_map: KeyMap::new(),
572        })
573    }
574
575    /// Create a new bare descriptor from witness script Errors when miniscript exceeds resource limits
576    /// under bare context or does not type check at the top level
577    #[uniffi::constructor]
578    pub fn new_bare(mini_script: String) -> Result<Self, DescriptorError> {
579        let parsed_miniscript = match BDKMiniscript::from_str(&mini_script) {
580            Ok(miniscript) => miniscript,
581            Err(e) => {
582                return Err(DescriptorError::Miniscript {
583                    error_message: e.to_string(),
584                });
585            }
586        };
587
588        let miniscript_descriptor =
589            match bdk_wallet::miniscript::Descriptor::new_bare(parsed_miniscript) {
590                Ok(descriptor) => descriptor,
591                Err(e) => {
592                    return Err(DescriptorError::Miniscript {
593                        error_message: e.to_string(),
594                    })
595                }
596            };
597        let extended_descriptor = ExtendedDescriptor::from(miniscript_descriptor);
598
599        Ok(Self {
600            extended_descriptor,
601            key_map: KeyMap::new(),
602        })
603    }
604
605    /// Dangerously convert the descriptor to a string.
606    pub fn to_string_with_secret(&self) -> String {
607        let descriptor = &self.extended_descriptor;
608        let key_map = &self.key_map;
609        descriptor.to_string_with_secret(key_map)
610    }
611
612    /// Does this descriptor contain paths: https://github.com/bitcoin/bips/blob/master/bip-0389.mediawiki
613    pub fn is_multipath(&self) -> bool {
614        self.extended_descriptor.is_multipath()
615    }
616
617    /// A unique identifier for the descriptor.
618    pub fn descriptor_id(&self) -> Arc<DescriptorId> {
619        let d_id = self.extended_descriptor.descriptor_id();
620        Arc::new(DescriptorId(d_id.0))
621    }
622
623    /// Return descriptors for all valid paths.
624    pub fn to_single_descriptors(&self) -> Result<Vec<Arc<Descriptor>>, MiniscriptError> {
625        self.extended_descriptor
626            .clone()
627            .into_single_descriptors()
628            .map_err(MiniscriptError::from)
629            .map(|descriptors| {
630                descriptors
631                    .into_iter()
632                    .map(|desc| {
633                        Arc::new(Descriptor {
634                            extended_descriptor: desc,
635                            key_map: self.key_map.clone(),
636                        })
637                    })
638                    .collect()
639            })
640    }
641
642    /// Computes an upper bound on the difference between a non-satisfied `TxIn`'s
643    /// `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`.
644    pub fn max_weight_to_satisfy(&self) -> Result<u64, DescriptorError> {
645        let weight = self
646            .extended_descriptor
647            .max_weight_to_satisfy()
648            .map_err(|e| DescriptorError::Miniscript {
649                error_message: e.to_string(),
650            })?;
651        Ok(weight.to_wu())
652    }
653
654    pub fn desc_type(&self) -> DescriptorType {
655        self.extended_descriptor.desc_type()
656    }
657
658    pub fn derive_address(
659        &self,
660        index: u32,
661        network: Network,
662    ) -> Result<Arc<Address>, DescriptorError> {
663        if self.extended_descriptor.is_multipath() {
664            return Err(DescriptorError::MultiPath);
665        }
666
667        let derived_descriptor = self
668            .extended_descriptor
669            .at_derivation_index(index)
670            .map_err(|error| match error {
671                ConversionError::HardenedChild => DescriptorError::HardenedDerivationXpub,
672                ConversionError::MultiKey => DescriptorError::MultiPath,
673            })?;
674
675        let address = derived_descriptor
676            .address(network)
677            .map_err(|error| DescriptorError::Miniscript {
678                error_message: error.to_string(),
679            })?
680            .into();
681
682        Ok(Arc::new(address))
683    }
684
685    /// Whether or not the descriptor has any wildcards.
686    pub fn has_wildcard(&self) -> bool {
687        self.extended_descriptor.has_wildcard()
688    }
689
690    /// Checks whether the descriptor is safe.
691    ///
692    /// Checks whether all the spend paths in the descriptor are possible on the
693    /// bitcoin network under the current standardness and consensus rules. Also
694    /// checks whether the descriptor requires signatures on all spend paths and
695    /// whether the script is malleable.
696    ///
697    /// In general, all the guarantees of miniscript hold only for safe scripts.
698    /// The signer may not be able to find satisfactions even if one exists.
699    pub fn sanity_check(&self) -> Result<(), DescriptorError> {
700        self.extended_descriptor
701            .sanity_check()
702            .map_err(|e| DescriptorError::Miniscript {
703                error_message: e.to_string(),
704            })
705    }
706}
707
708impl Display for Descriptor {
709    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
710        write!(f, "{}", self.extended_descriptor)
711    }
712}