@@ -166,6 +166,8 @@ pub enum SignerError {
166
166
/// [`TransactionSigner`], so that they can return their own custom errors, without having to
167
167
/// modify [`SignerError`] in BDK.
168
168
External ( String ) ,
169
+ /// PSBT sign error.
170
+ Psbt ( psbt:: SignError ) ,
169
171
}
170
172
171
173
impl From < sighash:: Error > for SignerError {
@@ -191,6 +193,7 @@ impl fmt::Display for SignerError {
191
193
Self :: SighashError ( err) => write ! ( f, "Error while computing the hash to sign: {}" , err) ,
192
194
Self :: MiniscriptPsbt ( err) => write ! ( f, "Miniscript PSBT error: {}" , err) ,
193
195
Self :: External ( err) => write ! ( f, "{}" , err) ,
196
+ Self :: Psbt ( err) => write ! ( f, "{}" , err) ,
194
197
}
195
198
}
196
199
}
@@ -453,92 +456,86 @@ impl InputSigner for SignerWrapper<PrivateKey> {
453
456
}
454
457
455
458
let pubkey = PublicKey :: from_private_key ( secp, self ) ;
456
- let x_only_pubkey = XOnlyPublicKey :: from ( pubkey. inner ) ;
457
-
458
- if let SignerContext :: Tap { is_internal_key } = self . ctx {
459
- if let Some ( psbt_internal_key) = psbt. inputs [ input_index] . tap_internal_key {
460
- if is_internal_key
461
- && psbt. inputs [ input_index] . tap_key_sig . is_none ( )
462
- && sign_options. sign_with_tap_internal_key
463
- && x_only_pubkey == psbt_internal_key
464
- {
465
- let ( hash, hash_ty) = compute_tap_sighash ( psbt, input_index, None ) ?;
466
- sign_psbt_schnorr (
467
- & self . inner ,
468
- x_only_pubkey,
469
- None ,
470
- & mut psbt. inputs [ input_index] ,
471
- hash,
472
- hash_ty,
473
- secp,
474
- ) ;
459
+
460
+ match self . ctx {
461
+ SignerContext :: Tap { is_internal_key } => {
462
+ let x_only_pubkey = XOnlyPublicKey :: from ( pubkey. inner ) ;
463
+
464
+ if let Some ( psbt_internal_key) = psbt. inputs [ input_index] . tap_internal_key {
465
+ if is_internal_key
466
+ && psbt. inputs [ input_index] . tap_key_sig . is_none ( )
467
+ && sign_options. sign_with_tap_internal_key
468
+ && x_only_pubkey == psbt_internal_key
469
+ {
470
+ let ( hash, hash_ty) = compute_tap_sighash ( psbt, input_index, None ) ?;
471
+ sign_psbt_schnorr (
472
+ & self . inner ,
473
+ x_only_pubkey,
474
+ None ,
475
+ & mut psbt. inputs [ input_index] ,
476
+ hash,
477
+ hash_ty,
478
+ secp,
479
+ ) ;
480
+ }
475
481
}
476
- }
477
482
478
- if let Some ( ( leaf_hashes, _) ) =
479
- psbt. inputs [ input_index] . tap_key_origins . get ( & x_only_pubkey)
480
- {
481
- let leaf_hashes = leaf_hashes
482
- . iter ( )
483
- . filter ( |lh| {
484
- // Removing the leaves we shouldn't sign for
485
- let should_sign = match & sign_options. tap_leaves_options {
486
- TapLeavesOptions :: All => true ,
487
- TapLeavesOptions :: Include ( v) => v. contains ( lh) ,
488
- TapLeavesOptions :: Exclude ( v) => !v. contains ( lh) ,
489
- TapLeavesOptions :: None => false ,
490
- } ;
491
- // Filtering out the leaves without our key
492
- should_sign
493
- && !psbt. inputs [ input_index]
494
- . tap_script_sigs
495
- . contains_key ( & ( x_only_pubkey, * * lh) )
496
- } )
497
- . cloned ( )
498
- . collect :: < Vec < _ > > ( ) ;
499
- for lh in leaf_hashes {
500
- let ( hash, hash_ty) = compute_tap_sighash ( psbt, input_index, Some ( lh) ) ?;
501
- sign_psbt_schnorr (
502
- & self . inner ,
503
- x_only_pubkey,
504
- Some ( lh) ,
505
- & mut psbt. inputs [ input_index] ,
506
- hash,
507
- hash_ty,
508
- secp,
509
- ) ;
483
+ if let Some ( ( leaf_hashes, _) ) =
484
+ psbt. inputs [ input_index] . tap_key_origins . get ( & x_only_pubkey)
485
+ {
486
+ let leaf_hashes = leaf_hashes
487
+ . iter ( )
488
+ . filter ( |lh| {
489
+ // Removing the leaves we shouldn't sign for
490
+ let should_sign = match & sign_options. tap_leaves_options {
491
+ TapLeavesOptions :: All => true ,
492
+ TapLeavesOptions :: Include ( v) => v. contains ( lh) ,
493
+ TapLeavesOptions :: Exclude ( v) => !v. contains ( lh) ,
494
+ TapLeavesOptions :: None => false ,
495
+ } ;
496
+ // Filtering out the leaves without our key
497
+ should_sign
498
+ && !psbt. inputs [ input_index]
499
+ . tap_script_sigs
500
+ . contains_key ( & ( x_only_pubkey, * * lh) )
501
+ } )
502
+ . cloned ( )
503
+ . collect :: < Vec < _ > > ( ) ;
504
+ for lh in leaf_hashes {
505
+ let ( hash, hash_ty) = compute_tap_sighash ( psbt, input_index, Some ( lh) ) ?;
506
+ sign_psbt_schnorr (
507
+ & self . inner ,
508
+ x_only_pubkey,
509
+ Some ( lh) ,
510
+ & mut psbt. inputs [ input_index] ,
511
+ hash,
512
+ hash_ty,
513
+ secp,
514
+ ) ;
515
+ }
510
516
}
511
517
}
518
+ SignerContext :: Segwitv0 | SignerContext :: Legacy => {
519
+ if psbt. inputs [ input_index] . partial_sigs . contains_key ( & pubkey) {
520
+ return Ok ( ( ) ) ;
521
+ }
512
522
513
- return Ok ( ( ) ) ;
514
- }
515
-
516
- if psbt. inputs [ input_index] . partial_sigs . contains_key ( & pubkey) {
517
- return Ok ( ( ) ) ;
518
- }
519
-
520
- let ( hash, hash_ty) = match self . ctx {
521
- SignerContext :: Segwitv0 => {
522
- let ( h, t) = compute_segwitv0_sighash ( psbt, input_index) ?;
523
- let h = h. to_raw_hash ( ) ;
524
- ( h, t)
525
- }
526
- SignerContext :: Legacy => {
527
- let ( h, t) = compute_legacy_sighash ( psbt, input_index) ?;
528
- let h = h. to_raw_hash ( ) ;
529
- ( h, t)
523
+ let mut sighasher = sighash:: SighashCache :: new ( psbt. unsigned_tx . clone ( ) ) ;
524
+ let ( msg, hash_ty) = psbt
525
+ . sighash_ecdsa ( input_index, & mut sighasher)
526
+ . map_err ( SignerError :: Psbt ) ?;
527
+
528
+ sign_psbt_ecdsa (
529
+ & self . inner ,
530
+ pubkey,
531
+ & mut psbt. inputs [ input_index] ,
532
+ & msg,
533
+ hash_ty,
534
+ secp,
535
+ sign_options. allow_grinding ,
536
+ ) ;
530
537
}
531
- _ => return Ok ( ( ) ) , // handled above
532
- } ;
533
- sign_psbt_ecdsa (
534
- & self . inner ,
535
- pubkey,
536
- & mut psbt. inputs [ input_index] ,
537
- hash,
538
- hash_ty,
539
- secp,
540
- sign_options. allow_grinding ,
541
- ) ;
538
+ }
542
539
543
540
Ok ( ( ) )
544
541
}
@@ -548,12 +545,11 @@ fn sign_psbt_ecdsa(
548
545
secret_key : & secp256k1:: SecretKey ,
549
546
pubkey : PublicKey ,
550
547
psbt_input : & mut psbt:: Input ,
551
- hash : impl bitcoin :: hashes :: Hash + bitcoin :: secp256k1 :: ThirtyTwoByteHash ,
548
+ msg : & Message ,
552
549
hash_ty : EcdsaSighashType ,
553
550
secp : & SecpCtx ,
554
551
allow_grinding : bool ,
555
552
) {
556
- let msg = & Message :: from ( hash) ;
557
553
let sig = if allow_grinding {
558
554
secp. sign_ecdsa_low_r ( msg, secret_key)
559
555
} else {
@@ -845,119 +841,6 @@ impl Default for SignOptions {
845
841
}
846
842
}
847
843
848
- /// Computes the legacy sighash.
849
- fn compute_legacy_sighash (
850
- psbt : & Psbt ,
851
- input_index : usize ,
852
- ) -> Result < ( sighash:: LegacySighash , EcdsaSighashType ) , SignerError > {
853
- if input_index >= psbt. inputs . len ( ) || input_index >= psbt. unsigned_tx . input . len ( ) {
854
- return Err ( SignerError :: InputIndexOutOfRange ) ;
855
- }
856
-
857
- let psbt_input = & psbt. inputs [ input_index] ;
858
- let tx_input = & psbt. unsigned_tx . input [ input_index] ;
859
-
860
- let sighash = psbt_input
861
- . sighash_type
862
- . unwrap_or_else ( || EcdsaSighashType :: All . into ( ) )
863
- . ecdsa_hash_ty ( )
864
- . map_err ( |_| SignerError :: InvalidSighash ) ?;
865
- let script = match psbt_input. redeem_script {
866
- Some ( ref redeem_script) => redeem_script. clone ( ) ,
867
- None => {
868
- let non_witness_utxo = psbt_input
869
- . non_witness_utxo
870
- . as_ref ( )
871
- . ok_or ( SignerError :: MissingNonWitnessUtxo ) ?;
872
- let prev_out = non_witness_utxo
873
- . output
874
- . get ( tx_input. previous_output . vout as usize )
875
- . ok_or ( SignerError :: InvalidNonWitnessUtxo ) ?;
876
-
877
- prev_out. script_pubkey . clone ( )
878
- }
879
- } ;
880
-
881
- Ok ( (
882
- sighash:: SighashCache :: new ( & psbt. unsigned_tx ) . legacy_signature_hash (
883
- input_index,
884
- & script,
885
- sighash. to_u32 ( ) ,
886
- ) ?,
887
- sighash,
888
- ) )
889
- }
890
-
891
- /// Computes the segwitv0 sighash.
892
- fn compute_segwitv0_sighash (
893
- psbt : & Psbt ,
894
- input_index : usize ,
895
- ) -> Result < ( sighash:: SegwitV0Sighash , EcdsaSighashType ) , SignerError > {
896
- if input_index >= psbt. inputs . len ( ) || input_index >= psbt. unsigned_tx . input . len ( ) {
897
- return Err ( SignerError :: InputIndexOutOfRange ) ;
898
- }
899
-
900
- let psbt_input = & psbt. inputs [ input_index] ;
901
- let tx_input = & psbt. unsigned_tx . input [ input_index] ;
902
-
903
- let sighash_type = psbt_input
904
- . sighash_type
905
- . unwrap_or_else ( || EcdsaSighashType :: All . into ( ) )
906
- . ecdsa_hash_ty ( )
907
- . map_err ( |_| SignerError :: InvalidSighash ) ?;
908
-
909
- // Always try first with the non-witness utxo
910
- let utxo = if let Some ( prev_tx) = & psbt_input. non_witness_utxo {
911
- // Check the provided prev-tx
912
- if prev_tx. txid ( ) != tx_input. previous_output . txid {
913
- return Err ( SignerError :: InvalidNonWitnessUtxo ) ;
914
- }
915
-
916
- // The output should be present, if it's missing the `non_witness_utxo` is invalid
917
- prev_tx
918
- . output
919
- . get ( tx_input. previous_output . vout as usize )
920
- . ok_or ( SignerError :: InvalidNonWitnessUtxo ) ?
921
- } else if let Some ( witness_utxo) = & psbt_input. witness_utxo {
922
- // Fallback to the witness_utxo. If we aren't allowed to use it, signing should fail
923
- // before we get to this point
924
- witness_utxo
925
- } else {
926
- // Nothing has been provided
927
- return Err ( SignerError :: MissingNonWitnessUtxo ) ;
928
- } ;
929
- let value = utxo. value ;
930
-
931
- let mut sighasher = sighash:: SighashCache :: new ( & psbt. unsigned_tx ) ;
932
-
933
- let sighash = match psbt_input. witness_script {
934
- Some ( ref witness_script) => {
935
- sighasher. p2wsh_signature_hash ( input_index, witness_script, value, sighash_type) ?
936
- }
937
- None => {
938
- if utxo. script_pubkey . is_p2wpkh ( ) {
939
- sighasher. p2wpkh_signature_hash (
940
- input_index,
941
- & utxo. script_pubkey ,
942
- value,
943
- sighash_type,
944
- ) ?
945
- } else if psbt_input
946
- . redeem_script
947
- . as_ref ( )
948
- . map ( |s| s. is_p2wpkh ( ) )
949
- . unwrap_or ( false )
950
- {
951
- let script_pubkey = psbt_input. redeem_script . as_ref ( ) . unwrap ( ) ;
952
- sighasher. p2wpkh_signature_hash ( input_index, script_pubkey, value, sighash_type) ?
953
- } else {
954
- return Err ( SignerError :: MissingWitnessScript ) ;
955
- }
956
- }
957
- } ;
958
- Ok ( ( sighash, sighash_type) )
959
- }
960
-
961
844
/// Computes the taproot sighash.
962
845
fn compute_tap_sighash (
963
846
psbt : & Psbt ,
0 commit comments