@@ -22,13 +22,13 @@ use core::{cmp, fmt, i64, mem};
22
22
23
23
use bitcoin:: hashes:: hash160;
24
24
use bitcoin:: secp256k1:: XOnlyPublicKey ;
25
- use bitcoin:: util:: taproot:: { ControlBlock , LeafVersion , TapLeafHash } ;
25
+ use bitcoin:: util:: taproot:: { ControlBlock , LeafVersion , TapBranchHash , TapLeafHash } ;
26
26
use bitcoin:: { LockTime , PackedLockTime , Script , Sequence } ;
27
27
use sync:: Arc ;
28
28
29
29
use super :: context:: SigType ;
30
30
use crate :: descriptor:: DescriptorType ;
31
- use crate :: plan:: { AssetProvider , Plan , RequiredPreimage , RequiredSig } ;
31
+ use crate :: plan:: { AssetProvider , Plan } ;
32
32
use crate :: prelude:: * ;
33
33
use crate :: util:: witness_size;
34
34
use crate :: {
@@ -530,6 +530,21 @@ impl_tuple_satisfier!(A, B, C, D, E, F);
530
530
impl_tuple_satisfier ! ( A , B , C , D , E , F , G ) ;
531
531
impl_tuple_satisfier ! ( A , B , C , D , E , F , G , H ) ;
532
532
533
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
534
+ /// Type of schnorr signature to produce
535
+ pub enum SchnorrSigType {
536
+ /// Key spend signature
537
+ KeySpend {
538
+ /// Merkle root to tweak the key, if present
539
+ merkle_root : Option < TapBranchHash > ,
540
+ } ,
541
+ /// Script spend signature
542
+ ScriptSpend {
543
+ /// Leaf hash of the script
544
+ leaf_hash : TapLeafHash ,
545
+ } ,
546
+ }
547
+
533
548
#[ derive( Debug , Clone , PartialEq , Eq ) ]
534
549
/// Placeholder for some data in a [`WitnessTemplate`]
535
550
pub enum Placeholder < Pk : MiniscriptKey > {
@@ -541,10 +556,10 @@ pub enum Placeholder<Pk: MiniscriptKey> {
541
556
EcdsaSigPk ( Pk ) ,
542
557
/// ECDSA signature given the pubkey hash
543
558
EcdsaSigHash ( hash160:: Hash ) ,
544
- /// Schnorr signature
545
- SchnorrSig ( Pk , Option < TapLeafHash > ) ,
546
- /// Schnorr signature given the pubkey hash and the leaf hash
547
- SchnorrSigHash ( hash160:: Hash , TapLeafHash ) ,
559
+ /// Schnorr signature and its size
560
+ SchnorrSig ( Pk , SchnorrSigType , usize ) ,
561
+ /// Schnorr signature given the pubkey hash and the leaf hash, plus its size
562
+ SchnorrSigHash ( hash160:: Hash , TapLeafHash , usize ) ,
548
563
/// SHA-256 preimage
549
564
Sha256Preimage ( Pk :: Sha256 ) ,
550
565
/// HASH256 preimage
@@ -575,12 +590,16 @@ impl<Pk: MiniscriptKey> fmt::Display for Placeholder<Pk> {
575
590
PubkeyHash ( pkh, size) => write ! ( f, "PubkeyHash(pkh: {}, size: {})" , pkh, size) ,
576
591
EcdsaSigPk ( pk) => write ! ( f, "EcdsaSigPk(pk: {})" , pk) ,
577
592
EcdsaSigHash ( hash) => write ! ( f, "EcdsaSigHash(hash: {})" , hash) ,
578
- SchnorrSig ( pk, tap_leaf_hash) => write ! (
593
+ SchnorrSig ( pk, tap_leaf_hash, size ) => write ! (
579
594
f,
580
- "SchnorrSig(pk: {}, tap_leaf_hash: {:?})" ,
581
- pk, tap_leaf_hash
595
+ "SchnorrSig(pk: {}, tap_leaf_hash: {:?}, size: {})" ,
596
+ pk, tap_leaf_hash, size
597
+ ) ,
598
+ SchnorrSigHash ( pkh, lh, size) => write ! (
599
+ f,
600
+ "SchnorrSigHash(pkh: {}, leaf_hash: {}, size: {})" ,
601
+ pkh, lh, size
582
602
) ,
583
- SchnorrSigHash ( pkh, lh) => write ! ( f, "SchnorrSigHash(pkh: {}, leaf_hash: {})" , pkh, lh) ,
584
603
Sha256Preimage ( hash) => write ! ( f, "Sha256Preimage(hash: {})" , hash) ,
585
604
Hash256Preimage ( hash) => write ! ( f, "Hash256Preimage(hash: {})" , hash) ,
586
605
Ripemd160Preimage ( hash) => write ! ( f, "Ripemd160Preimage(hash: {})" , hash) ,
@@ -612,8 +631,8 @@ impl<Pk: MiniscriptKey + ToPublicKey> Placeholder<Pk> {
612
631
. or ( sat. lookup_raw_pkh_ecdsa_sig ( pkh) . map ( |( p, _) | p) )
613
632
. map ( |pk| {
614
633
let pk = pk. to_bytes ( ) ;
615
- // We have to add a 1-byte OP_PUSH
616
- debug_assert ! ( 1 + pk. len( ) == * size) ;
634
+ // Need to add +1 because the size in the placeholder also accounts for the OP_PUSH
635
+ debug_assert ! ( pk. len( ) + 1 == * size) ;
617
636
pk
618
637
} ) ,
619
638
Placeholder :: Hash256Preimage ( h) => sat. lookup_hash256 ( h) . map ( |p| p. to_vec ( ) ) ,
@@ -624,13 +643,26 @@ impl<Pk: MiniscriptKey + ToPublicKey> Placeholder<Pk> {
624
643
Placeholder :: EcdsaSigHash ( pkh) => {
625
644
sat. lookup_raw_pkh_ecdsa_sig ( pkh) . map ( |( _, s) | s. to_vec ( ) )
626
645
}
627
- Placeholder :: SchnorrSig ( pk, Some ( leaf_hash) ) => sat
646
+ Placeholder :: SchnorrSig ( pk, SchnorrSigType :: ScriptSpend { leaf_hash } , size ) => sat
628
647
. lookup_tap_leaf_script_sig ( pk, leaf_hash)
629
- . map ( |s| s. to_vec ( ) ) ,
630
- Placeholder :: SchnorrSigHash ( pkh, lh) => sat
648
+ . map ( |s| s. to_vec ( ) )
649
+ . map ( |s| {
650
+ debug_assert ! ( s. len( ) == * size) ;
651
+ s
652
+ } ) ,
653
+ Placeholder :: SchnorrSigHash ( pkh, lh, size) => sat
631
654
. lookup_raw_pkh_tap_leaf_script_sig ( & ( * pkh, * lh) )
632
- . map ( |( _, s) | s. to_vec ( ) ) ,
633
- Placeholder :: SchnorrSig ( _, _) => sat. lookup_tap_key_spend_sig ( ) . map ( |s| s. to_vec ( ) ) ,
655
+ . map ( |( _, s) | s. to_vec ( ) )
656
+ . map ( |s| {
657
+ debug_assert ! ( s. len( ) == * size) ;
658
+ s
659
+ } ) ,
660
+ Placeholder :: SchnorrSig ( _, _, size) => {
661
+ sat. lookup_tap_key_spend_sig ( ) . map ( |s| s. to_vec ( ) ) . map ( |s| {
662
+ debug_assert ! ( s. len( ) == * size) ;
663
+ s
664
+ } )
665
+ }
634
666
Placeholder :: HashDissatisfaction => Some ( vec ! [ 0 ; 32 ] ) ,
635
667
Placeholder :: PushZero => Some ( vec ! [ ] ) ,
636
668
Placeholder :: PushOne => Some ( vec ! [ 1 ] ) ,
@@ -653,29 +685,6 @@ pub enum Witness<T> {
653
685
Impossible ,
654
686
}
655
687
656
- /// Enum for partially satisfied witness templates
657
- pub enum PartialSatisfaction < Pk : MiniscriptKey > {
658
- /// Placeholder item (not yet satisfied)
659
- Placeholder ( Placeholder < Pk > ) ,
660
- /// Actual data
661
- Data ( Vec < u8 > ) ,
662
- }
663
-
664
- impl < Pk : MiniscriptKey > PartialSatisfaction < Pk > {
665
- /// Whether the item is a placeholder
666
- pub fn is_placeholder ( & self ) -> bool {
667
- match & self {
668
- PartialSatisfaction :: Placeholder ( _) => true ,
669
- _ => false ,
670
- }
671
- }
672
-
673
- /// Whether the item is data
674
- pub fn is_data ( & self ) -> bool {
675
- !self . is_placeholder ( )
676
- }
677
- }
678
-
679
688
/// Template of a witness being constructed interactively
680
689
///
681
690
/// The generic `I` type determines the available API:
@@ -710,91 +719,6 @@ impl<Pk: MiniscriptKey + ToPublicKey> WitnessTemplate<Placeholder<Pk>> {
710
719
711
720
Some ( stack)
712
721
}
713
-
714
- /// Being an interactive satisfaction session
715
- pub fn interactive_satisfaction ( self ) -> WitnessTemplate < PartialSatisfaction < Pk > > {
716
- WitnessTemplate {
717
- stack : self
718
- . stack
719
- . into_iter ( )
720
- . map ( PartialSatisfaction :: Placeholder )
721
- . collect ( ) ,
722
- }
723
- }
724
-
725
- /// Returns the list of required signatures
726
- pub fn required_signatures ( & self ) -> Vec < RequiredSig < ' _ , Pk > > {
727
- self . stack
728
- . iter ( )
729
- . filter_map ( |item| match item {
730
- Placeholder :: EcdsaSigPk ( pk) => Some ( RequiredSig :: Ecdsa ( pk) ) ,
731
- Placeholder :: SchnorrSig ( pk, None ) => Some ( RequiredSig :: SchnorrTapKey ( pk) ) ,
732
- Placeholder :: SchnorrSig ( pk, Some ( lh) ) => {
733
- Some ( RequiredSig :: SchnorrTapScript ( pk, lh) )
734
- }
735
- _ => None ,
736
- } )
737
- . collect ( )
738
- }
739
-
740
- /// Returns the list of required preimages
741
- pub fn required_preimages ( & self ) -> Vec < RequiredPreimage < ' _ , Pk > > {
742
- self . stack
743
- . iter ( )
744
- . filter_map ( |item| match item {
745
- Placeholder :: Sha256Preimage ( h) => Some ( RequiredPreimage :: Sha256 ( h) ) ,
746
- Placeholder :: Hash256Preimage ( h) => Some ( RequiredPreimage :: Hash256 ( h) ) ,
747
- Placeholder :: Ripemd160Preimage ( h) => Some ( RequiredPreimage :: Ripemd160 ( h) ) ,
748
- Placeholder :: Hash160Preimage ( h) => Some ( RequiredPreimage :: Hash160 ( h) ) ,
749
- _ => None ,
750
- } )
751
- . collect ( )
752
- }
753
- }
754
-
755
- impl < Pk : MiniscriptKey + ToPublicKey > WitnessTemplate < PartialSatisfaction < Pk > > {
756
- /// Apply the items needed from a satisfier
757
- ///
758
- /// Returns the completed witness if all the placeholders have been filled, or `Err` with itself a list of missing
759
- /// items otherwise.
760
- pub fn apply < Sat : Satisfier < Pk > > (
761
- self ,
762
- stfr : & Sat ,
763
- ) -> Result < Vec < Vec < u8 > > , ( Self , Vec < Placeholder < Pk > > ) > {
764
- let mut unsatisfied = vec ! [ ] ;
765
-
766
- let stack = self
767
- . stack
768
- . into_iter ( )
769
- . map ( |ps| {
770
- let placeholder = match & ps {
771
- PartialSatisfaction :: Placeholder ( p) => p,
772
- PartialSatisfaction :: Data ( _) => return ps,
773
- } ;
774
-
775
- if let Some ( data) = placeholder. satisfy_self ( stfr) {
776
- return PartialSatisfaction :: Data ( data) ;
777
- }
778
-
779
- unsatisfied. push ( placeholder. clone ( ) ) ;
780
- ps
781
- } )
782
- . collect :: < Vec < _ > > ( ) ;
783
-
784
- if unsatisfied. is_empty ( ) {
785
- Ok ( stack
786
- . into_iter ( )
787
- . map ( |ps| match ps {
788
- PartialSatisfaction :: Data ( d) => d,
789
- PartialSatisfaction :: Placeholder ( _) => {
790
- unreachable ! ( "there shouldn't be any placeholder left" )
791
- }
792
- } )
793
- . collect ( ) )
794
- } else {
795
- Err ( ( WitnessTemplate { stack } , unsatisfied) )
796
- }
797
- }
798
722
}
799
723
800
724
impl < Pk : MiniscriptKey > PartialOrd for Witness < Placeholder < Pk > > {
@@ -838,10 +762,13 @@ impl<Pk: MiniscriptKey + ToPublicKey> Witness<Placeholder<Pk>> {
838
762
}
839
763
}
840
764
super :: context:: SigType :: Schnorr => {
841
- if sat. lookup_tap_leaf_script_sig ( pk, leaf_hash) {
765
+ if let Some ( size ) = sat. lookup_tap_leaf_script_sig ( pk, leaf_hash) {
842
766
Witness :: Stack ( vec ! [ Placeholder :: SchnorrSig (
843
767
pk. clone( ) ,
844
- Some ( leaf_hash. clone( ) ) ,
768
+ SchnorrSigType :: ScriptSpend {
769
+ leaf_hash: * leaf_hash,
770
+ } ,
771
+ size,
845
772
) ] )
846
773
} else {
847
774
// Signatures cannot be forged
@@ -885,11 +812,11 @@ impl<Pk: MiniscriptKey + ToPublicKey> Witness<Placeholder<Pk>> {
885
812
None => Witness :: Impossible ,
886
813
} ,
887
814
SigType :: Schnorr => match sat. lookup_raw_pkh_tap_leaf_script_sig ( & ( * pkh, * leaf_hash) ) {
888
- true => Witness :: Stack ( vec ! [
889
- Placeholder :: SchnorrSigHash ( pkh. clone( ) , * leaf_hash) ,
815
+ Some ( size ) => Witness :: Stack ( vec ! [
816
+ Placeholder :: SchnorrSigHash ( pkh. clone( ) , * leaf_hash, size ) ,
890
817
Placeholder :: PubkeyHash ( pkh. clone( ) , 32 ) ,
891
818
] ) ,
892
- false => Witness :: Impossible ,
819
+ None => Witness :: Impossible ,
893
820
} ,
894
821
}
895
822
}
0 commit comments