jitash_bdk/wallet/
signer.rs

1// Bitcoin Dev Kit
2// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
3//
4// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
5//
6// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9// You may not use this file except in accordance with one or both of these
10// licenses.
11
12//! Generalized signers
13//!
14//! This module provides the ability to add customized signers to a [`Wallet`](super::Wallet)
15//! through the [`Wallet::add_signer`](super::Wallet::add_signer) function.
16//!
17//! ```
18//! # use std::sync::Arc;
19//! # use std::str::FromStr;
20//! # use bitcoin::secp256k1::{Secp256k1, All};
21//! # use bitcoin::*;
22//! # use bitcoin::util::psbt;
23//! # use jitash_bdk::signer::*;
24//! # use jitash_bdk::database::*;
25//! # use jitash_bdk::*;
26//! # #[derive(Debug)]
27//! # struct CustomHSM;
28//! # impl CustomHSM {
29//! #     fn hsm_sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> {
30//! #         Ok(())
31//! #     }
32//! #     fn connect() -> Self {
33//! #         CustomHSM
34//! #     }
35//! #     fn get_id(&self) -> SignerId {
36//! #         SignerId::Dummy(0)
37//! #     }
38//! # }
39//! #[derive(Debug)]
40//! struct CustomSigner {
41//!     device: CustomHSM,
42//! }
43//!
44//! impl CustomSigner {
45//!     fn connect() -> Self {
46//!         CustomSigner { device: CustomHSM::connect() }
47//!     }
48//! }
49//!
50//! impl SignerCommon for CustomSigner {
51//!     fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
52//!         self.device.get_id()
53//!     }
54//! }
55//!
56//! impl InputSigner for CustomSigner {
57//!     fn sign_input(
58//!         &self,
59//!         psbt: &mut psbt::PartiallySignedTransaction,
60//!         input_index: usize,
61//!         _sign_options: &SignOptions,
62//!         _secp: &Secp256k1<All>,
63//!     ) -> Result<(), SignerError> {
64//!         self.device.hsm_sign_input(psbt, input_index)?;
65//!
66//!         Ok(())
67//!     }
68//! }
69//!
70//! let custom_signer = CustomSigner::connect();
71//!
72//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
73//! let mut wallet = Wallet::new(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
74//! wallet.add_signer(
75//!     KeychainKind::External,
76//!     SignerOrdering(200),
77//!     Arc::new(custom_signer)
78//! );
79//!
80//! # Ok::<_, jitash_bdk::Error>(())
81//! ```
82
83use std::cmp::Ordering;
84use std::collections::BTreeMap;
85use std::fmt;
86use std::ops::{Bound::Included, Deref};
87use std::sync::Arc;
88
89use bitcoin::blockdata::opcodes;
90use bitcoin::blockdata::script::Builder as ScriptBuilder;
91use bitcoin::hashes::{hash160, Hash};
92use bitcoin::secp256k1::Message;
93use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, Fingerprint};
94use bitcoin::util::{ecdsa, psbt, schnorr, sighash, taproot};
95use bitcoin::{secp256k1, XOnlyPublicKey};
96use bitcoin::{EcdsaSighashType, PrivateKey, PublicKey, SchnorrSighashType, Script};
97
98use miniscript::descriptor::{
99    Descriptor, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, KeyMap, SinglePriv,
100    SinglePubKey,
101};
102use miniscript::{Legacy, Segwitv0, SigType, Tap, ToPublicKey};
103
104use super::utils::SecpCtx;
105use crate::descriptor::{DescriptorMeta, XKeyUtils};
106use crate::psbt::PsbtUtils;
107
108/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
109/// multiple of them
110#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq, Hash)]
111pub enum SignerId {
112    /// Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA public key
113    PkHash(hash160::Hash),
114    /// The fingerprint of a BIP32 extended key
115    Fingerprint(Fingerprint),
116    /// Dummy identifier
117    Dummy(u64),
118}
119
120impl From<hash160::Hash> for SignerId {
121    fn from(hash: hash160::Hash) -> SignerId {
122        SignerId::PkHash(hash)
123    }
124}
125
126impl From<Fingerprint> for SignerId {
127    fn from(fing: Fingerprint) -> SignerId {
128        SignerId::Fingerprint(fing)
129    }
130}
131
132/// Signing error
133#[derive(Debug, PartialEq, Eq, Clone)]
134pub enum SignerError {
135    /// The private key is missing for the required public key
136    MissingKey,
137    /// The private key in use has the right fingerprint but derives differently than expected
138    InvalidKey,
139    /// The user canceled the operation
140    UserCanceled,
141    /// Input index is out of range
142    InputIndexOutOfRange,
143    /// The `non_witness_utxo` field of the transaction is required to sign this input
144    MissingNonWitnessUtxo,
145    /// The `non_witness_utxo` specified is invalid
146    InvalidNonWitnessUtxo,
147    /// The `witness_utxo` field of the transaction is required to sign this input
148    MissingWitnessUtxo,
149    /// The `witness_script` field of the transaction is required to sign this input
150    MissingWitnessScript,
151    /// The fingerprint and derivation path are missing from the psbt input
152    MissingHdKeypath,
153    /// The psbt contains a non-`SIGHASH_ALL` sighash in one of its input and the user hasn't
154    /// explicitly allowed them
155    ///
156    /// To enable signing transactions with non-standard sighashes set
157    /// [`SignOptions::allow_all_sighashes`] to `true`.
158    NonStandardSighash,
159    /// Invalid SIGHASH for the signing context in use
160    InvalidSighash,
161    /// Error while computing the hash to sign
162    SighashError(sighash::Error),
163    /// Error while signing using hardware wallets
164    #[cfg(feature = "hardware-signer")]
165    HWIError(hwi::error::Error),
166}
167
168#[cfg(feature = "hardware-signer")]
169impl From<hwi::error::Error> for SignerError {
170    fn from(e: hwi::error::Error) -> Self {
171        SignerError::HWIError(e)
172    }
173}
174
175impl From<sighash::Error> for SignerError {
176    fn from(e: sighash::Error) -> Self {
177        SignerError::SighashError(e)
178    }
179}
180
181impl fmt::Display for SignerError {
182    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183        match self {
184            Self::MissingKey => write!(f, "Missing private key"),
185            Self::InvalidKey => write!(f, "The private key in use has the right fingerprint but derives differently than expected"),
186            Self::UserCanceled => write!(f, "The user canceled the operation"),
187            Self::InputIndexOutOfRange => write!(f, "Input index out of range"),
188            Self::MissingNonWitnessUtxo => write!(f, "Missing non-witness UTXO"),
189            Self::InvalidNonWitnessUtxo => write!(f, "Invalid non-witness UTXO"),
190            Self::MissingWitnessUtxo => write!(f, "Missing witness UTXO"),
191            Self::MissingWitnessScript => write!(f, "Missing witness script"),
192            Self::MissingHdKeypath => write!(f, "Missing fingerprint and derivation path"),
193            Self::NonStandardSighash => write!(f, "The psbt contains a non standard sighash"),
194            Self::InvalidSighash => write!(f, "Invalid SIGHASH for the signing context in use"),
195            Self::SighashError(err) => write!(f, "Error while computing the hash to sign: {}", err),
196            #[cfg(feature = "hardware-signer")]
197            Self::HWIError(err) => write!(f, "Error while signing using hardware wallets: {}", err),
198        }
199    }
200}
201
202impl std::error::Error for SignerError {}
203
204/// Signing context
205///
206/// Used by our software signers to determine the type of signatures to make
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum SignerContext {
209    /// Legacy context
210    Legacy,
211    /// Segwit v0 context (BIP 143)
212    Segwitv0,
213    /// Taproot context (BIP 340)
214    Tap {
215        /// Whether the signer can sign for the internal key or not
216        is_internal_key: bool,
217    },
218}
219
220/// Wrapper structure to pair a signer with its context
221#[derive(Debug, Clone)]
222pub struct SignerWrapper<S: Sized + fmt::Debug + Clone> {
223    signer: S,
224    ctx: SignerContext,
225}
226
227impl<S: Sized + fmt::Debug + Clone> SignerWrapper<S> {
228    /// Create a wrapped signer from a signer and a context
229    pub fn new(signer: S, ctx: SignerContext) -> Self {
230        SignerWrapper { signer, ctx }
231    }
232}
233
234impl<S: Sized + fmt::Debug + Clone> Deref for SignerWrapper<S> {
235    type Target = S;
236
237    fn deref(&self) -> &Self::Target {
238        &self.signer
239    }
240}
241
242/// Common signer methods
243pub trait SignerCommon: fmt::Debug + Send + Sync {
244    /// Return the [`SignerId`] for this signer
245    ///
246    /// The [`SignerId`] can be used to lookup a signer in the [`Wallet`](crate::Wallet)'s signers map or to
247    /// compare two signers.
248    fn id(&self, secp: &SecpCtx) -> SignerId;
249
250    /// Return the secret key for the signer
251    ///
252    /// This is used internally to reconstruct the original descriptor that may contain secrets.
253    /// External signers that are meant to keep key isolated should just return `None` here (which
254    /// is the default for this method, if not overridden).
255    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
256        None
257    }
258}
259
260/// PSBT Input signer
261///
262/// This trait can be implemented to provide custom signers to the wallet. If the signer supports signing
263/// individual inputs, this trait should be implemented and BDK will provide automatically an implementation
264/// for [`TransactionSigner`].
265pub trait InputSigner: SignerCommon {
266    /// Sign a single psbt input
267    fn sign_input(
268        &self,
269        psbt: &mut psbt::PartiallySignedTransaction,
270        input_index: usize,
271        sign_options: &SignOptions,
272        secp: &SecpCtx,
273    ) -> Result<(), SignerError>;
274}
275
276/// PSBT signer
277///
278/// This trait can be implemented when the signer can't sign inputs individually, but signs the whole transaction
279/// at once.
280pub trait TransactionSigner: SignerCommon {
281    /// Sign all the inputs of the psbt
282    fn sign_transaction(
283        &self,
284        psbt: &mut psbt::PartiallySignedTransaction,
285        sign_options: &SignOptions,
286        secp: &SecpCtx,
287    ) -> Result<(), SignerError>;
288}
289
290impl<T: InputSigner> TransactionSigner for T {
291    fn sign_transaction(
292        &self,
293        psbt: &mut psbt::PartiallySignedTransaction,
294        sign_options: &SignOptions,
295        secp: &SecpCtx,
296    ) -> Result<(), SignerError> {
297        for input_index in 0..psbt.inputs.len() {
298            self.sign_input(psbt, input_index, sign_options, secp)?;
299        }
300
301        Ok(())
302    }
303}
304
305impl SignerCommon for SignerWrapper<DescriptorXKey<ExtendedPrivKey>> {
306    fn id(&self, secp: &SecpCtx) -> SignerId {
307        SignerId::from(self.root_fingerprint(secp))
308    }
309
310    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
311        Some(DescriptorSecretKey::XPrv(self.signer.clone()))
312    }
313}
314
315impl InputSigner for SignerWrapper<DescriptorXKey<ExtendedPrivKey>> {
316    fn sign_input(
317        &self,
318        psbt: &mut psbt::PartiallySignedTransaction,
319        input_index: usize,
320        sign_options: &SignOptions,
321        secp: &SecpCtx,
322    ) -> Result<(), SignerError> {
323        if input_index >= psbt.inputs.len() {
324            return Err(SignerError::InputIndexOutOfRange);
325        }
326
327        if psbt.inputs[input_index].final_script_sig.is_some()
328            || psbt.inputs[input_index].final_script_witness.is_some()
329        {
330            return Ok(());
331        }
332
333        let tap_key_origins = psbt.inputs[input_index]
334            .tap_key_origins
335            .iter()
336            .map(|(pk, (_, keysource))| (SinglePubKey::XOnly(*pk), keysource));
337        let (public_key, full_path) = match psbt.inputs[input_index]
338            .bip32_derivation
339            .iter()
340            .map(|(pk, keysource)| (SinglePubKey::FullKey(PublicKey::new(*pk)), keysource))
341            .chain(tap_key_origins)
342            .find_map(|(pk, keysource)| {
343                if self.matches(keysource, secp).is_some() {
344                    Some((pk, keysource.1.clone()))
345                } else {
346                    None
347                }
348            }) {
349            Some((pk, full_path)) => (pk, full_path),
350            None => return Ok(()),
351        };
352
353        let derived_key = match self.origin.clone() {
354            Some((_fingerprint, origin_path)) => {
355                let deriv_path = DerivationPath::from(
356                    &full_path.into_iter().cloned().collect::<Vec<ChildNumber>>()
357                        [origin_path.len()..],
358                );
359                self.xkey.derive_priv(secp, &deriv_path).unwrap()
360            }
361            None => self.xkey.derive_priv(secp, &full_path).unwrap(),
362        };
363
364        let computed_pk = secp256k1::PublicKey::from_secret_key(secp, &derived_key.private_key);
365        let valid_key = match public_key {
366            SinglePubKey::FullKey(pk) if pk.inner == computed_pk => true,
367            SinglePubKey::XOnly(x_only) if XOnlyPublicKey::from(computed_pk) == x_only => true,
368            _ => false,
369        };
370        if !valid_key {
371            Err(SignerError::InvalidKey)
372        } else {
373            // HD wallets imply compressed keys
374            let priv_key = PrivateKey {
375                compressed: true,
376                network: self.xkey.network,
377                inner: derived_key.private_key,
378            };
379
380            SignerWrapper::new(priv_key, self.ctx).sign_input(psbt, input_index, sign_options, secp)
381        }
382    }
383}
384
385impl SignerCommon for SignerWrapper<PrivateKey> {
386    fn id(&self, secp: &SecpCtx) -> SignerId {
387        SignerId::from(self.public_key(secp).to_pubkeyhash(SigType::Ecdsa))
388    }
389
390    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
391        Some(DescriptorSecretKey::Single(SinglePriv {
392            key: self.signer,
393            origin: None,
394        }))
395    }
396}
397
398impl InputSigner for SignerWrapper<PrivateKey> {
399    fn sign_input(
400        &self,
401        psbt: &mut psbt::PartiallySignedTransaction,
402        input_index: usize,
403        sign_options: &SignOptions,
404        secp: &SecpCtx,
405    ) -> Result<(), SignerError> {
406        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
407            return Err(SignerError::InputIndexOutOfRange);
408        }
409
410        if psbt.inputs[input_index].final_script_sig.is_some()
411            || psbt.inputs[input_index].final_script_witness.is_some()
412        {
413            return Ok(());
414        }
415
416        let pubkey = PublicKey::from_private_key(secp, self);
417        let x_only_pubkey = XOnlyPublicKey::from(pubkey.inner);
418
419        if let SignerContext::Tap { is_internal_key } = self.ctx {
420            if is_internal_key
421                && psbt.inputs[input_index].tap_key_sig.is_none()
422                && sign_options.sign_with_tap_internal_key
423            {
424                let (hash, hash_ty) = Tap::sighash(psbt, input_index, None)?;
425                sign_psbt_schnorr(
426                    &self.inner,
427                    x_only_pubkey,
428                    None,
429                    &mut psbt.inputs[input_index],
430                    hash,
431                    hash_ty,
432                    secp,
433                );
434            }
435
436            if let Some((leaf_hashes, _)) =
437                psbt.inputs[input_index].tap_key_origins.get(&x_only_pubkey)
438            {
439                let leaf_hashes = leaf_hashes
440                    .iter()
441                    .filter(|lh| {
442                        // Removing the leaves we shouldn't sign for
443                        let should_sign = match &sign_options.tap_leaves_options {
444                            TapLeavesOptions::All => true,
445                            TapLeavesOptions::Include(v) => v.contains(lh),
446                            TapLeavesOptions::Exclude(v) => !v.contains(lh),
447                            TapLeavesOptions::None => false,
448                        };
449                        // Filtering out the leaves without our key
450                        should_sign
451                            && !psbt.inputs[input_index]
452                                .tap_script_sigs
453                                .contains_key(&(x_only_pubkey, **lh))
454                    })
455                    .cloned()
456                    .collect::<Vec<_>>();
457                for lh in leaf_hashes {
458                    let (hash, hash_ty) = Tap::sighash(psbt, input_index, Some(lh))?;
459                    sign_psbt_schnorr(
460                        &self.inner,
461                        x_only_pubkey,
462                        Some(lh),
463                        &mut psbt.inputs[input_index],
464                        hash,
465                        hash_ty,
466                        secp,
467                    );
468                }
469            }
470
471            return Ok(());
472        }
473
474        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
475            return Ok(());
476        }
477
478        let (hash, hash_ty) = match self.ctx {
479            SignerContext::Segwitv0 => Segwitv0::sighash(psbt, input_index, ())?,
480            SignerContext::Legacy => Legacy::sighash(psbt, input_index, ())?,
481            _ => return Ok(()), // handled above
482        };
483        sign_psbt_ecdsa(
484            &self.inner,
485            pubkey,
486            &mut psbt.inputs[input_index],
487            hash,
488            hash_ty,
489            secp,
490            sign_options.allow_grinding,
491        );
492
493        Ok(())
494    }
495}
496
497fn sign_psbt_ecdsa(
498    secret_key: &secp256k1::SecretKey,
499    pubkey: PublicKey,
500    psbt_input: &mut psbt::Input,
501    hash: bitcoin::Sighash,
502    hash_ty: EcdsaSighashType,
503    secp: &SecpCtx,
504    allow_grinding: bool,
505) {
506    let msg = &Message::from_slice(&hash.into_inner()[..]).unwrap();
507    let sig = if allow_grinding {
508        secp.sign_ecdsa_low_r(msg, secret_key)
509    } else {
510        secp.sign_ecdsa(msg, secret_key)
511    };
512    secp.verify_ecdsa(msg, &sig, &pubkey.inner)
513        .expect("invalid or corrupted ecdsa signature");
514
515    let final_signature = ecdsa::EcdsaSig { sig, hash_ty };
516    psbt_input.partial_sigs.insert(pubkey, final_signature);
517}
518
519// Calling this with `leaf_hash` = `None` will sign for key-spend
520fn sign_psbt_schnorr(
521    secret_key: &secp256k1::SecretKey,
522    pubkey: XOnlyPublicKey,
523    leaf_hash: Option<taproot::TapLeafHash>,
524    psbt_input: &mut psbt::Input,
525    hash: taproot::TapSighashHash,
526    hash_ty: SchnorrSighashType,
527    secp: &SecpCtx,
528) {
529    use schnorr::TapTweak;
530
531    let keypair = secp256k1::KeyPair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
532    let keypair = match leaf_hash {
533        None => keypair
534            .tap_tweak(secp, psbt_input.tap_merkle_root)
535            .to_inner(),
536        Some(_) => keypair, // no tweak for script spend
537    };
538
539    let msg = &Message::from_slice(&hash.into_inner()[..]).unwrap();
540    let sig = secp.sign_schnorr(msg, &keypair);
541    secp.verify_schnorr(&sig, msg, &XOnlyPublicKey::from_keypair(&keypair).0)
542        .expect("invalid or corrupted schnorr signature");
543
544    let final_signature = schnorr::SchnorrSig { sig, hash_ty };
545
546    if let Some(lh) = leaf_hash {
547        psbt_input
548            .tap_script_sigs
549            .insert((pubkey, lh), final_signature);
550    } else {
551        psbt_input.tap_key_sig = Some(final_signature);
552    }
553}
554
555/// Defines the order in which signers are called
556///
557/// The default value is `100`. Signers with an ordering above that will be called later,
558/// and they will thus see the partial signatures added to the transaction once they get to sign
559/// themselves.
560#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
561pub struct SignerOrdering(pub usize);
562
563impl std::default::Default for SignerOrdering {
564    fn default() -> Self {
565        SignerOrdering(100)
566    }
567}
568
569#[derive(Debug, Clone)]
570struct SignersContainerKey {
571    id: SignerId,
572    ordering: SignerOrdering,
573}
574
575impl From<(SignerId, SignerOrdering)> for SignersContainerKey {
576    fn from(tuple: (SignerId, SignerOrdering)) -> Self {
577        SignersContainerKey {
578            id: tuple.0,
579            ordering: tuple.1,
580        }
581    }
582}
583
584/// Container for multiple signers
585#[derive(Debug, Default, Clone)]
586pub struct SignersContainer(BTreeMap<SignersContainerKey, Arc<dyn TransactionSigner>>);
587
588impl SignersContainer {
589    /// Create a map of public keys to secret keys
590    pub fn as_key_map(&self, secp: &SecpCtx) -> KeyMap {
591        self.0
592            .values()
593            .filter_map(|signer| signer.descriptor_secret_key())
594            .filter_map(|secret| secret.to_public(secp).ok().map(|public| (public, secret)))
595            .collect()
596    }
597
598    /// Build a new signer container from a [`KeyMap`]
599    ///
600    /// Also looks at the corresponding descriptor to determine the [`SignerContext`] to attach to
601    /// the signers
602    pub fn build(
603        keymap: KeyMap,
604        descriptor: &Descriptor<DescriptorPublicKey>,
605        secp: &SecpCtx,
606    ) -> SignersContainer {
607        let mut container = SignersContainer::new();
608
609        for (pubkey, secret) in keymap {
610            let ctx = match descriptor {
611                Descriptor::Tr(tr) => SignerContext::Tap {
612                    is_internal_key: tr.internal_key() == &pubkey,
613                },
614                _ if descriptor.is_witness() => SignerContext::Segwitv0,
615                _ => SignerContext::Legacy,
616            };
617
618            match secret {
619                DescriptorSecretKey::Single(private_key) => container.add_external(
620                    SignerId::from(
621                        private_key
622                            .key
623                            .public_key(secp)
624                            .to_pubkeyhash(SigType::Ecdsa),
625                    ),
626                    SignerOrdering::default(),
627                    Arc::new(SignerWrapper::new(private_key.key, ctx)),
628                ),
629                DescriptorSecretKey::XPrv(xprv) => container.add_external(
630                    SignerId::from(xprv.root_fingerprint(secp)),
631                    SignerOrdering::default(),
632                    Arc::new(SignerWrapper::new(xprv, ctx)),
633                ),
634            };
635        }
636
637        container
638    }
639}
640
641impl SignersContainer {
642    /// Default constructor
643    pub fn new() -> Self {
644        SignersContainer(Default::default())
645    }
646
647    /// Adds an external signer to the container for the specified id. Optionally returns the
648    /// signer that was previously in the container, if any
649    pub fn add_external(
650        &mut self,
651        id: SignerId,
652        ordering: SignerOrdering,
653        signer: Arc<dyn TransactionSigner>,
654    ) -> Option<Arc<dyn TransactionSigner>> {
655        self.0.insert((id, ordering).into(), signer)
656    }
657
658    /// Removes a signer from the container and returns it
659    pub fn remove(
660        &mut self,
661        id: SignerId,
662        ordering: SignerOrdering,
663    ) -> Option<Arc<dyn TransactionSigner>> {
664        self.0.remove(&(id, ordering).into())
665    }
666
667    /// Returns the list of identifiers of all the signers in the container
668    pub fn ids(&self) -> Vec<&SignerId> {
669        self.0
670            .keys()
671            .map(|SignersContainerKey { id, .. }| id)
672            .collect()
673    }
674
675    /// Returns the list of signers in the container, sorted by lowest to highest `ordering`
676    pub fn signers(&self) -> Vec<&Arc<dyn TransactionSigner>> {
677        self.0.values().collect()
678    }
679
680    /// Finds the signer with lowest ordering for a given id in the container.
681    pub fn find(&self, id: SignerId) -> Option<&Arc<dyn TransactionSigner>> {
682        self.0
683            .range((
684                Included(&(id.clone(), SignerOrdering(0)).into()),
685                Included(&(id.clone(), SignerOrdering(usize::MAX)).into()),
686            ))
687            .filter(|(k, _)| k.id == id)
688            .map(|(_, v)| v)
689            .next()
690    }
691}
692
693/// Options for a software signer
694///
695/// Adjust the behavior of our software signers and the way a transaction is finalized
696#[derive(Debug, Clone)]
697pub struct SignOptions {
698    /// Whether the signer should trust the `witness_utxo`, if the `non_witness_utxo` hasn't been
699    /// provided
700    ///
701    /// Defaults to `false` to mitigate the "SegWit bug" which chould trick the wallet into
702    /// paying a fee larger than expected.
703    ///
704    /// Some wallets, especially if relatively old, might not provide the `non_witness_utxo` for
705    /// SegWit transactions in the PSBT they generate: in those cases setting this to `true`
706    /// should correctly produce a signature, at the expense of an increased trust in the creator
707    /// of the PSBT.
708    ///
709    /// For more details see: <https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd>
710    pub trust_witness_utxo: bool,
711
712    /// Whether the wallet should assume a specific height has been reached when trying to finalize
713    /// a transaction
714    ///
715    /// The wallet will only "use" a timelock to satisfy the spending policy of an input if the
716    /// timelock height has already been reached. This option allows overriding the "current height" to let the
717    /// wallet use timelocks in the future to spend a coin.
718    pub assume_height: Option<u32>,
719
720    /// Whether the signer should use the `sighash_type` set in the PSBT when signing, no matter
721    /// what its value is
722    ///
723    /// Defaults to `false` which will only allow signing using `SIGHASH_ALL`.
724    pub allow_all_sighashes: bool,
725
726    /// Whether to remove partial signatures from the PSBT inputs while finalizing PSBT.
727    ///
728    /// Defaults to `true` which will remove partial signatures during finalization.
729    pub remove_partial_sigs: bool,
730
731    /// Whether to try finalizing the PSBT after the inputs are signed.
732    ///
733    /// Defaults to `true` which will try finalizing PSBT after inputs are signed.
734    pub try_finalize: bool,
735
736    /// Specifies which Taproot script-spend leaves we should sign for. This option is
737    /// ignored if we're signing a non-taproot PSBT.
738    ///
739    /// Defaults to All, i.e., the wallet will sign all the leaves it has a key for.
740    pub tap_leaves_options: TapLeavesOptions,
741
742    /// Whether we should try to sign a taproot transaction with the taproot internal key
743    /// or not. This option is ignored if we're signing a non-taproot PSBT.
744    ///
745    /// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
746    pub sign_with_tap_internal_key: bool,
747
748    /// Whether we should grind ECDSA signature to ensure signing with low r
749    /// or not.
750    /// Defaults to `true`, i.e., we always grind ECDSA signature to sign with low r.
751    pub allow_grinding: bool,
752}
753
754/// Customize which taproot script-path leaves the signer should sign.
755#[derive(Debug, Clone, PartialEq, Eq)]
756pub enum TapLeavesOptions {
757    /// The signer will sign all the leaves it has a key for.
758    All,
759    /// The signer won't sign leaves other than the ones specified. Note that it could still ignore
760    /// some of the specified leaves, if it doesn't have the right key to sign them.
761    Include(Vec<taproot::TapLeafHash>),
762    /// The signer won't sign the specified leaves.
763    Exclude(Vec<taproot::TapLeafHash>),
764    /// The signer won't sign any leaf.
765    None,
766}
767
768impl Default for TapLeavesOptions {
769    fn default() -> Self {
770        TapLeavesOptions::All
771    }
772}
773
774#[allow(clippy::derivable_impls)]
775impl Default for SignOptions {
776    fn default() -> Self {
777        SignOptions {
778            trust_witness_utxo: false,
779            assume_height: None,
780            allow_all_sighashes: false,
781            remove_partial_sigs: true,
782            try_finalize: true,
783            tap_leaves_options: TapLeavesOptions::default(),
784            sign_with_tap_internal_key: true,
785            allow_grinding: true,
786        }
787    }
788}
789
790pub(crate) trait ComputeSighash {
791    type Extra;
792    type Sighash;
793    type SighashType;
794
795    fn sighash(
796        psbt: &psbt::PartiallySignedTransaction,
797        input_index: usize,
798        extra: Self::Extra,
799    ) -> Result<(Self::Sighash, Self::SighashType), SignerError>;
800}
801
802impl ComputeSighash for Legacy {
803    type Extra = ();
804    type Sighash = bitcoin::Sighash;
805    type SighashType = EcdsaSighashType;
806
807    fn sighash(
808        psbt: &psbt::PartiallySignedTransaction,
809        input_index: usize,
810        _extra: (),
811    ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
812        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
813            return Err(SignerError::InputIndexOutOfRange);
814        }
815
816        let psbt_input = &psbt.inputs[input_index];
817        let tx_input = &psbt.unsigned_tx.input[input_index];
818
819        let sighash = psbt_input
820            .sighash_type
821            .unwrap_or_else(|| EcdsaSighashType::All.into())
822            .ecdsa_hash_ty()
823            .map_err(|_| SignerError::InvalidSighash)?;
824        let script = match psbt_input.redeem_script {
825            Some(ref redeem_script) => redeem_script.clone(),
826            None => {
827                let non_witness_utxo = psbt_input
828                    .non_witness_utxo
829                    .as_ref()
830                    .ok_or(SignerError::MissingNonWitnessUtxo)?;
831                let prev_out = non_witness_utxo
832                    .output
833                    .get(tx_input.previous_output.vout as usize)
834                    .ok_or(SignerError::InvalidNonWitnessUtxo)?;
835
836                prev_out.script_pubkey.clone()
837            }
838        };
839
840        Ok((
841            sighash::SighashCache::new(&psbt.unsigned_tx).legacy_signature_hash(
842                input_index,
843                &script,
844                sighash.to_u32(),
845            )?,
846            sighash,
847        ))
848    }
849}
850
851fn p2wpkh_script_code(script: &Script) -> Script {
852    ScriptBuilder::new()
853        .push_opcode(opcodes::all::OP_DUP)
854        .push_opcode(opcodes::all::OP_HASH160)
855        .push_slice(&script[2..])
856        .push_opcode(opcodes::all::OP_EQUALVERIFY)
857        .push_opcode(opcodes::all::OP_CHECKSIG)
858        .into_script()
859}
860
861impl ComputeSighash for Segwitv0 {
862    type Extra = ();
863    type Sighash = bitcoin::Sighash;
864    type SighashType = EcdsaSighashType;
865
866    fn sighash(
867        psbt: &psbt::PartiallySignedTransaction,
868        input_index: usize,
869        _extra: (),
870    ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
871        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
872            return Err(SignerError::InputIndexOutOfRange);
873        }
874
875        let psbt_input = &psbt.inputs[input_index];
876        let tx_input = &psbt.unsigned_tx.input[input_index];
877
878        let sighash = psbt_input
879            .sighash_type
880            .unwrap_or_else(|| EcdsaSighashType::All.into())
881            .ecdsa_hash_ty()
882            .map_err(|_| SignerError::InvalidSighash)?;
883
884        // Always try first with the non-witness utxo
885        let utxo = if let Some(prev_tx) = &psbt_input.non_witness_utxo {
886            // Check the provided prev-tx
887            if prev_tx.txid() != tx_input.previous_output.txid {
888                return Err(SignerError::InvalidNonWitnessUtxo);
889            }
890
891            // The output should be present, if it's missing the `non_witness_utxo` is invalid
892            prev_tx
893                .output
894                .get(tx_input.previous_output.vout as usize)
895                .ok_or(SignerError::InvalidNonWitnessUtxo)?
896        } else if let Some(witness_utxo) = &psbt_input.witness_utxo {
897            // Fallback to the witness_utxo. If we aren't allowed to use it, signing should fail
898            // before we get to this point
899            witness_utxo
900        } else {
901            // Nothing has been provided
902            return Err(SignerError::MissingNonWitnessUtxo);
903        };
904        let value = utxo.value;
905
906        let script = match psbt_input.witness_script {
907            Some(ref witness_script) => witness_script.clone(),
908            None => {
909                if utxo.script_pubkey.is_v0_p2wpkh() {
910                    p2wpkh_script_code(&utxo.script_pubkey)
911                } else if psbt_input
912                    .redeem_script
913                    .as_ref()
914                    .map(Script::is_v0_p2wpkh)
915                    .unwrap_or(false)
916                {
917                    p2wpkh_script_code(psbt_input.redeem_script.as_ref().unwrap())
918                } else {
919                    return Err(SignerError::MissingWitnessScript);
920                }
921            }
922        };
923
924        Ok((
925            sighash::SighashCache::new(&psbt.unsigned_tx).segwit_signature_hash(
926                input_index,
927                &script,
928                value,
929                sighash,
930            )?,
931            sighash,
932        ))
933    }
934}
935
936impl ComputeSighash for Tap {
937    type Extra = Option<taproot::TapLeafHash>;
938    type Sighash = taproot::TapSighashHash;
939    type SighashType = SchnorrSighashType;
940
941    fn sighash(
942        psbt: &psbt::PartiallySignedTransaction,
943        input_index: usize,
944        extra: Self::Extra,
945    ) -> Result<(Self::Sighash, SchnorrSighashType), SignerError> {
946        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
947            return Err(SignerError::InputIndexOutOfRange);
948        }
949
950        let psbt_input = &psbt.inputs[input_index];
951
952        let sighash_type = psbt_input
953            .sighash_type
954            .unwrap_or_else(|| SchnorrSighashType::Default.into())
955            .schnorr_hash_ty()
956            .map_err(|_| SignerError::InvalidSighash)?;
957        let witness_utxos = (0..psbt.inputs.len())
958            .map(|i| psbt.get_utxo_for(i))
959            .collect::<Vec<_>>();
960        let mut all_witness_utxos = vec![];
961
962        let mut cache = sighash::SighashCache::new(&psbt.unsigned_tx);
963        let is_anyone_can_pay = psbt::PsbtSighashType::from(sighash_type).to_u32() & 0x80 != 0;
964        let prevouts = if is_anyone_can_pay {
965            sighash::Prevouts::One(
966                input_index,
967                witness_utxos[input_index]
968                    .as_ref()
969                    .ok_or(SignerError::MissingWitnessUtxo)?,
970            )
971        } else if witness_utxos.iter().all(Option::is_some) {
972            all_witness_utxos.extend(witness_utxos.iter().filter_map(|x| x.as_ref()));
973            sighash::Prevouts::All(&all_witness_utxos)
974        } else {
975            return Err(SignerError::MissingWitnessUtxo);
976        };
977
978        // Assume no OP_CODESEPARATOR
979        let extra = extra.map(|leaf_hash| (leaf_hash, 0xFFFFFFFF));
980
981        Ok((
982            cache.taproot_signature_hash(input_index, &prevouts, None, extra, sighash_type)?,
983            sighash_type,
984        ))
985    }
986}
987
988impl PartialOrd for SignersContainerKey {
989    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
990        Some(self.cmp(other))
991    }
992}
993
994impl Ord for SignersContainerKey {
995    fn cmp(&self, other: &Self) -> Ordering {
996        self.ordering
997            .cmp(&other.ordering)
998            .then(self.id.cmp(&other.id))
999    }
1000}
1001
1002impl PartialEq for SignersContainerKey {
1003    fn eq(&self, other: &Self) -> bool {
1004        self.id == other.id && self.ordering == other.ordering
1005    }
1006}
1007
1008impl Eq for SignersContainerKey {}
1009
1010#[cfg(test)]
1011mod signers_container_tests {
1012    use super::*;
1013    use crate::descriptor;
1014    use crate::descriptor::IntoWalletDescriptor;
1015    use crate::keys::{DescriptorKey, IntoDescriptorKey};
1016    use assert_matches::assert_matches;
1017    use bitcoin::secp256k1::{All, Secp256k1};
1018    use bitcoin::util::bip32;
1019    use bitcoin::Network;
1020    use miniscript::ScriptContext;
1021    use std::str::FromStr;
1022
1023    fn is_equal(this: &Arc<dyn TransactionSigner>, that: &Arc<DummySigner>) -> bool {
1024        let secp = Secp256k1::new();
1025        this.id(&secp) == that.id(&secp)
1026    }
1027
1028    // Signers added with the same ordering (like `Ordering::default`) created from `KeyMap`
1029    // should be preserved and not overwritten.
1030    // This happens usually when a set of signers is created from a descriptor with private keys.
1031    #[test]
1032    fn signers_with_same_ordering() {
1033        let secp = Secp256k1::new();
1034
1035        let (prvkey1, _, _) = setup_keys(TPRV0_STR);
1036        let (prvkey2, _, _) = setup_keys(TPRV1_STR);
1037        let desc = descriptor!(sh(multi(2, prvkey1, prvkey2))).unwrap();
1038        let (wallet_desc, keymap) = desc
1039            .into_wallet_descriptor(&secp, Network::Testnet)
1040            .unwrap();
1041
1042        let signers = SignersContainer::build(keymap, &wallet_desc, &secp);
1043        assert_eq!(signers.ids().len(), 2);
1044
1045        let signers = signers.signers();
1046        assert_eq!(signers.len(), 2);
1047    }
1048
1049    #[test]
1050    fn signers_sorted_by_ordering() {
1051        let mut signers = SignersContainer::new();
1052        let signer1 = Arc::new(DummySigner { number: 1 });
1053        let signer2 = Arc::new(DummySigner { number: 2 });
1054        let signer3 = Arc::new(DummySigner { number: 3 });
1055
1056        // Mixed order insertions verifies we are not inserting at head or tail.
1057        signers.add_external(SignerId::Dummy(2), SignerOrdering(2), signer2.clone());
1058        signers.add_external(SignerId::Dummy(1), SignerOrdering(1), signer1.clone());
1059        signers.add_external(SignerId::Dummy(3), SignerOrdering(3), signer3.clone());
1060
1061        // Check that signers are sorted from lowest to highest ordering
1062        let signers = signers.signers();
1063
1064        assert!(is_equal(signers[0], &signer1));
1065        assert!(is_equal(signers[1], &signer2));
1066        assert!(is_equal(signers[2], &signer3));
1067    }
1068
1069    #[test]
1070    fn find_signer_by_id() {
1071        let mut signers = SignersContainer::new();
1072        let signer1 = Arc::new(DummySigner { number: 1 });
1073        let signer2 = Arc::new(DummySigner { number: 2 });
1074        let signer3 = Arc::new(DummySigner { number: 3 });
1075        let signer4 = Arc::new(DummySigner { number: 3 }); // Same ID as `signer3` but will use lower ordering.
1076
1077        let id1 = SignerId::Dummy(1);
1078        let id2 = SignerId::Dummy(2);
1079        let id3 = SignerId::Dummy(3);
1080        let id_nonexistent = SignerId::Dummy(999);
1081
1082        signers.add_external(id1.clone(), SignerOrdering(1), signer1.clone());
1083        signers.add_external(id2.clone(), SignerOrdering(2), signer2.clone());
1084        signers.add_external(id3.clone(), SignerOrdering(3), signer3.clone());
1085
1086        assert_matches!(signers.find(id1), Some(signer) if is_equal(signer, &signer1));
1087        assert_matches!(signers.find(id2), Some(signer) if is_equal(signer, &signer2));
1088        assert_matches!(signers.find(id3.clone()), Some(signer) if is_equal(signer, &signer3));
1089
1090        // The `signer4` has the same ID as `signer3` but lower ordering.
1091        // It should be found by `id3` instead of `signer3`.
1092        signers.add_external(id3.clone(), SignerOrdering(2), signer4.clone());
1093        assert_matches!(signers.find(id3), Some(signer) if is_equal(signer, &signer4));
1094
1095        // Can't find anything with ID that doesn't exist
1096        assert_matches!(signers.find(id_nonexistent), None);
1097    }
1098
1099    #[derive(Debug, Clone, Copy)]
1100    struct DummySigner {
1101        number: u64,
1102    }
1103
1104    impl SignerCommon for DummySigner {
1105        fn id(&self, _secp: &SecpCtx) -> SignerId {
1106            SignerId::Dummy(self.number)
1107        }
1108    }
1109
1110    impl TransactionSigner for DummySigner {
1111        fn sign_transaction(
1112            &self,
1113            _psbt: &mut psbt::PartiallySignedTransaction,
1114            _sign_options: &SignOptions,
1115            _secp: &SecpCtx,
1116        ) -> Result<(), SignerError> {
1117            Ok(())
1118        }
1119    }
1120
1121    const TPRV0_STR:&str = "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf";
1122    const TPRV1_STR:&str = "tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N";
1123
1124    const PATH: &str = "m/44'/1'/0'/0";
1125
1126    fn setup_keys<Ctx: ScriptContext>(
1127        tprv: &str,
1128    ) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) {
1129        let secp: Secp256k1<All> = Secp256k1::new();
1130        let path = bip32::DerivationPath::from_str(PATH).unwrap();
1131        let tprv = bip32::ExtendedPrivKey::from_str(tprv).unwrap();
1132        let tpub = bip32::ExtendedPubKey::from_priv(&secp, &tprv);
1133        let fingerprint = tprv.fingerprint(&secp);
1134        let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap();
1135        let pubkey = (tpub, path).into_descriptor_key().unwrap();
1136
1137        (prvkey, pubkey, fingerprint)
1138    }
1139}