@@ -734,6 +734,7 @@ mod test {
734734 use std:: str:: FromStr ;
735735
736736 use bitcoin:: bip32:: Xpub ;
737+ use secp256k1:: Secp256k1 ;
737738
738739 use super :: * ;
739740 use crate :: * ;
@@ -1160,88 +1161,92 @@ mod test {
11601161 assert_eq ! ( psbt_input. bip32_derivation. len( ) , 2 , "Unexpected number of bip32_derivation" ) ;
11611162 }
11621163
1163- #[ test]
1164- fn test_plan_satisfy_wsh ( ) {
1165- use std:: collections:: BTreeMap ;
1166-
1167- use bitcoin:: secp256k1:: { self , Secp256k1 } ;
1168-
1164+ fn test_plan_satisfy (
1165+ desc_str_fn : fn ( & [ bitcoin:: PublicKey ] ) -> String ,
1166+ exp_witness_len : usize ,
1167+ ) -> Vec < Vec < u8 > > {
11691168 let secp = Secp256k1 :: new ( ) ;
11701169
1171- let sk =
1172- secp256k1:: SecretKey :: from_slice ( & b"sally was a secret key, she said" [ ..] ) . unwrap ( ) ;
1173- let pk = bitcoin:: PublicKey :: new ( secp256k1:: PublicKey :: from_secret_key ( & secp, & sk) ) ;
1170+ let ( sks, pks) : ( Vec < _ > , Vec < _ > ) = [
1171+ & b"sally was a secret key, she said" [ ..] ,
1172+ & b"polly was a secret key, she said" [ ..] ,
1173+ & b"bonny was a secret key, she said" [ ..] ,
1174+ ]
1175+ . iter ( )
1176+ . map ( |d| {
1177+ let sk = secp256k1:: SecretKey :: from_slice ( d) . unwrap ( ) ;
1178+ let pk = bitcoin:: PublicKey :: new ( secp256k1:: PublicKey :: from_secret_key ( & secp, & sk) ) ;
1179+ ( sk, pk)
1180+ } )
1181+ . unzip ( ) ;
11741182
1175- let desc =
1176- Descriptor :: < DefiniteDescriptorKey > :: from_str ( & format ! ( "wsh(pk({}))" , pk) ) . unwrap ( ) ;
1183+ let desc = Descriptor :: < DefiniteDescriptorKey > :: from_str ( & desc_str_fn ( & pks) ) . unwrap ( ) ;
11771184
1178- let sighash =
1179- secp256k1:: Message :: from_digest_slice ( & b"michael was a message, amusingly" [ ..] )
1180- . expect ( "32 bytes" ) ;
1181- let ecdsa_sig = bitcoin:: ecdsa:: Signature {
1182- signature : secp. sign_ecdsa ( & sighash, & sk) ,
1183- sighash_type : bitcoin:: sighash:: EcdsaSighashType :: All ,
1184- } ;
1185+ let sigs = sks
1186+ . iter ( )
1187+ . map ( |sk| {
1188+ let sighash =
1189+ secp256k1:: Message :: from_digest_slice ( & b"michael was a message, amusingly" [ ..] )
1190+ . expect ( "32 bytes" ) ;
1191+ bitcoin:: ecdsa:: Signature {
1192+ signature : secp. sign_ecdsa ( & sighash, sk) ,
1193+ sighash_type : bitcoin:: sighash:: EcdsaSighashType :: All ,
1194+ }
1195+ } )
1196+ . collect :: < Vec < _ > > ( ) ;
11851197
11861198 // This witness script should exist in the witness stack returned by `Plan::satisfy`.
1187- let exp_witness_script = desc. explicit_script ( ) . expect ( "wsh has explicit script" ) ;
1199+ let exp_witness_script = desc. explicit_script ( ) . expect ( "has explicit script" ) ;
1200+ let exp_script_sig = desc. unsigned_script_sig ( ) ;
11881201
11891202 let mut satisfier = BTreeMap :: < DefiniteDescriptorKey , bitcoin:: ecdsa:: Signature > :: new ( ) ;
1190- satisfier. insert ( DefiniteDescriptorKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) , ecdsa_sig) ;
1203+ let mut assets = Assets :: new ( ) ;
1204+ for ( i, pk) in pks. iter ( ) . enumerate ( ) {
1205+ satisfier. insert ( DefiniteDescriptorKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) , sigs[ i] ) ;
1206+ assets = assets. add ( DescriptorPublicKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) ) ;
1207+ }
11911208
1192- let assets = Assets :: new ( ) . add ( DescriptorPublicKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) ) ;
11931209 let plan = desc. plan ( & assets) . expect ( "plan should succeed" ) ;
11941210
11951211 let ( witness, script_sig) = plan. satisfy ( & satisfier) . expect ( "satisfy should succeed" ) ;
1212+ assert_eq ! ( witness. last( ) . unwrap( ) , & exp_witness_script. into_bytes( ) ) ;
1213+ assert_eq ! ( script_sig, exp_script_sig) ;
1214+ assert_eq ! ( witness. len( ) , exp_witness_len) ;
11961215
1216+ witness
1217+ }
1218+
1219+ #[ test]
1220+ fn test_plan_satisfy_wsh ( ) {
11971221 // For native P2WSH:
11981222 // - script_sig should be empty
11991223 // - witness should contain [signature, witness_script]
1200- assert_eq ! ( script_sig, ScriptBuf :: new( ) ) ;
1201- assert_eq ! ( witness. len( ) , 2 ) ;
1202- assert_eq ! ( witness. last( ) . unwrap( ) , & exp_witness_script. into_bytes( ) ) ;
1224+ test_plan_satisfy ( |pks| format ! ( "wsh(pk({}))" , pks[ 0 ] ) , 2 ) ;
12031225 }
12041226
12051227 #[ test]
12061228 fn test_plan_satisfy_sh_wsh ( ) {
1207- use std:: collections:: BTreeMap ;
1208-
1209- use bitcoin:: secp256k1:: { self , Secp256k1 } ;
1210-
1211- let secp = Secp256k1 :: new ( ) ;
1212- let sk =
1213- secp256k1:: SecretKey :: from_slice ( & b"sally was a secret key, she said" [ ..] ) . unwrap ( ) ;
1214- let pk = bitcoin:: PublicKey :: new ( secp256k1:: PublicKey :: from_secret_key ( & secp, & sk) ) ;
1215-
1216- let desc =
1217- Descriptor :: < DefiniteDescriptorKey > :: from_str ( & format ! ( "sh(wsh(pk({})))" , pk) ) . unwrap ( ) ;
1218-
1219- let sighash =
1220- secp256k1:: Message :: from_digest_slice ( & b"michael was a message, amusingly" [ ..] )
1221- . expect ( "32 bytes" ) ;
1222- let ecdsa_sig = bitcoin:: ecdsa:: Signature {
1223- signature : secp. sign_ecdsa ( & sighash, & sk) ,
1224- sighash_type : bitcoin:: sighash:: EcdsaSighashType :: All ,
1225- } ;
1226-
1227- // Get expected values before plan() consumes the descriptor.
1228- let exp_witness_script = desc. explicit_script ( ) . expect ( "sh-wsh has explicit script" ) ;
1229- let exp_script_sig = desc. unsigned_script_sig ( ) ;
1230-
1231- let mut satisfier: BTreeMap < DefiniteDescriptorKey , bitcoin:: ecdsa:: Signature > =
1232- BTreeMap :: new ( ) ;
1233- satisfier. insert ( DefiniteDescriptorKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) , ecdsa_sig) ;
1234-
1235- let assets = Assets :: new ( ) . add ( DescriptorPublicKey :: from_str ( & pk. to_string ( ) ) . unwrap ( ) ) ;
1236- let plan = desc. plan ( & assets) . expect ( "plan should succeed" ) ;
1237-
1238- let ( witness, script_sig) = plan. satisfy ( & satisfier) . expect ( "satisfy should succeed" ) ;
1239-
12401229 // For P2SH-P2WSH:
12411230 // - script_sig should be the unsigned_script_sig (pushes the P2WSH redeemScript)
12421231 // - witness should contain [signature, witness_script]
1243- assert_eq ! ( script_sig, exp_script_sig) ;
1244- assert_eq ! ( witness. len( ) , 2 ) ;
1245- assert_eq ! ( witness. last( ) . unwrap( ) , & exp_witness_script. into_bytes( ) ) ;
1232+ test_plan_satisfy ( |pks| format ! ( "sh(wsh(pk({})))" , pks[ 0 ] ) , 2 ) ;
1233+ }
1234+
1235+ #[ test]
1236+ fn test_plan_satisfy_sortedmulti ( ) {
1237+ // For native P2WSH with sortedmulti:
1238+ // - script_sig should be empty
1239+ // - witness should contain [sig1, sig2, sig3, witness_script]
1240+ // - witness should be the same no matter the order of the keys
1241+ assert_eq ! (
1242+ test_plan_satisfy(
1243+ |pks| format!( "wsh(sortedmulti(2,{},{},{}))" , pks[ 0 ] , pks[ 1 ] , pks[ 2 ] ) ,
1244+ 4
1245+ ) ,
1246+ test_plan_satisfy(
1247+ |pks| format!( "wsh(sortedmulti(2,{},{},{}))" , pks[ 1 ] , pks[ 2 ] , pks[ 0 ] ) ,
1248+ 4
1249+ )
1250+ ) ;
12461251 }
12471252}
0 commit comments