1212//! components of the AST.
1313//!
1414
15- use core:: marker:: PhantomData ;
1615use core:: { fmt, hash, str} ;
1716
1817use bitcoin:: hashes:: hash160;
@@ -22,7 +21,7 @@ use bitcoin::taproot::{LeafVersion, TapLeafHash};
2221use self :: analyzable:: ExtParams ;
2322pub use self :: context:: { BareCtx , Legacy , Segwitv0 , Tap } ;
2423use crate :: iter:: TreeLike ;
25- use crate :: { prelude:: * , MAX_RECURSION_DEPTH } ;
24+ use crate :: prelude:: * ;
2625use crate :: { script_num_size, TranslateErr } ;
2726
2827pub mod analyzable;
@@ -43,62 +42,73 @@ use self::lex::{lex, TokenIter};
4342use self :: types:: Property ;
4443pub use crate :: miniscript:: context:: ScriptContext ;
4544use crate :: miniscript:: decode:: Terminal ;
46- use crate :: miniscript:: types:: extra_props:: ExtData ;
47- use crate :: miniscript:: types:: Type ;
4845use crate :: {
4946 expression, plan, Error , ForEachKey , MiniscriptKey , ToPublicKey , TranslatePk , Translator ,
5047} ;
5148#[ cfg( test) ]
5249mod ms_tests;
5350
54- /// The top-level miniscript abstract syntax tree (AST).
55- #[ derive( Clone ) ]
56- pub struct Miniscript < Pk : MiniscriptKey , Ctx : ScriptContext > {
57- /// A node in the AST.
58- pub node : Terminal < Pk , Ctx > ,
59- /// The correctness and malleability type information for the AST node.
60- pub ty : types:: Type ,
61- /// Additional information helpful for extra analysis.
62- pub ext : types:: extra_props:: ExtData ,
63- /// Context PhantomData. Only accessible inside this crate
64- phantom : PhantomData < Ctx > ,
65- }
51+ mod private {
52+ use core:: marker:: PhantomData ;
6653
67- impl < Pk : MiniscriptKey , Ctx : ScriptContext > Miniscript < Pk , Ctx > {
68- /// Add type information(Type and Extdata) to Miniscript based on
69- /// `AstElem` fragment. Dependent on display and clone because of Error
70- /// Display code of type_check.
71- pub fn from_ast ( t : Terminal < Pk , Ctx > ) -> Result < Miniscript < Pk , Ctx > , Error > {
72- let res = Miniscript {
73- ty : Type :: type_check ( & t) ?,
74- ext : ExtData :: type_check ( & t) ?,
75- node : t,
76- phantom : PhantomData ,
77- } ;
78- // TODO: This recursion depth is based on segwitv0.
79- // We can relax this in tapscript, but this should be good for almost
80- // all practical cases and we can revisit this if needed.
81- // casting to u32 is safe because tree_height will never go more than u32::MAX
82- if ( res. ext . tree_height as u32 ) > MAX_RECURSION_DEPTH {
83- return Err ( Error :: MaxRecursiveDepthExceeded ) ;
84- }
85- Ctx :: check_global_consensus_validity ( & res) ?;
86- Ok ( res)
54+ use super :: types:: { ExtData , Property , Type } ;
55+ pub use crate :: miniscript:: context:: ScriptContext ;
56+ use crate :: miniscript:: types;
57+ use crate :: { Error , MiniscriptKey , Terminal , MAX_RECURSION_DEPTH } ;
58+
59+ /// The top-level miniscript abstract syntax tree (AST).
60+ #[ derive( Clone ) ]
61+ pub struct Miniscript < Pk : MiniscriptKey , Ctx : ScriptContext > {
62+ /// A node in the AST.
63+ pub node : Terminal < Pk , Ctx > ,
64+ /// The correctness and malleability type information for the AST node.
65+ pub ty : types:: Type ,
66+ /// Additional information helpful for extra analysis.
67+ pub ext : types:: extra_props:: ExtData ,
68+ /// Context PhantomData. Only accessible inside this crate
69+ phantom : PhantomData < Ctx > ,
8770 }
71+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > Miniscript < Pk , Ctx > {
72+
73+ /// Add type information(Type and Extdata) to Miniscript based on
74+ /// `AstElem` fragment. Dependent on display and clone because of Error
75+ /// Display code of type_check.
76+ pub fn from_ast ( t : Terminal < Pk , Ctx > ) -> Result < Miniscript < Pk , Ctx > , Error > {
77+ let res = Miniscript {
78+ ty : Type :: type_check ( & t) ?,
79+ ext : ExtData :: type_check ( & t) ?,
80+ node : t,
81+ phantom : PhantomData ,
82+ } ;
83+ // TODO: This recursion depth is based on segwitv0.
84+ // We can relax this in tapscript, but this should be good for almost
85+ // all practical cases and we can revisit this if needed.
86+ // casting to u32 is safe because tree_height will never go more than u32::MAX
87+ if ( res. ext . tree_height as u32 ) > MAX_RECURSION_DEPTH {
88+ return Err ( Error :: MaxRecursiveDepthExceeded ) ;
89+ }
90+ Ctx :: check_global_consensus_validity ( & res) ?;
91+ Ok ( res)
92+ }
8893
89- /// Create a new `Miniscript` from a `Terminal` node and a `Type` annotation
90- /// This does not check the typing rules. The user is responsible for ensuring
91- /// that the type provided is correct.
92- ///
93- /// You should almost always use `Miniscript::from_ast` instead of this function.
94- pub fn from_components_unchecked (
95- node : Terminal < Pk , Ctx > ,
96- ty : types:: Type ,
97- ext : types:: extra_props:: ExtData ,
98- ) -> Miniscript < Pk , Ctx > {
99- Miniscript { node, ty, ext, phantom : PhantomData }
94+ /// Create a new `Miniscript` from a `Terminal` node and a `Type` annotation
95+ /// This does not check the typing rules. The user is responsible for ensuring
96+ /// that the type provided is correct.
97+ ///
98+ /// You should almost always use `Miniscript::from_ast` instead of this function.
99+ pub fn from_components_unchecked (
100+ node : Terminal < Pk , Ctx > ,
101+ ty : types:: Type ,
102+ ext : types:: extra_props:: ExtData ,
103+ ) -> Miniscript < Pk , Ctx > {
104+ Miniscript { node, ty, ext, phantom : PhantomData }
105+ }
100106 }
107+ }
108+
109+ pub use private:: Miniscript ;
101110
111+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > Miniscript < Pk , Ctx > {
102112 /// Extracts the `AstElem` representing the root of the miniscript
103113 pub fn into_inner ( self ) -> Terminal < Pk , Ctx > { self . node }
104114
@@ -603,7 +613,6 @@ pub mod hash256 {
603613#[ cfg( test) ]
604614mod tests {
605615
606- use core:: marker:: PhantomData ;
607616 use core:: str;
608617 use core:: str:: FromStr ;
609618
@@ -614,7 +623,7 @@ mod tests {
614623 use sync:: Arc ;
615624
616625 use super :: { Miniscript , ScriptContext , Segwitv0 , Tap } ;
617- use crate :: miniscript:: types:: { self , ExtData , Property , Type } ;
626+ use crate :: miniscript:: types;
618627 use crate :: miniscript:: Terminal ;
619628 use crate :: policy:: Liftable ;
620629 use crate :: { prelude:: * , Error } ;
@@ -800,21 +809,15 @@ mod tests {
800809 . unwrap ( ) ;
801810 let hash = hash160:: Hash :: from_byte_array ( [ 17 ; 20 ] ) ;
802811
803- let pk_node = Terminal :: Check ( Arc :: new ( Miniscript {
804- node : Terminal :: PkK ( String :: from ( "" ) ) ,
805- ty : Type :: from_pk_k :: < Segwitv0 > ( ) ,
806- ext : types:: extra_props:: ExtData :: from_pk_k :: < Segwitv0 > ( ) ,
807- phantom : PhantomData ,
808- } ) ) ;
812+ let pk_node = Terminal :: Check ( Arc :: new (
813+ Miniscript :: from_ast ( Terminal :: PkK ( String :: from ( "" ) ) ) . unwrap ( ) ,
814+ ) ) ;
809815 let pkk_ms: Miniscript < String , Segwitv0 > = Miniscript :: from_ast ( pk_node) . unwrap ( ) ;
810816 dummy_string_rtt ( pkk_ms, "[B/onduesm]c:[K/onduesm]pk_k(\" \" )" , "pk()" ) ;
811817
812- let pkh_node = Terminal :: Check ( Arc :: new ( Miniscript {
813- node : Terminal :: PkH ( String :: from ( "" ) ) ,
814- ty : Type :: from_pk_h :: < Segwitv0 > ( ) ,
815- ext : types:: extra_props:: ExtData :: from_pk_h :: < Segwitv0 > ( ) ,
816- phantom : PhantomData ,
817- } ) ) ;
818+ let pkh_node = Terminal :: Check ( Arc :: new (
819+ Miniscript :: from_ast ( Terminal :: PkH ( String :: from ( "" ) ) ) . unwrap ( ) ,
820+ ) ) ;
818821 let pkh_ms: Miniscript < String , Segwitv0 > = Miniscript :: from_ast ( pkh_node) . unwrap ( ) ;
819822
820823 let expected_debug = "[B/nduesm]c:[K/nduesm]pk_h(\" \" )" ;
@@ -830,12 +833,7 @@ mod tests {
830833 assert_eq ! ( display, expected) ;
831834 }
832835
833- let pkk_node = Terminal :: Check ( Arc :: new ( Miniscript {
834- node : Terminal :: PkK ( pk) ,
835- ty : Type :: from_pk_k :: < Segwitv0 > ( ) ,
836- ext : types:: extra_props:: ExtData :: from_pk_k :: < Segwitv0 > ( ) ,
837- phantom : PhantomData ,
838- } ) ) ;
836+ let pkk_node = Terminal :: Check ( Arc :: new ( Miniscript :: from_ast ( Terminal :: PkK ( pk) ) . unwrap ( ) ) ) ;
839837 let pkk_ms: Segwitv0Script = Miniscript :: from_ast ( pkk_node) . unwrap ( ) ;
840838
841839 script_rtt (
@@ -844,17 +842,10 @@ mod tests {
844842 202020202ac",
845843 ) ;
846844
847- let pkh_ms: Segwitv0Script = Miniscript {
848- node : Terminal :: Check ( Arc :: new ( Miniscript {
849- node : Terminal :: RawPkH ( hash) ,
850- ty : Type :: from_pk_h :: < Segwitv0 > ( ) ,
851- ext : types:: extra_props:: ExtData :: from_pk_h :: < Segwitv0 > ( ) ,
852- phantom : PhantomData ,
853- } ) ) ,
854- ty : Type :: cast_check ( Type :: from_pk_h :: < Segwitv0 > ( ) ) . unwrap ( ) ,
855- ext : ExtData :: cast_check ( ExtData :: from_pk_h :: < Segwitv0 > ( ) ) . unwrap ( ) ,
856- phantom : PhantomData ,
857- } ;
845+ let pkh_ms: Segwitv0Script = Miniscript :: from_ast ( Terminal :: Check ( Arc :: new (
846+ Miniscript :: from_ast ( Terminal :: RawPkH ( hash) ) . unwrap ( ) ,
847+ ) ) )
848+ . unwrap ( ) ;
858849
859850 script_rtt ( pkh_ms, "76a914111111111111111111111111111111111111111188ac" ) ;
860851 }
@@ -1366,4 +1357,13 @@ mod tests {
13661357 Err ( Error :: MaxRecursiveDepthExceeded )
13671358 ) ;
13681359 }
1360+
1361+ #[ test]
1362+ fn test_script_parse_dos ( ) {
1363+ let mut script = bitcoin:: script:: Builder :: new ( ) . push_opcode ( bitcoin:: opcodes:: OP_TRUE ) ;
1364+ for _ in 0 ..10000 {
1365+ script = script. push_opcode ( bitcoin:: opcodes:: all:: OP_0NOTEQUAL ) ;
1366+ }
1367+ Tapscript :: parse_insane ( & script. into_script ( ) ) . unwrap_err ( ) ;
1368+ }
13691369}
0 commit comments