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;
@@ -22,7 +21,7 @@ use bitcoin::taproot::{LeafVersion, TapLeafHash};
22
21
use self :: analyzable:: ExtParams ;
23
22
pub use self :: context:: { BareCtx , Legacy , Segwitv0 , Tap } ;
24
23
use crate :: iter:: TreeLike ;
25
- use crate :: { prelude:: * , MAX_RECURSION_DEPTH } ;
24
+ use crate :: prelude:: * ;
26
25
use crate :: { script_num_size, TranslateErr } ;
27
26
28
27
pub mod analyzable;
@@ -43,62 +42,73 @@ use self::lex::{lex, TokenIter};
43
42
use self :: types:: Property ;
44
43
pub use crate :: miniscript:: context:: ScriptContext ;
45
44
use crate :: miniscript:: decode:: Terminal ;
46
- use crate :: miniscript:: types:: extra_props:: ExtData ;
47
- use crate :: miniscript:: types:: Type ;
48
45
use crate :: {
49
46
expression, plan, Error , ForEachKey , MiniscriptKey , ToPublicKey , TranslatePk , 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
- /// 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 > ,
87
70
}
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
+ }
88
93
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
+ }
100
106
}
107
+ }
108
+
109
+ pub use private:: Miniscript ;
101
110
111
+ impl < Pk : MiniscriptKey , Ctx : ScriptContext > Miniscript < Pk , Ctx > {
102
112
/// Extracts the `AstElem` representing the root of the miniscript
103
113
pub fn into_inner ( self ) -> Terminal < Pk , Ctx > { self . node }
104
114
@@ -603,7 +613,6 @@ pub mod hash256 {
603
613
#[ cfg( test) ]
604
614
mod tests {
605
615
606
- use core:: marker:: PhantomData ;
607
616
use core:: str;
608
617
use core:: str:: FromStr ;
609
618
@@ -614,7 +623,7 @@ mod tests {
614
623
use sync:: Arc ;
615
624
616
625
use super :: { Miniscript , ScriptContext , Segwitv0 , Tap } ;
617
- use crate :: miniscript:: types:: { self , ExtData , Property , Type } ;
626
+ use crate :: miniscript:: types;
618
627
use crate :: miniscript:: Terminal ;
619
628
use crate :: policy:: Liftable ;
620
629
use crate :: { prelude:: * , Error } ;
@@ -800,21 +809,15 @@ mod tests {
800
809
. unwrap ( ) ;
801
810
let hash = hash160:: Hash :: from_byte_array ( [ 17 ; 20 ] ) ;
802
811
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
+ ) ) ;
809
815
let pkk_ms: Miniscript < String , Segwitv0 > = Miniscript :: from_ast ( pk_node) . unwrap ( ) ;
810
816
dummy_string_rtt ( pkk_ms, "[B/onduesm]c:[K/onduesm]pk_k(\" \" )" , "pk()" ) ;
811
817
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
+ ) ) ;
818
821
let pkh_ms: Miniscript < String , Segwitv0 > = Miniscript :: from_ast ( pkh_node) . unwrap ( ) ;
819
822
820
823
let expected_debug = "[B/nduesm]c:[K/nduesm]pk_h(\" \" )" ;
@@ -830,12 +833,7 @@ mod tests {
830
833
assert_eq ! ( display, expected) ;
831
834
}
832
835
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 ( ) ) ) ;
839
837
let pkk_ms: Segwitv0Script = Miniscript :: from_ast ( pkk_node) . unwrap ( ) ;
840
838
841
839
script_rtt (
@@ -844,17 +842,10 @@ mod tests {
844
842
202020202ac",
845
843
) ;
846
844
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 ( ) ;
858
849
859
850
script_rtt ( pkh_ms, "76a914111111111111111111111111111111111111111188ac" ) ;
860
851
}
@@ -1366,4 +1357,13 @@ mod tests {
1366
1357
Err ( Error :: MaxRecursiveDepthExceeded )
1367
1358
) ;
1368
1359
}
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
+ }
1369
1369
}
0 commit comments