@@ -22,7 +22,115 @@ use core::fmt;
22
22
use std:: error;
23
23
24
24
use crate :: prelude:: * ;
25
- use crate :: { Miniscript , MiniscriptKey , ScriptContext } ;
25
+ use crate :: { Miniscript , MiniscriptKey , ScriptContext , Terminal } ;
26
+
27
+ /// Params for parsing miniscripts that either non-sane or non-specified(experimental) in the spec.
28
+ /// Used as a parameter [`Miniscript::from_str_insane`] and [`Miniscript::parse_insane`].
29
+ ///
30
+ /// This allows parsing miniscripts if
31
+ /// 1. It is unsafe(does not require a digital signature to spend it)
32
+ /// 2. It contains a unspendable path because of either
33
+ /// a. Resource limitations
34
+ /// b. Timelock Mixing
35
+ /// 3. The script is malleable and thereby some of satisfaction weight
36
+ /// guarantees are not satisfied.
37
+ /// 4. It has repeated public keys
38
+ /// 5. raw pkh fragments without the pk. This could be obtained when parsing miniscript from script
39
+ #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Clone , Copy , Default ) ]
40
+ pub struct ExtParams {
41
+ /// Allow parsing of non-safe miniscripts
42
+ pub top_unsafe : bool ,
43
+ /// Allow parsing of miniscripts with unspendable paths
44
+ pub resource_limitations : bool ,
45
+ /// Allow parsing of miniscripts with timelock mixing
46
+ pub timelock_mixing : bool ,
47
+ /// Allow parsing of malleable miniscripts
48
+ pub malleability : bool ,
49
+ /// Allow parsing of miniscripts with repeated public keys
50
+ pub repeated_pk : bool ,
51
+ /// Allow parsing of miniscripts with raw pkh fragments without the pk.
52
+ /// This could be obtained when parsing miniscript from script
53
+ pub raw_pkh : bool ,
54
+ }
55
+
56
+ impl ExtParams {
57
+ /// Create a new ExtParams that with all the sanity rules
58
+ pub fn new ( ) -> ExtParams {
59
+ ExtParams {
60
+ top_unsafe : false ,
61
+ resource_limitations : false ,
62
+ timelock_mixing : false ,
63
+ malleability : false ,
64
+ repeated_pk : false ,
65
+ raw_pkh : false ,
66
+ }
67
+ }
68
+
69
+ /// Create a new ExtParams that allows all the sanity rules
70
+ pub fn sane ( ) -> ExtParams {
71
+ ExtParams :: new ( )
72
+ }
73
+
74
+ /// Create a new ExtParams that insanity rules
75
+ pub fn insane ( ) -> ExtParams {
76
+ ExtParams {
77
+ top_unsafe : true ,
78
+ resource_limitations : true ,
79
+ timelock_mixing : true ,
80
+ malleability : true ,
81
+ repeated_pk : true ,
82
+ raw_pkh : false ,
83
+ }
84
+ }
85
+
86
+ /// Enable all non-sane rules and experimental rules
87
+ pub fn all ( ) -> ExtParams {
88
+ ExtParams {
89
+ top_unsafe : true ,
90
+ resource_limitations : true ,
91
+ timelock_mixing : true ,
92
+ malleability : true ,
93
+ repeated_pk : true ,
94
+ raw_pkh : true ,
95
+ }
96
+ }
97
+
98
+ /// Builder that allows non-safe miniscripts.
99
+ pub fn top_unsafe ( mut self ) -> ExtParams {
100
+ self . top_unsafe = true ;
101
+ self
102
+ }
103
+
104
+ /// Builder that allows miniscripts with exceed resource limitations.
105
+ pub fn exceed_resource_limitations ( mut self ) -> ExtParams {
106
+ self . resource_limitations = true ;
107
+ self
108
+ }
109
+
110
+ /// Builder that allows miniscripts with timelock mixing.
111
+ pub fn timelock_mixing ( mut self ) -> ExtParams {
112
+ self . timelock_mixing = true ;
113
+ self
114
+ }
115
+
116
+ /// Builder that allows malleable miniscripts.
117
+ pub fn malleability ( mut self ) -> ExtParams {
118
+ self . malleability = true ;
119
+ self
120
+ }
121
+
122
+ /// Builder that allows miniscripts with repeated public keys.
123
+ pub fn repeated_pk ( mut self ) -> ExtParams {
124
+ self . repeated_pk = true ;
125
+ self
126
+ }
127
+
128
+ /// Builder that allows miniscripts with raw pkh fragments.
129
+ pub fn raw_pkh ( mut self ) -> ExtParams {
130
+ self . raw_pkh = true ;
131
+ self
132
+ }
133
+ }
26
134
27
135
/// Possible reasons Miniscript guarantees can fail
28
136
/// We currently mark Miniscript as Non-Analyzable if
@@ -45,6 +153,8 @@ pub enum AnalysisError {
45
153
HeightTimelockCombination ,
46
154
/// Malleable script
47
155
Malleable ,
156
+ /// Contains partial descriptor raw pkh
157
+ ContainsRawPkh ,
48
158
}
49
159
50
160
impl fmt:: Display for AnalysisError {
@@ -62,7 +172,8 @@ impl fmt::Display for AnalysisError {
62
172
AnalysisError :: HeightTimelockCombination => {
63
173
f. write_str ( "Contains a combination of heightlock and timelock" )
64
174
}
65
- AnalysisError :: Malleable => f. write_str ( "Miniscript is malleable" )
175
+ AnalysisError :: Malleable => f. write_str ( "Miniscript is malleable" ) ,
176
+ AnalysisError :: ContainsRawPkh => f. write_str ( "Miniscript contains raw pkh" ) ,
66
177
}
67
178
}
68
179
}
@@ -77,7 +188,8 @@ impl error::Error for AnalysisError {
77
188
| RepeatedPubkeys
78
189
| BranchExceedResouceLimits
79
190
| HeightTimelockCombination
80
- | Malleable => None ,
191
+ | Malleable
192
+ | ContainsRawPkh => None ,
81
193
}
82
194
}
83
195
}
@@ -116,6 +228,14 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
116
228
unique_pkhs_len != all_pkhs_len
117
229
}
118
230
231
+ /// Whether the given miniscript contains a raw pkh fragment
232
+ pub fn contains_raw_pkh ( & self ) -> bool {
233
+ self . iter ( ) . any ( |ms| match ms. node {
234
+ Terminal :: RawPkH ( _) => true ,
235
+ _ => false ,
236
+ } )
237
+ }
238
+
119
239
/// Check whether the underlying Miniscript is safe under the current context
120
240
/// Lifting these polices would create a semantic representation that does
121
241
/// not represent the underlying semantics when miniscript is spent.
@@ -140,4 +260,23 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
140
260
Ok ( ( ) )
141
261
}
142
262
}
263
+
264
+ /// Check whether the miniscript follows the given Extra policy [`ExtParams`]
265
+ pub fn ext_check ( & self , ext : & ExtParams ) -> Result < ( ) , AnalysisError > {
266
+ if !ext. top_unsafe && !self . requires_sig ( ) {
267
+ Err ( AnalysisError :: SiglessBranch )
268
+ } else if !ext. malleability && !self . is_non_malleable ( ) {
269
+ Err ( AnalysisError :: Malleable )
270
+ } else if !ext. resource_limitations && !self . within_resource_limits ( ) {
271
+ Err ( AnalysisError :: BranchExceedResouceLimits )
272
+ } else if !ext. repeated_pk && self . has_repeated_keys ( ) {
273
+ Err ( AnalysisError :: RepeatedPubkeys )
274
+ } else if !ext. timelock_mixing && self . has_mixed_timelocks ( ) {
275
+ Err ( AnalysisError :: HeightTimelockCombination )
276
+ } else if !ext. raw_pkh && self . contains_raw_pkh ( ) {
277
+ Err ( AnalysisError :: ContainsRawPkh )
278
+ } else {
279
+ Ok ( ( ) )
280
+ }
281
+ }
143
282
}
0 commit comments