@@ -22,13 +22,13 @@ use core::{cmp, fmt, i64, mem};
2222
2323use bitcoin:: hashes:: hash160;
2424use bitcoin:: secp256k1:: XOnlyPublicKey ;
25- use bitcoin:: util:: taproot:: { ControlBlock , LeafVersion , TapLeafHash } ;
25+ use bitcoin:: util:: taproot:: { ControlBlock , LeafVersion , TapBranchHash , TapLeafHash } ;
2626use bitcoin:: { LockTime , PackedLockTime , Script , Sequence } ;
2727use sync:: Arc ;
2828
2929use super :: context:: SigType ;
3030use crate :: descriptor:: DescriptorType ;
31- use crate :: plan:: { AssetProvider , Plan , RequiredPreimage , RequiredSig } ;
31+ use crate :: plan:: { AssetProvider , Plan } ;
3232use crate :: prelude:: * ;
3333use crate :: util:: witness_size;
3434use crate :: {
@@ -530,6 +530,21 @@ impl_tuple_satisfier!(A, B, C, D, E, F);
530530impl_tuple_satisfier ! ( A , B , C , D , E , F , G ) ;
531531impl_tuple_satisfier ! ( A , B , C , D , E , F , G , H ) ;
532532
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+
533548#[ derive( Debug , Clone , PartialEq , Eq ) ]
534549/// Placeholder for some data in a [`WitnessTemplate`]
535550pub enum Placeholder < Pk : MiniscriptKey > {
@@ -541,10 +556,10 @@ pub enum Placeholder<Pk: MiniscriptKey> {
541556 EcdsaSigPk ( Pk ) ,
542557 /// ECDSA signature given the pubkey hash
543558 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 ) ,
548563 /// SHA-256 preimage
549564 Sha256Preimage ( Pk :: Sha256 ) ,
550565 /// HASH256 preimage
@@ -575,12 +590,16 @@ impl<Pk: MiniscriptKey> fmt::Display for Placeholder<Pk> {
575590 PubkeyHash ( pkh, size) => write ! ( f, "PubkeyHash(pkh: {}, size: {})" , pkh, size) ,
576591 EcdsaSigPk ( pk) => write ! ( f, "EcdsaSigPk(pk: {})" , pk) ,
577592 EcdsaSigHash ( hash) => write ! ( f, "EcdsaSigHash(hash: {})" , hash) ,
578- SchnorrSig ( pk, tap_leaf_hash) => write ! (
593+ SchnorrSig ( pk, tap_leaf_hash, size ) => write ! (
579594 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
582602 ) ,
583- SchnorrSigHash ( pkh, lh) => write ! ( f, "SchnorrSigHash(pkh: {}, leaf_hash: {})" , pkh, lh) ,
584603 Sha256Preimage ( hash) => write ! ( f, "Sha256Preimage(hash: {})" , hash) ,
585604 Hash256Preimage ( hash) => write ! ( f, "Hash256Preimage(hash: {})" , hash) ,
586605 Ripemd160Preimage ( hash) => write ! ( f, "Ripemd160Preimage(hash: {})" , hash) ,
@@ -612,8 +631,8 @@ impl<Pk: MiniscriptKey + ToPublicKey> Placeholder<Pk> {
612631 . or ( sat. lookup_raw_pkh_ecdsa_sig ( pkh) . map ( |( p, _) | p) )
613632 . map ( |pk| {
614633 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) ;
617636 pk
618637 } ) ,
619638 Placeholder :: Hash256Preimage ( h) => sat. lookup_hash256 ( h) . map ( |p| p. to_vec ( ) ) ,
@@ -624,13 +643,26 @@ impl<Pk: MiniscriptKey + ToPublicKey> Placeholder<Pk> {
624643 Placeholder :: EcdsaSigHash ( pkh) => {
625644 sat. lookup_raw_pkh_ecdsa_sig ( pkh) . map ( |( _, s) | s. to_vec ( ) )
626645 }
627- Placeholder :: SchnorrSig ( pk, Some ( leaf_hash) ) => sat
646+ Placeholder :: SchnorrSig ( pk, SchnorrSigType :: ScriptSpend { leaf_hash } , size ) => sat
628647 . 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
631654 . 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+ }
634666 Placeholder :: HashDissatisfaction => Some ( vec ! [ 0 ; 32 ] ) ,
635667 Placeholder :: PushZero => Some ( vec ! [ ] ) ,
636668 Placeholder :: PushOne => Some ( vec ! [ 1 ] ) ,
@@ -653,29 +685,6 @@ pub enum Witness<T> {
653685 Impossible ,
654686}
655687
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-
679688/// Template of a witness being constructed interactively
680689///
681690/// The generic `I` type determines the available API:
@@ -710,91 +719,6 @@ impl<Pk: MiniscriptKey + ToPublicKey> WitnessTemplate<Placeholder<Pk>> {
710719
711720 Some ( stack)
712721 }
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- }
798722}
799723
800724impl < Pk : MiniscriptKey > PartialOrd for Witness < Placeholder < Pk > > {
@@ -838,10 +762,13 @@ impl<Pk: MiniscriptKey + ToPublicKey> Witness<Placeholder<Pk>> {
838762 }
839763 }
840764 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) {
842766 Witness :: Stack ( vec ! [ Placeholder :: SchnorrSig (
843767 pk. clone( ) ,
844- Some ( leaf_hash. clone( ) ) ,
768+ SchnorrSigType :: ScriptSpend {
769+ leaf_hash: * leaf_hash,
770+ } ,
771+ size,
845772 ) ] )
846773 } else {
847774 // Signatures cannot be forged
@@ -885,11 +812,11 @@ impl<Pk: MiniscriptKey + ToPublicKey> Witness<Placeholder<Pk>> {
885812 None => Witness :: Impossible ,
886813 } ,
887814 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 ) ,
890817 Placeholder :: PubkeyHash ( pkh. clone( ) , 32 ) ,
891818 ] ) ,
892- false => Witness :: Impossible ,
819+ None => Witness :: Impossible ,
893820 } ,
894821 }
895822 }
0 commit comments