@@ -36,15 +36,13 @@ mod bare;
3636mod iter;
3737mod segwitv0;
3838mod sh;
39- mod sortedmulti;
4039mod tr;
4140
4241// Descriptor Exports
4342pub use self :: bare:: { Bare , Pkh } ;
4443pub use self :: iter:: PkIter ;
45- pub use self :: segwitv0:: { Wpkh , Wsh , WshInner } ;
44+ pub use self :: segwitv0:: { Wpkh , Wsh } ;
4645pub use self :: sh:: { Sh , ShInner } ;
47- pub use self :: sortedmulti:: SortedMultiVec ;
4846pub use self :: tr:: {
4947 TapTree , TapTreeDepthError , TapTreeIter , TapTreeIterItem , Tr , TrSpendInfo , TrSpendInfoIter ,
5048 TrSpendInfoIterItem ,
@@ -256,18 +254,31 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
256254 Descriptor :: Pkh ( ref pk) => PkIter :: from_key ( pk. as_inner ( ) . clone ( ) ) ,
257255 Descriptor :: Wpkh ( ref pk) => PkIter :: from_key ( pk. as_inner ( ) . clone ( ) ) ,
258256 Descriptor :: Sh ( ref sh) => match * sh. as_inner ( ) {
259- ShInner :: Wsh ( ref wsh) => match wsh. as_inner ( ) {
260- WshInner :: SortedMulti ( ref sorted) => PkIter :: from_sortedmulti ( sorted. pks ( ) ) ,
261- WshInner :: Ms ( ref ms) => PkIter :: from_miniscript_segwit ( ms) ,
262- } ,
257+ ShInner :: Wsh ( ref wsh) => {
258+ let ms = wsh. as_inner ( ) ;
259+ if let Terminal :: SortedMulti ( ref thresh) = ms. node {
260+ PkIter :: from_sortedmulti ( thresh. data ( ) )
261+ } else {
262+ PkIter :: from_miniscript_segwit ( ms)
263+ }
264+ }
263265 ShInner :: Wpkh ( ref pk) => PkIter :: from_key ( pk. as_inner ( ) . clone ( ) ) ,
264- ShInner :: SortedMulti ( ref sorted) => PkIter :: from_sortedmulti ( sorted. pks ( ) ) ,
265- ShInner :: Ms ( ref ms) => PkIter :: from_miniscript_legacy ( ms) ,
266- } ,
267- Descriptor :: Wsh ( ref wsh) => match wsh. as_inner ( ) {
268- WshInner :: SortedMulti ( ref sorted) => PkIter :: from_sortedmulti ( sorted. pks ( ) ) ,
269- WshInner :: Ms ( ref ms) => PkIter :: from_miniscript_segwit ( ms) ,
266+ ShInner :: Ms ( ref ms) => {
267+ if let Terminal :: SortedMulti ( ref thresh) = ms. node {
268+ PkIter :: from_sortedmulti ( thresh. data ( ) )
269+ } else {
270+ PkIter :: from_miniscript_legacy ( ms)
271+ }
272+ }
270273 } ,
274+ Descriptor :: Wsh ( ref wsh) => {
275+ let ms = wsh. as_inner ( ) ;
276+ if let Terminal :: SortedMulti ( ref thresh) = ms. node {
277+ PkIter :: from_sortedmulti ( thresh. data ( ) )
278+ } else {
279+ PkIter :: from_miniscript_segwit ( ms)
280+ }
281+ }
271282 Descriptor :: Tr ( ref tr) => PkIter :: from_tr ( tr) ,
272283 }
273284 }
@@ -313,18 +324,29 @@ impl<Pk: MiniscriptKey> Descriptor<Pk> {
313324 Descriptor :: Pkh ( ref _pkh) => DescriptorType :: Pkh ,
314325 Descriptor :: Wpkh ( ref _wpkh) => DescriptorType :: Wpkh ,
315326 Descriptor :: Sh ( ref sh) => match sh. as_inner ( ) {
316- ShInner :: Wsh ( ref wsh) => match wsh. as_inner ( ) {
317- WshInner :: SortedMulti ( ref _smv) => DescriptorType :: ShWshSortedMulti ,
318- WshInner :: Ms ( ref _ms) => DescriptorType :: ShWsh ,
319- } ,
327+ ShInner :: Wsh ( ref wsh) => {
328+ if let Terminal :: SortedMulti ( ..) = wsh. as_inner ( ) . node {
329+ DescriptorType :: ShWshSortedMulti
330+ } else {
331+ DescriptorType :: ShWsh
332+ }
333+ }
320334 ShInner :: Wpkh ( ref _wpkh) => DescriptorType :: ShWpkh ,
321- ShInner :: SortedMulti ( ref _smv) => DescriptorType :: ShSortedMulti ,
322- ShInner :: Ms ( ref _ms) => DescriptorType :: Sh ,
323- } ,
324- Descriptor :: Wsh ( ref wsh) => match wsh. as_inner ( ) {
325- WshInner :: SortedMulti ( ref _smv) => DescriptorType :: WshSortedMulti ,
326- WshInner :: Ms ( ref _ms) => DescriptorType :: Wsh ,
335+ ShInner :: Ms ( ref ms) => {
336+ if let Terminal :: SortedMulti ( ..) = ms. node {
337+ DescriptorType :: ShSortedMulti
338+ } else {
339+ DescriptorType :: Sh
340+ }
341+ }
327342 } ,
343+ Descriptor :: Wsh ( ref wsh) => {
344+ if let Terminal :: SortedMulti ( ..) = wsh. as_inner ( ) . node {
345+ DescriptorType :: WshSortedMulti
346+ } else {
347+ DescriptorType :: Wsh
348+ }
349+ }
328350 Descriptor :: Tr ( ref _tr) => DescriptorType :: Tr ,
329351 }
330352 }
@@ -1208,6 +1230,7 @@ mod tests {
12081230
12091231 use super :: { checksum, * } ;
12101232 use crate :: hex_script;
1233+ use crate :: miniscript:: context:: ScriptContextError ;
12111234 #[ cfg( feature = "compiler" ) ]
12121235 use crate :: policy;
12131236
@@ -1257,7 +1280,7 @@ mod tests {
12571280 StdDescriptor :: from_str( "sh(sortedmulti)" )
12581281 . unwrap_err( )
12591282 . to_string( ) ,
1260- "sortedmulti must have at least 1 children, but found 0 "
1283+ "expected threshold, found terminal "
12611284 ) ; //issue 202
12621285 assert_eq ! (
12631286 StdDescriptor :: from_str( & format!( "sh(sortedmulti(2,{}))" , & TEST_PK [ 3 ..69 ] ) )
@@ -2884,4 +2907,26 @@ pk(03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8))";
28842907 let definite: Result < Descriptor < DefiniteDescriptorKey > , _ > = desc. try_into ( ) ;
28852908 assert ! ( matches!( definite, Err ( NonDefiniteKeyError :: Wildcard ) ) ) ;
28862909 }
2910+
2911+ #[ test]
2912+ fn too_many_pubkeys_for_p2sh ( ) {
2913+ // Arbitrary 65-byte public key (66 with length prefix).
2914+ let pk = PublicKey :: from_str (
2915+ "0400232a2acfc9b43fa89f1b4f608fde335d330d7114f70ea42bfb4a41db368a3e3be6934a4097dd25728438ef73debb1f2ffdb07fec0f18049df13bdc5285dc5b" ,
2916+ )
2917+ . unwrap ( ) ;
2918+
2919+ // This is legal for CHECKMULTISIG, but the 8 keys consume the whole 520 bytes
2920+ // allowed by P2SH, meaning that the full script goes over the limit.
2921+ let thresh = Threshold :: new ( 2 , vec ! [ pk; 8 ] ) . expect ( "the thresh is ok.." ) ;
2922+ let script = Miniscript :: < _ , Legacy > :: sortedmulti ( thresh) . encode ( ) ;
2923+ let res = Miniscript :: < _ , Legacy > :: decode ( & script) ;
2924+
2925+ let error = res. expect_err ( "decoding should err" ) ;
2926+
2927+ match error {
2928+ Error :: ContextError ( ScriptContextError :: MaxRedeemScriptSizeExceeded { .. } ) => { } // ok
2929+ other => panic ! ( "unexpected error: {:?}" , other) ,
2930+ }
2931+ }
28872932}
0 commit comments