miniscript_debug/miniscript/types/
malleability.rs1use super::{ErrorKind, Property};
18use crate::ScriptContext;
19
20#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
25pub enum Dissat {
26 None,
29 Unique,
34 Unknown,
39}
40
41impl Dissat {
42 fn is_subtype(&self, other: Self) -> bool {
45 match (*self, other) {
46 (x, y) if x == y => true,
47 (_, Dissat::Unknown) => true,
48 _ => false,
49 }
50 }
51}
52
53#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
56pub struct Malleability {
57 pub dissat: Dissat,
59 pub safe: bool,
64 pub non_malleable: bool,
67}
68
69impl Malleability {
70 pub fn is_subtype(&self, other: Self) -> bool {
75 self.dissat.is_subtype(other.dissat)
76 && self.safe >= other.safe
77 && self.non_malleable >= other.non_malleable
78 }
79}
80
81impl Property for Malleability {
82 fn from_true() -> Self {
83 Malleability {
84 dissat: Dissat::None,
85 safe: false,
86 non_malleable: true,
87 }
88 }
89
90 fn from_false() -> Self {
91 Malleability {
92 dissat: Dissat::Unique,
93 safe: true,
94 non_malleable: true,
95 }
96 }
97
98 fn from_pk_k<Ctx: ScriptContext>() -> Self {
99 Malleability {
100 dissat: Dissat::Unique,
101 safe: true,
102 non_malleable: true,
103 }
104 }
105
106 fn from_pk_h<Ctx: ScriptContext>() -> Self {
107 Malleability {
108 dissat: Dissat::Unique,
109 safe: true,
110 non_malleable: true,
111 }
112 }
113
114 fn from_multi(_: usize, _: usize) -> Self {
115 Malleability {
116 dissat: Dissat::Unique,
117 safe: true,
118 non_malleable: true,
119 }
120 }
121
122 fn from_multi_a(_: usize, _: usize) -> Self {
123 Malleability {
124 dissat: Dissat::Unique,
125 safe: true,
126 non_malleable: true,
127 }
128 }
129
130 fn from_hash() -> Self {
131 Malleability {
132 dissat: Dissat::Unknown,
133 safe: false,
134 non_malleable: true,
135 }
136 }
137
138 fn from_time(_: u32) -> Self {
139 Malleability {
140 dissat: Dissat::None,
141 safe: false,
142 non_malleable: true,
143 }
144 }
145
146 fn cast_alt(self) -> Result<Self, ErrorKind> {
147 Ok(self)
148 }
149
150 fn cast_swap(self) -> Result<Self, ErrorKind> {
151 Ok(self)
152 }
153
154 fn cast_check(self) -> Result<Self, ErrorKind> {
155 Ok(self)
156 }
157
158 fn cast_dupif(self) -> Result<Self, ErrorKind> {
159 Ok(Malleability {
160 dissat: if self.dissat == Dissat::None {
161 Dissat::Unique
162 } else {
163 Dissat::Unknown
164 },
165 safe: self.safe,
166 non_malleable: self.non_malleable,
167 })
168 }
169
170 fn cast_verify(self) -> Result<Self, ErrorKind> {
171 Ok(Malleability {
172 dissat: Dissat::None,
173 safe: self.safe,
174 non_malleable: self.non_malleable,
175 })
176 }
177
178 fn cast_nonzero(self) -> Result<Self, ErrorKind> {
179 Ok(Malleability {
180 dissat: if self.dissat == Dissat::None {
181 Dissat::Unique
182 } else {
183 Dissat::Unknown
184 },
185 safe: self.safe,
186 non_malleable: self.non_malleable,
187 })
188 }
189
190 fn cast_zeronotequal(self) -> Result<Self, ErrorKind> {
191 Ok(self)
192 }
193
194 fn cast_true(self) -> Result<Self, ErrorKind> {
195 Ok(Malleability {
196 dissat: Dissat::None,
197 safe: self.safe,
198 non_malleable: self.non_malleable,
199 })
200 }
201
202 fn cast_or_i_false(self) -> Result<Self, ErrorKind> {
203 Ok(Malleability {
204 dissat: if self.dissat == Dissat::None {
205 Dissat::Unique
206 } else {
207 Dissat::Unknown
208 },
209 safe: self.safe,
210 non_malleable: self.non_malleable,
211 })
212 }
213
214 fn and_b(left: Self, right: Self) -> Result<Self, ErrorKind> {
215 Ok(Malleability {
216 dissat: match (left.dissat, right.dissat) {
217 (Dissat::None, Dissat::None) => Dissat::None,
218 (Dissat::None, _) if left.safe => Dissat::None,
219 (_, Dissat::None) if right.safe => Dissat::None,
220 (Dissat::Unique, Dissat::Unique) => {
221 if left.safe && right.safe {
222 Dissat::Unique
223 } else {
224 Dissat::Unknown
225 }
226 }
227 _ => Dissat::Unknown,
228 },
229 safe: left.safe || right.safe,
230 non_malleable: left.non_malleable && right.non_malleable,
231 })
232 }
233
234 fn and_v(left: Self, right: Self) -> Result<Self, ErrorKind> {
235 Ok(Malleability {
236 dissat: match (left.safe, right.dissat) {
237 (_, Dissat::None) => Dissat::None, (true, _) => Dissat::None, _ => Dissat::Unknown,
240 },
241 safe: left.safe || right.safe,
242 non_malleable: left.non_malleable && right.non_malleable,
243 })
244 }
245
246 fn or_b(left: Self, right: Self) -> Result<Self, ErrorKind> {
247 Ok(Malleability {
248 dissat: Dissat::Unique,
249 safe: left.safe && right.safe,
250 non_malleable: left.non_malleable
251 && left.dissat == Dissat::Unique
252 && right.non_malleable
253 && right.dissat == Dissat::Unique
254 && (left.safe || right.safe),
255 })
256 }
257
258 fn or_d(left: Self, right: Self) -> Result<Self, ErrorKind> {
259 Ok(Malleability {
260 dissat: right.dissat,
261 safe: left.safe && right.safe,
262 non_malleable: left.non_malleable
263 && left.dissat == Dissat::Unique
264 && right.non_malleable
265 && (left.safe || right.safe),
266 })
267 }
268
269 fn or_c(left: Self, right: Self) -> Result<Self, ErrorKind> {
270 Ok(Malleability {
271 dissat: Dissat::None,
272 safe: left.safe && right.safe,
273 non_malleable: left.non_malleable
274 && left.dissat == Dissat::Unique
275 && right.non_malleable
276 && (left.safe || right.safe),
277 })
278 }
279
280 fn or_i(left: Self, right: Self) -> Result<Self, ErrorKind> {
281 Ok(Malleability {
282 dissat: match (left.dissat, right.dissat) {
283 (Dissat::None, Dissat::None) => Dissat::None,
284 (Dissat::Unique, Dissat::None) => Dissat::Unique,
285 (Dissat::None, Dissat::Unique) => Dissat::Unique,
286 _ => Dissat::Unknown,
287 },
288 safe: left.safe && right.safe,
289 non_malleable: left.non_malleable && right.non_malleable && (left.safe || right.safe),
290 })
291 }
292
293 fn and_or(a: Self, b: Self, c: Self) -> Result<Self, ErrorKind> {
294 Ok(Malleability {
295 dissat: match (a.safe, b.dissat, c.dissat) {
296 (_, Dissat::None, Dissat::Unique) => Dissat::Unique, (true, _, Dissat::Unique) => Dissat::Unique, (_, Dissat::None, Dissat::None) => Dissat::None, (true, _, Dissat::None) => Dissat::None, _ => Dissat::Unknown,
301 },
302 safe: (a.safe || b.safe) && c.safe,
303 non_malleable: a.non_malleable
304 && c.non_malleable
305 && a.dissat == Dissat::Unique
306 && b.non_malleable
307 && (a.safe || b.safe || c.safe),
308 })
309 }
310
311 fn threshold<S>(k: usize, n: usize, mut sub_ck: S) -> Result<Self, ErrorKind>
312 where
313 S: FnMut(usize) -> Result<Self, ErrorKind>,
314 {
315 let mut safe_count = 0;
316 let mut all_are_dissat_unique = true;
317 let mut all_are_non_malleable = true;
318 for i in 0..n {
319 let subtype = sub_ck(i)?;
320 safe_count += if subtype.safe { 1 } else { 0 };
321 all_are_dissat_unique &= subtype.dissat == Dissat::Unique;
322 all_are_non_malleable &= subtype.non_malleable;
323 }
324 Ok(Malleability {
325 dissat: if all_are_dissat_unique && safe_count == n {
326 Dissat::Unique
327 } else {
328 Dissat::Unknown
329 },
330 safe: safe_count > n - k,
331 non_malleable: all_are_non_malleable && safe_count >= n - k && all_are_dissat_unique,
332 })
333 }
334}