@@ -417,6 +417,7 @@ where
417417 }
418418}
419419
420+ #[ cfg( not( fuzzing) ) ]
420421impl < Pk , Ctx > expression:: FromTree for Terminal < Pk , Ctx >
421422where
422423 Pk : MiniscriptKey + str:: FromStr ,
@@ -503,15 +504,7 @@ where
503504 } ) ,
504505 ( "1" , 0 ) => Ok ( Terminal :: True ) ,
505506 ( "0" , 0 ) => Ok ( Terminal :: False ) ,
506- ( "and_v" , 2 ) => {
507- let expr = expression:: binary ( top, Terminal :: AndV ) ?;
508- if let Terminal :: AndV ( _, ref right) = expr {
509- if let Terminal :: True = right. node {
510- return Err ( Error :: NonCanonicalTrue ) ;
511- }
512- }
513- Ok ( expr)
514- }
507+ ( "and_v" , 2 ) => expression:: binary ( top, Terminal :: AndV ) ,
515508 ( "and_b" , 2 ) => expression:: binary ( top, Terminal :: AndB ) ,
516509 ( "and_n" , 2 ) => Ok ( Terminal :: AndOr (
517510 expression:: FromTree :: from_tree ( & top. args [ 0 ] ) ?,
@@ -526,15 +519,7 @@ where
526519 ( "or_b" , 2 ) => expression:: binary ( top, Terminal :: OrB ) ,
527520 ( "or_d" , 2 ) => expression:: binary ( top, Terminal :: OrD ) ,
528521 ( "or_c" , 2 ) => expression:: binary ( top, Terminal :: OrC ) ,
529- ( "or_i" , 2 ) => {
530- let expr = expression:: binary ( top, Terminal :: OrI ) ?;
531- if let Terminal :: OrI ( ref left, ref right) = expr {
532- if left. node == Terminal :: False || right. node == Terminal :: False {
533- return Err ( Error :: NonCanonicalFalse ) ;
534- }
535- }
536- Ok ( expr)
537- }
522+ ( "or_i" , 2 ) => expression:: binary ( top, Terminal :: OrI ) ,
538523 ( "thresh" , n) => {
539524 if n == 0 {
540525 return Err ( errstr ( "no arguments given" ) ) ;
@@ -815,3 +800,206 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
815800 }
816801 }
817802}
803+
804+ #[ cfg( fuzzing) ]
805+ impl < Pk , Ctx > expression:: FromTree for Terminal < Pk , Ctx >
806+ where
807+ Pk : MiniscriptKey + str:: FromStr ,
808+ Pk :: Hash : str:: FromStr ,
809+ Ctx : ScriptContext ,
810+ <Pk as str:: FromStr >:: Err : ToString ,
811+ <<Pk as MiniscriptKey >:: Hash as str:: FromStr >:: Err : ToString ,
812+ {
813+ fn from_tree ( top : & expression:: Tree ) -> Result < Terminal < Pk , Ctx > , Error > {
814+ let mut aliased_wrap;
815+ let frag_name;
816+ let frag_wrap;
817+ let mut name_split = top. name . split ( ':' ) ;
818+ match ( name_split. next ( ) , name_split. next ( ) , name_split. next ( ) ) {
819+ ( None , _, _) => {
820+ frag_name = "" ;
821+ frag_wrap = "" ;
822+ }
823+ ( Some ( name) , None , _) => {
824+ if name == "pk" {
825+ frag_name = "pk_k" ;
826+ frag_wrap = "c" ;
827+ } else if name == "pkh" {
828+ frag_name = "pk_h" ;
829+ frag_wrap = "c" ;
830+ } else {
831+ frag_name = name;
832+ frag_wrap = "" ;
833+ }
834+ }
835+ ( Some ( wrap) , Some ( name) , None ) => {
836+ if wrap. is_empty ( ) {
837+ return Err ( Error :: Unexpected ( top. name . to_owned ( ) ) ) ;
838+ }
839+ if name == "pk" {
840+ frag_name = "pk_k" ;
841+ aliased_wrap = wrap. to_owned ( ) ;
842+ aliased_wrap. push_str ( "c" ) ;
843+ frag_wrap = & aliased_wrap;
844+ } else if name == "pkh" {
845+ frag_name = "pk_h" ;
846+ aliased_wrap = wrap. to_owned ( ) ;
847+ aliased_wrap. push_str ( "c" ) ;
848+ frag_wrap = & aliased_wrap;
849+ } else {
850+ frag_name = name;
851+ frag_wrap = wrap;
852+ }
853+ }
854+ ( Some ( _) , Some ( _) , Some ( _) ) => {
855+ return Err ( Error :: MultiColon ( top. name . to_owned ( ) ) ) ;
856+ }
857+ }
858+ let mut unwrapped = match ( frag_name, top. args . len ( ) ) {
859+ ( "pk_k" , 1 ) => {
860+ expression:: terminal ( & top. args [ 0 ] , |x| Pk :: from_str ( x) . map ( Terminal :: PkK ) )
861+ }
862+ ( "pk_h" , 1 ) => {
863+ expression:: terminal ( & top. args [ 0 ] , |x| Pk :: Hash :: from_str ( x) . map ( Terminal :: PkH ) )
864+ }
865+ ( "after" , 1 ) => expression:: terminal ( & top. args [ 0 ] , |x| {
866+ expression:: parse_num ( x) . map ( Terminal :: After )
867+ } ) ,
868+ ( "older" , 1 ) => expression:: terminal ( & top. args [ 0 ] , |x| {
869+ expression:: parse_num ( x) . map ( Terminal :: Older )
870+ } ) ,
871+ ( "sha256" , 1 ) => expression:: terminal ( & top. args [ 0 ] , |x| {
872+ sha256:: Hash :: from_hex ( x) . map ( Terminal :: Sha256 )
873+ } ) ,
874+ ( "hash256" , 1 ) => expression:: terminal ( & top. args [ 0 ] , |x| {
875+ sha256d:: Hash :: from_hex ( x)
876+ . map ( |x| x. into_inner ( ) )
877+ . map ( |mut x| {
878+ x. reverse ( ) ;
879+ x
880+ } )
881+ . map ( |x| Terminal :: Hash256 ( sha256d:: Hash :: from_inner ( x) ) )
882+ } ) ,
883+ ( "ripemd160" , 1 ) => expression:: terminal ( & top. args [ 0 ] , |x| {
884+ ripemd160:: Hash :: from_hex ( x) . map ( Terminal :: Ripemd160 )
885+ } ) ,
886+ ( "hash160" , 1 ) => expression:: terminal ( & top. args [ 0 ] , |x| {
887+ hash160:: Hash :: from_hex ( x) . map ( Terminal :: Hash160 )
888+ } ) ,
889+ ( "1" , 0 ) => Ok ( Terminal :: True ) ,
890+ ( "0" , 0 ) => Ok ( Terminal :: False ) ,
891+ ( "and_v" , 2 ) => {
892+ let expr = expression:: binary ( top, Terminal :: AndV ) ?;
893+ if let Terminal :: AndV ( _, ref right) = expr {
894+ if let Terminal :: True = right. node {
895+ return Err ( Error :: Unexpected ( String :: from ( "NonCannonicalTrue" ) ) ) ;
896+ }
897+ }
898+ Ok ( expr)
899+ }
900+ ( "and_b" , 2 ) => expression:: binary ( top, Terminal :: AndB ) ,
901+ ( "and_n" , 2 ) => Ok ( Terminal :: AndOr (
902+ expression:: FromTree :: from_tree ( & top. args [ 0 ] ) ?,
903+ expression:: FromTree :: from_tree ( & top. args [ 1 ] ) ?,
904+ Arc :: new ( Miniscript :: from_ast ( Terminal :: False ) ?) ,
905+ ) ) ,
906+ ( "andor" , 3 ) => Ok ( Terminal :: AndOr (
907+ expression:: FromTree :: from_tree ( & top. args [ 0 ] ) ?,
908+ expression:: FromTree :: from_tree ( & top. args [ 1 ] ) ?,
909+ expression:: FromTree :: from_tree ( & top. args [ 2 ] ) ?,
910+ ) ) ,
911+ ( "or_b" , 2 ) => expression:: binary ( top, Terminal :: OrB ) ,
912+ ( "or_d" , 2 ) => expression:: binary ( top, Terminal :: OrD ) ,
913+ ( "or_c" , 2 ) => expression:: binary ( top, Terminal :: OrC ) ,
914+ ( "or_i" , 2 ) => {
915+ let expr = expression:: binary ( top, Terminal :: OrI ) ?;
916+ if let Terminal :: OrI ( ref left, ref right) = expr {
917+ if left. node == Terminal :: False || right. node == Terminal :: False {
918+ return Err ( Error :: Unexpected ( String :: from ( "NonCannonicalFalse" ) ) ) ;
919+ }
920+ }
921+ Ok ( expr)
922+ }
923+ ( "thresh" , n) => {
924+ if n == 0 {
925+ return Err ( errstr ( "no arguments given" ) ) ;
926+ }
927+ let k = expression:: terminal ( & top. args [ 0 ] , expression:: parse_num) ? as usize ;
928+ if k > n - 1 {
929+ return Err ( errstr ( "higher threshold than there are subexpressions" ) ) ;
930+ }
931+ if n == 1 {
932+ return Err ( errstr ( "empty thresholds not allowed in descriptors" ) ) ;
933+ }
934+
935+ let subs: Result < Vec < Arc < Miniscript < Pk , Ctx > > > , _ > = top. args [ 1 ..]
936+ . iter ( )
937+ . map ( |sub| expression:: FromTree :: from_tree ( sub) )
938+ . collect ( ) ;
939+
940+ Ok ( Terminal :: Thresh ( k, subs?) )
941+ }
942+ ( "multi" , n) => {
943+ if n == 0 {
944+ return Err ( errstr ( "no arguments given" ) ) ;
945+ }
946+ let k = expression:: terminal ( & top. args [ 0 ] , expression:: parse_num) ? as usize ;
947+ if k > n - 1 {
948+ return Err ( errstr ( "higher threshold than there were keys in multi" ) ) ;
949+ }
950+
951+ let pks: Result < Vec < Pk > , _ > = top. args [ 1 ..]
952+ . iter ( )
953+ . map ( |sub| expression:: terminal ( sub, Pk :: from_str) )
954+ . collect ( ) ;
955+
956+ pks. map ( |pks| Terminal :: Multi ( k, pks) )
957+ }
958+ _ => Err ( Error :: Unexpected ( format ! (
959+ "{}({} args) while parsing Miniscript" ,
960+ top. name,
961+ top. args. len( ) ,
962+ ) ) ) ,
963+ } ?;
964+ for ch in frag_wrap. chars ( ) . rev ( ) {
965+ // Check whether the wrapper is valid under the current context
966+ let ms = Miniscript :: from_ast ( unwrapped) ?;
967+ Ctx :: check_global_validity ( & ms) ?;
968+ match ch {
969+ 'a' => unwrapped = Terminal :: Alt ( Arc :: new ( ms) ) ,
970+ 's' => unwrapped = Terminal :: Swap ( Arc :: new ( ms) ) ,
971+ 'c' => unwrapped = Terminal :: Check ( Arc :: new ( ms) ) ,
972+ 'd' => unwrapped = Terminal :: DupIf ( Arc :: new ( ms) ) ,
973+ 'v' => unwrapped = Terminal :: Verify ( Arc :: new ( ms) ) ,
974+ 'j' => unwrapped = Terminal :: NonZero ( Arc :: new ( ms) ) ,
975+ 'n' => unwrapped = Terminal :: ZeroNotEqual ( Arc :: new ( ms) ) ,
976+ 't' => {
977+ unwrapped = Terminal :: AndV (
978+ Arc :: new ( ms) ,
979+ Arc :: new ( Miniscript :: from_ast ( Terminal :: True ) ?) ,
980+ )
981+ }
982+ 'u' => {
983+ unwrapped = Terminal :: OrI (
984+ Arc :: new ( ms) ,
985+ Arc :: new ( Miniscript :: from_ast ( Terminal :: False ) ?) ,
986+ )
987+ }
988+ 'l' => {
989+ if ms. node == Terminal :: False {
990+ return Err ( Error :: LikelyFalse ) ;
991+ }
992+ unwrapped = Terminal :: OrI (
993+ Arc :: new ( Miniscript :: from_ast ( Terminal :: False ) ?) ,
994+ Arc :: new ( ms) ,
995+ )
996+ }
997+ x => return Err ( Error :: UnknownWrapper ( x) ) ,
998+ }
999+ }
1000+ // Check whether the unwrapped miniscript is valid under the current context
1001+ let ms = Miniscript :: from_ast ( unwrapped) ?;
1002+ Ctx :: check_global_validity ( & ms) ?;
1003+ Ok ( ms. node )
1004+ }
1005+ }
0 commit comments