@@ -728,6 +728,7 @@ mod test {
728728 use std:: str:: FromStr ;
729729
730730 use bitcoin:: bip32:: Xpub ;
731+ use secp256k1:: Secp256k1 ;
731732
732733 use super :: * ;
733734 use crate :: * ;
@@ -1154,88 +1155,92 @@ mod test {
11541155 assert_eq ! ( psbt_input. bip32_derivation. len( ) , 2 , "Unexpected number of bip32_derivation" ) ;
11551156 }
11561157
1157- #[ test]
1158- fn test_plan_satisfy_wsh ( ) {
1159- use std:: collections:: BTreeMap ;
1160-
1161- use bitcoin:: secp256k1:: { self , Secp256k1 } ;
1162-
1158+ fn test_plan_satisfy (
1159+ desc_str_fn : fn ( & [ bitcoin:: PublicKey ] ) -> String ,
1160+ exp_witness_len : usize ,
1161+ ) -> Vec < Vec < u8 > > {
11631162 let secp = Secp256k1 :: new ( ) ;
11641163
1165- let sk =
1166- secp256k1:: SecretKey :: from_slice ( & b"sally was a secret key, she said" [ ..] ) . unwrap ( ) ;
1167- let pk = bitcoin:: PublicKey :: new ( secp256k1:: PublicKey :: from_secret_key ( & secp, & sk) ) ;
1164+ let ( sks, pks) : ( Vec < _ > , Vec < _ > ) = [
1165+ & b"sally was a secret key, she said" [ ..] ,
1166+ & b"polly was a secret key, she said" [ ..] ,
1167+ & b"bonny was a secret key, she said" [ ..] ,
1168+ ]
1169+ . iter ( )
1170+ . map ( |d| {
1171+ let sk = secp256k1:: SecretKey :: from_slice ( d) . unwrap ( ) ;
1172+ let pk = bitcoin:: PublicKey :: new ( secp256k1:: PublicKey :: from_secret_key ( & secp, & sk) ) ;
1173+ ( sk, pk)
1174+ } )
1175+ . unzip ( ) ;
11681176
1169- let desc =
1170- Descriptor :: < DefiniteDescriptorKey > :: from_str ( & format ! ( "wsh(pk({}))" , pk) ) . unwrap ( ) ;
1177+ let desc = Descriptor :: < DefiniteDescriptorKey > :: from_str ( & desc_str_fn ( & pks) ) . unwrap ( ) ;
11711178
1172- let sighash =
1173- secp256k1:: Message :: from_digest_slice ( & b"michael was a message, amusingly" [ ..] )
1174- . expect ( "32 bytes" ) ;
1175- let ecdsa_sig = bitcoin:: ecdsa:: Signature {
1176- signature : secp. sign_ecdsa ( & sighash, & sk) ,
1177- sighash_type : bitcoin:: sighash:: EcdsaSighashType :: All ,
1178- } ;
1179+ let sigs = sks
1180+ . iter ( )
1181+ . map ( |sk| {
1182+ let sighash =
1183+ secp256k1:: Message :: from_digest_slice ( & b"michael was a message, amusingly" [ ..] )
1184+ . expect ( "32 bytes" ) ;
1185+ bitcoin:: ecdsa:: Signature {
1186+ signature : secp. sign_ecdsa ( & sighash, sk) ,
1187+ sighash_type : bitcoin:: sighash:: EcdsaSighashType :: All ,
1188+ }
1189+ } )
1190+ . collect :: < Vec < _ > > ( ) ;
11791191
11801192 // This witness script should exist in the witness stack returned by `Plan::satisfy`.
1181- let exp_witness_script = desc. explicit_script ( ) . expect ( "wsh has explicit script" ) ;
1193+ let exp_witness_script = desc. explicit_script ( ) . expect ( "has explicit script" ) ;
1194+ let exp_script_sig = desc. unsigned_script_sig ( ) ;
11821195
11831196 let mut satisfier = BTreeMap :: < DefiniteDescriptorKey , bitcoin:: ecdsa:: Signature > :: new ( ) ;
1184- satisfier. insert ( DefiniteDescriptorKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) , ecdsa_sig) ;
1197+ let mut assets = Assets :: new ( ) ;
1198+ for ( i, pk) in pks. iter ( ) . enumerate ( ) {
1199+ satisfier. insert ( DefiniteDescriptorKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) , sigs[ i] ) ;
1200+ assets = assets. add ( DescriptorPublicKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) ) ;
1201+ }
11851202
1186- let assets = Assets :: new ( ) . add ( DescriptorPublicKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) ) ;
11871203 let plan = desc. plan ( & assets) . expect ( "plan should succeed" ) ;
11881204
11891205 let ( witness, script_sig) = plan. satisfy ( & satisfier) . expect ( "satisfy should succeed" ) ;
1206+ assert_eq ! ( witness. last( ) . unwrap( ) , & exp_witness_script. into_bytes( ) ) ;
1207+ assert_eq ! ( script_sig, exp_script_sig) ;
1208+ assert_eq ! ( witness. len( ) , exp_witness_len) ;
11901209
1210+ witness
1211+ }
1212+
1213+ #[ test]
1214+ fn test_plan_satisfy_wsh ( ) {
11911215 // For native P2WSH:
11921216 // - script_sig should be empty
11931217 // - witness should contain [signature, witness_script]
1194- assert_eq ! ( script_sig, ScriptBuf :: new( ) ) ;
1195- assert_eq ! ( witness. len( ) , 2 ) ;
1196- assert_eq ! ( witness. last( ) . unwrap( ) , & exp_witness_script. into_bytes( ) ) ;
1218+ test_plan_satisfy ( |pks| format ! ( "wsh(pk({}))" , pks[ 0 ] ) , 2 ) ;
11971219 }
11981220
11991221 #[ test]
12001222 fn test_plan_satisfy_sh_wsh ( ) {
1201- use std:: collections:: BTreeMap ;
1202-
1203- use bitcoin:: secp256k1:: { self , Secp256k1 } ;
1204-
1205- let secp = Secp256k1 :: new ( ) ;
1206- let sk =
1207- secp256k1:: SecretKey :: from_slice ( & b"sally was a secret key, she said" [ ..] ) . unwrap ( ) ;
1208- let pk = bitcoin:: PublicKey :: new ( secp256k1:: PublicKey :: from_secret_key ( & secp, & sk) ) ;
1209-
1210- let desc =
1211- Descriptor :: < DefiniteDescriptorKey > :: from_str ( & format ! ( "sh(wsh(pk({})))" , pk) ) . unwrap ( ) ;
1212-
1213- let sighash =
1214- secp256k1:: Message :: from_digest_slice ( & b"michael was a message, amusingly" [ ..] )
1215- . expect ( "32 bytes" ) ;
1216- let ecdsa_sig = bitcoin:: ecdsa:: Signature {
1217- signature : secp. sign_ecdsa ( & sighash, & sk) ,
1218- sighash_type : bitcoin:: sighash:: EcdsaSighashType :: All ,
1219- } ;
1220-
1221- // Get expected values before plan() consumes the descriptor.
1222- let exp_witness_script = desc. explicit_script ( ) . expect ( "sh-wsh has explicit script" ) ;
1223- let exp_script_sig = desc. unsigned_script_sig ( ) ;
1224-
1225- let mut satisfier: BTreeMap < DefiniteDescriptorKey , bitcoin:: ecdsa:: Signature > =
1226- BTreeMap :: new ( ) ;
1227- satisfier. insert ( DefiniteDescriptorKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) , ecdsa_sig) ;
1228-
1229- let assets = Assets :: new ( ) . add ( DescriptorPublicKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) ) ;
1230- let plan = desc. plan ( & assets) . expect ( "plan should succeed" ) ;
1231-
1232- let ( witness, script_sig) = plan. satisfy ( & satisfier) . expect ( "satisfy should succeed" ) ;
1233-
12341223 // For P2SH-P2WSH:
12351224 // - script_sig should be the unsigned_script_sig (pushes the P2WSH redeemScript)
12361225 // - witness should contain [signature, witness_script]
1237- assert_eq ! ( script_sig, exp_script_sig) ;
1238- assert_eq ! ( witness. len( ) , 2 ) ;
1239- assert_eq ! ( witness. last( ) . unwrap( ) , & exp_witness_script. into_bytes( ) ) ;
1226+ test_plan_satisfy ( |pks| format ! ( "sh(wsh(pk({})))" , pks[ 0 ] ) , 2 ) ;
1227+ }
1228+
1229+ #[ test]
1230+ fn test_plan_satisfy_sortedmulti ( ) {
1231+ // For native P2WSH with sortedmulti:
1232+ // - script_sig should be empty
1233+ // - witness should contain [sig1, sig2, sig3, witness_script]
1234+ // - witness should be the same no matter the order of the keys
1235+ assert_eq ! (
1236+ test_plan_satisfy(
1237+ |pks| format!( "wsh(sortedmulti(2,{},{},{}))" , pks[ 0 ] , pks[ 1 ] , pks[ 2 ] ) ,
1238+ 4
1239+ ) ,
1240+ test_plan_satisfy(
1241+ |pks| format!( "wsh(sortedmulti(2,{},{},{}))" , pks[ 1 ] , pks[ 2 ] , pks[ 0 ] ) ,
1242+ 4
1243+ )
1244+ ) ;
12401245 }
12411246}
0 commit comments