1use 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#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq, Hash)]
111pub enum SignerId {
112 PkHash(hash160::Hash),
114 Fingerprint(Fingerprint),
116 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#[derive(Debug, PartialEq, Eq, Clone)]
134pub enum SignerError {
135 MissingKey,
137 InvalidKey,
139 UserCanceled,
141 InputIndexOutOfRange,
143 MissingNonWitnessUtxo,
145 InvalidNonWitnessUtxo,
147 MissingWitnessUtxo,
149 MissingWitnessScript,
151 MissingHdKeypath,
153 NonStandardSighash,
159 InvalidSighash,
161 SighashError(sighash::Error),
163 #[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum SignerContext {
209 Legacy,
211 Segwitv0,
213 Tap {
215 is_internal_key: bool,
217 },
218}
219
220#[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 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
242pub trait SignerCommon: fmt::Debug + Send + Sync {
244 fn id(&self, secp: &SecpCtx) -> SignerId;
249
250 fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
256 None
257 }
258}
259
260pub trait InputSigner: SignerCommon {
266 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
276pub trait TransactionSigner: SignerCommon {
281 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 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 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 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(()), };
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
519fn 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, };
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#[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#[derive(Debug, Default, Clone)]
586pub struct SignersContainer(BTreeMap<SignersContainerKey, Arc<dyn TransactionSigner>>);
587
588impl SignersContainer {
589 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 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 pub fn new() -> Self {
644 SignersContainer(Default::default())
645 }
646
647 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 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 pub fn ids(&self) -> Vec<&SignerId> {
669 self.0
670 .keys()
671 .map(|SignersContainerKey { id, .. }| id)
672 .collect()
673 }
674
675 pub fn signers(&self) -> Vec<&Arc<dyn TransactionSigner>> {
677 self.0.values().collect()
678 }
679
680 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#[derive(Debug, Clone)]
697pub struct SignOptions {
698 pub trust_witness_utxo: bool,
711
712 pub assume_height: Option<u32>,
719
720 pub allow_all_sighashes: bool,
725
726 pub remove_partial_sigs: bool,
730
731 pub try_finalize: bool,
735
736 pub tap_leaves_options: TapLeavesOptions,
741
742 pub sign_with_tap_internal_key: bool,
747
748 pub allow_grinding: bool,
752}
753
754#[derive(Debug, Clone, PartialEq, Eq)]
756pub enum TapLeavesOptions {
757 All,
759 Include(Vec<taproot::TapLeafHash>),
762 Exclude(Vec<taproot::TapLeafHash>),
764 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 let utxo = if let Some(prev_tx) = &psbt_input.non_witness_utxo {
886 if prev_tx.txid() != tx_input.previous_output.txid {
888 return Err(SignerError::InvalidNonWitnessUtxo);
889 }
890
891 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 witness_utxo
900 } else {
901 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 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 #[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 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 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 }); 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 signers.add_external(id3.clone(), SignerOrdering(2), signer4.clone());
1093 assert_matches!(signers.find(id3), Some(signer) if is_equal(signer, &signer4));
1094
1095 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}