12
12
//! components of the AST.
13
13
//!
14
14
15
- use core:: marker:: PhantomData ;
16
15
use core:: { fmt, hash, str} ;
17
16
18
17
use bitcoin:: hashes:: hash160;
@@ -23,7 +22,7 @@ use self::analyzable::ExtParams;
23
22
pub use self :: context:: { BareCtx , Legacy , Segwitv0 , Tap } ;
24
23
use crate :: iter:: TreeLike ;
25
24
use crate :: prelude:: * ;
26
- use crate :: { script_num_size, TranslateErr , MAX_RECURSION_DEPTH } ;
25
+ use crate :: { script_num_size, TranslateErr } ;
27
26
28
27
pub mod analyzable;
29
28
pub mod astelem;
@@ -42,79 +41,89 @@ use sync::Arc;
42
41
use self :: lex:: { lex, TokenIter } ;
43
42
pub use crate :: miniscript:: context:: ScriptContext ;
44
43
use crate :: miniscript:: decode:: Terminal ;
45
- use crate :: miniscript:: types:: extra_props:: ExtData ;
46
- use crate :: miniscript:: types:: Type ;
47
44
use crate :: {
48
45
expression, plan, Error , ForEachKey , FromStrKey , MiniscriptKey , ToPublicKey , TranslatePk ,
49
46
Translator ,
50
47
} ;
51
48
#[ cfg( test) ]
52
49
mod ms_tests;
53
50
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 ;
66
53
67
- impl < Pk : MiniscriptKey , Ctx : ScriptContext > Miniscript < Pk , Ctx > {
68
- /// The `1` combinator.
69
- pub const TRUE : Self = Miniscript {
70
- node : Terminal :: True ,
71
- ty : types:: Type :: TRUE ,
72
- ext : types:: extra_props:: ExtData :: TRUE ,
73
- phantom : PhantomData ,
74
- } ;
75
-
76
- /// The `0` combinator.
77
- pub const FALSE : Self = Miniscript {
78
- node : Terminal :: False ,
79
- ty : types:: Type :: FALSE ,
80
- ext : types:: extra_props:: ExtData :: FALSE ,
81
- phantom : PhantomData ,
82
- } ;
83
-
84
- /// Add type information(Type and Extdata) to Miniscript based on
85
- /// `AstElem` fragment. Dependent on display and clone because of Error
86
- /// Display code of type_check.
87
- pub fn from_ast ( t : Terminal < Pk , Ctx > ) -> Result < Miniscript < Pk , Ctx > , Error > {
88
- let res = Miniscript {
89
- ty : Type :: type_check ( & t) ?,
90
- ext : ExtData :: type_check ( & t) ?,
91
- node : t,
54
+ use super :: types:: { ExtData , 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 > ,
70
+ }
71
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > Miniscript < Pk , Ctx > {
72
+ /// The `1` combinator.
73
+ pub const TRUE : Self = Miniscript {
74
+ node : Terminal :: True ,
75
+ ty : types:: Type :: TRUE ,
76
+ ext : types:: extra_props:: ExtData :: TRUE ,
92
77
phantom : PhantomData ,
93
78
} ;
94
- // TODO: This recursion depth is based on segwitv0.
95
- // We can relax this in tapscript, but this should be good for almost
96
- // all practical cases and we can revisit this if needed.
97
- // casting to u32 is safe because tree_height will never go more than u32::MAX
98
- if ( res. ext . tree_height as u32 ) > MAX_RECURSION_DEPTH {
99
- return Err ( Error :: MaxRecursiveDepthExceeded ) ;
79
+
80
+ /// The `0` combinator.
81
+ pub const FALSE : Self = Miniscript {
82
+ node : Terminal :: False ,
83
+ ty : types:: Type :: FALSE ,
84
+ ext : types:: extra_props:: ExtData :: FALSE ,
85
+ phantom : PhantomData ,
86
+ } ;
87
+
88
+ /// Add type information(Type and Extdata) to Miniscript based on
89
+ /// `AstElem` fragment. Dependent on display and clone because of Error
90
+ /// Display code of type_check.
91
+ pub fn from_ast ( t : Terminal < Pk , Ctx > ) -> Result < Miniscript < Pk , Ctx > , Error > {
92
+ let res = Miniscript {
93
+ ty : Type :: type_check ( & t) ?,
94
+ ext : ExtData :: type_check ( & t) ?,
95
+ node : t,
96
+ phantom : PhantomData ,
97
+ } ;
98
+ // TODO: This recursion depth is based on segwitv0.
99
+ // We can relax this in tapscript, but this should be good for almost
100
+ // all practical cases and we can revisit this if needed.
101
+ // casting to u32 is safe because tree_height will never go more than u32::MAX
102
+ if ( res. ext . tree_height as u32 ) > MAX_RECURSION_DEPTH {
103
+ return Err ( Error :: MaxRecursiveDepthExceeded ) ;
104
+ }
105
+ Ctx :: check_global_consensus_validity ( & res) ?;
106
+ Ok ( res)
100
107
}
101
- Ctx :: check_global_consensus_validity ( & res) ?;
102
- Ok ( res)
103
- }
104
108
105
- /// Create a new `Miniscript` from a `Terminal` node and a `Type` annotation
106
- /// This does not check the typing rules. The user is responsible for ensuring
107
- /// that the type provided is correct.
108
- ///
109
- /// You should almost always use `Miniscript::from_ast` instead of this function.
110
- pub fn from_components_unchecked (
111
- node : Terminal < Pk , Ctx > ,
112
- ty : types:: Type ,
113
- ext : types:: extra_props:: ExtData ,
114
- ) -> Miniscript < Pk , Ctx > {
115
- Miniscript { node, ty, ext, phantom : PhantomData }
109
+ /// Create a new `Miniscript` from a `Terminal` node and a `Type` annotation
110
+ /// This does not check the typing rules. The user is responsible for ensuring
111
+ /// that the type provided is correct.
112
+ ///
113
+ /// You should almost always use `Miniscript::from_ast` instead of this function.
114
+ pub fn from_components_unchecked (
115
+ node : Terminal < Pk , Ctx > ,
116
+ ty : types:: Type ,
117
+ ext : types:: extra_props:: ExtData ,
118
+ ) -> Miniscript < Pk , Ctx > {
119
+ Miniscript { node, ty, ext, phantom : PhantomData }
120
+ }
116
121
}
122
+ }
117
123
124
+ pub use private:: Miniscript ;
125
+
126
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > Miniscript < Pk , Ctx > {
118
127
/// Extracts the `AstElem` representing the root of the miniscript
119
128
pub fn into_inner ( self ) -> Terminal < Pk , Ctx > { self . node }
120
129
@@ -700,7 +709,6 @@ pub mod hash256 {
700
709
#[ cfg( test) ]
701
710
mod tests {
702
711
703
- use core:: marker:: PhantomData ;
704
712
use core:: str;
705
713
use core:: str:: FromStr ;
706
714
@@ -710,8 +718,7 @@ mod tests {
710
718
use sync:: Arc ;
711
719
712
720
use super :: { Miniscript , ScriptContext , Segwitv0 , Tap } ;
713
- use crate :: miniscript:: types:: { self , ExtData , Type } ;
714
- use crate :: miniscript:: Terminal ;
721
+ use crate :: miniscript:: { types, Terminal } ;
715
722
use crate :: policy:: Liftable ;
716
723
use crate :: prelude:: * ;
717
724
use crate :: test_utils:: { StrKeyTranslator , StrXOnlyKeyTranslator } ;
@@ -896,21 +903,15 @@ mod tests {
896
903
. unwrap ( ) ;
897
904
let hash = hash160:: Hash :: from_byte_array ( [ 17 ; 20 ] ) ;
898
905
899
- let pk_node = Terminal :: Check ( Arc :: new ( Miniscript {
900
- node : Terminal :: PkK ( String :: from ( "" ) ) ,
901
- ty : Type :: pk_k ( ) ,
902
- ext : types:: extra_props:: ExtData :: pk_k :: < Segwitv0 > ( ) ,
903
- phantom : PhantomData ,
904
- } ) ) ;
906
+ let pk_node = Terminal :: Check ( Arc :: new (
907
+ Miniscript :: from_ast ( Terminal :: PkK ( String :: from ( "" ) ) ) . unwrap ( ) ,
908
+ ) ) ;
905
909
let pkk_ms: Miniscript < String , Segwitv0 > = Miniscript :: from_ast ( pk_node) . unwrap ( ) ;
906
910
dummy_string_rtt ( pkk_ms, "[B/onduesm]pk(\" \" )" , "pk()" ) ;
907
911
908
- let pkh_node = Terminal :: Check ( Arc :: new ( Miniscript {
909
- node : Terminal :: PkH ( String :: from ( "" ) ) ,
910
- ty : Type :: pk_h ( ) ,
911
- ext : types:: extra_props:: ExtData :: pk_h :: < Segwitv0 > ( ) ,
912
- phantom : PhantomData ,
913
- } ) ) ;
912
+ let pkh_node = Terminal :: Check ( Arc :: new (
913
+ Miniscript :: from_ast ( Terminal :: PkH ( String :: from ( "" ) ) ) . unwrap ( ) ,
914
+ ) ) ;
914
915
let pkh_ms: Miniscript < String , Segwitv0 > = Miniscript :: from_ast ( pkh_node) . unwrap ( ) ;
915
916
916
917
let expected_debug = "[B/nduesm]pkh(\" \" )" ;
@@ -926,12 +927,7 @@ mod tests {
926
927
assert_eq ! ( display, expected) ;
927
928
}
928
929
929
- let pkk_node = Terminal :: Check ( Arc :: new ( Miniscript {
930
- node : Terminal :: PkK ( pk) ,
931
- ty : Type :: pk_k ( ) ,
932
- ext : types:: extra_props:: ExtData :: pk_k :: < Segwitv0 > ( ) ,
933
- phantom : PhantomData ,
934
- } ) ) ;
930
+ let pkk_node = Terminal :: Check ( Arc :: new ( Miniscript :: from_ast ( Terminal :: PkK ( pk) ) . unwrap ( ) ) ) ;
935
931
let pkk_ms: Segwitv0Script = Miniscript :: from_ast ( pkk_node) . unwrap ( ) ;
936
932
937
933
script_rtt (
@@ -940,17 +936,10 @@ mod tests {
940
936
202020202ac",
941
937
) ;
942
938
943
- let pkh_ms: Segwitv0Script = Miniscript {
944
- node : Terminal :: Check ( Arc :: new ( Miniscript {
945
- node : Terminal :: RawPkH ( hash) ,
946
- ty : Type :: pk_h ( ) ,
947
- ext : types:: extra_props:: ExtData :: pk_h :: < Segwitv0 > ( ) ,
948
- phantom : PhantomData ,
949
- } ) ) ,
950
- ty : Type :: cast_check ( Type :: pk_h ( ) ) . unwrap ( ) ,
951
- ext : ExtData :: cast_check ( ExtData :: pk_h :: < Segwitv0 > ( ) ) ,
952
- phantom : PhantomData ,
953
- } ;
939
+ let pkh_ms: Segwitv0Script = Miniscript :: from_ast ( Terminal :: Check ( Arc :: new (
940
+ Miniscript :: from_ast ( Terminal :: RawPkH ( hash) ) . unwrap ( ) ,
941
+ ) ) )
942
+ . unwrap ( ) ;
954
943
955
944
script_rtt ( pkh_ms, "76a914111111111111111111111111111111111111111188ac" ) ;
956
945
}
@@ -1462,6 +1451,15 @@ mod tests {
1462
1451
Err ( Error :: MaxRecursiveDepthExceeded )
1463
1452
) ;
1464
1453
}
1454
+
1455
+ #[ test]
1456
+ fn test_script_parse_dos ( ) {
1457
+ let mut script = bitcoin:: script:: Builder :: new ( ) . push_opcode ( bitcoin:: opcodes:: OP_TRUE ) ;
1458
+ for _ in 0 ..10000 {
1459
+ script = script. push_opcode ( bitcoin:: opcodes:: all:: OP_0NOTEQUAL ) ;
1460
+ }
1461
+ Tapscript :: parse_insane ( & script. into_script ( ) ) . unwrap_err ( ) ;
1462
+ }
1465
1463
}
1466
1464
1467
1465
#[ cfg( bench) ]
0 commit comments