1use core::ops::Deref;
20
21use sync::Arc;
22
23use super::decode::Terminal;
24use super::{Miniscript, MiniscriptKey, ScriptContext};
25use crate::prelude::*;
26
27impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
29 pub fn iter(&self) -> Iter<Pk, Ctx> {
33 Iter::new(self)
34 }
35
36 pub fn iter_pk(&self) -> PkIter<Pk, Ctx> {
40 PkIter::new(self)
41 }
42
43 pub fn branches(&self) -> Vec<&Miniscript<Pk, Ctx>> {
46 match self.node {
47 Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) | Terminal::Multi(_, _) => {
48 vec![]
49 }
50
51 Terminal::Alt(ref node)
52 | Terminal::Swap(ref node)
53 | Terminal::Check(ref node)
54 | Terminal::DupIf(ref node)
55 | Terminal::Verify(ref node)
56 | Terminal::NonZero(ref node)
57 | Terminal::ZeroNotEqual(ref node) => vec![node],
58
59 Terminal::AndV(ref node1, ref node2)
60 | Terminal::AndB(ref node1, ref node2)
61 | Terminal::OrB(ref node1, ref node2)
62 | Terminal::OrD(ref node1, ref node2)
63 | Terminal::OrC(ref node1, ref node2)
64 | Terminal::OrI(ref node1, ref node2) => vec![node1, node2],
65
66 Terminal::AndOr(ref node1, ref node2, ref node3) => vec![node1, node2, node3],
67
68 Terminal::Thresh(_, ref node_vec) => node_vec.iter().map(Arc::deref).collect(),
69
70 _ => vec![],
71 }
72 }
73
74 pub fn get_nth_child(&self, n: usize) -> Option<&Miniscript<Pk, Ctx>> {
76 match (n, &self.node) {
77 (0, &Terminal::Alt(ref node))
78 | (0, &Terminal::Swap(ref node))
79 | (0, &Terminal::Check(ref node))
80 | (0, &Terminal::DupIf(ref node))
81 | (0, &Terminal::Verify(ref node))
82 | (0, &Terminal::NonZero(ref node))
83 | (0, &Terminal::ZeroNotEqual(ref node))
84 | (0, &Terminal::AndV(ref node, _))
85 | (0, &Terminal::AndB(ref node, _))
86 | (0, &Terminal::OrB(ref node, _))
87 | (0, &Terminal::OrD(ref node, _))
88 | (0, &Terminal::OrC(ref node, _))
89 | (0, &Terminal::OrI(ref node, _))
90 | (1, &Terminal::AndV(_, ref node))
91 | (1, &Terminal::AndB(_, ref node))
92 | (1, &Terminal::OrB(_, ref node))
93 | (1, &Terminal::OrD(_, ref node))
94 | (1, &Terminal::OrC(_, ref node))
95 | (1, &Terminal::OrI(_, ref node))
96 | (0, &Terminal::AndOr(ref node, _, _))
97 | (1, &Terminal::AndOr(_, ref node, _))
98 | (2, &Terminal::AndOr(_, _, ref node)) => Some(node),
99
100 (n, &Terminal::Thresh(_, ref node_vec)) => node_vec.get(n).map(|x| &**x),
101
102 _ => None,
103 }
104 }
105
106 pub fn get_nth_pk(&self, n: usize) -> Option<Pk> {
111 match (&self.node, n) {
112 (&Terminal::PkK(ref key), 0) | (&Terminal::PkH(ref key), 0) => Some(key.clone()),
113 (&Terminal::Multi(_, ref keys), _) | (&Terminal::MultiA(_, ref keys), _) => {
114 keys.get(n).cloned()
115 }
116 _ => None,
117 }
118 }
119}
120
121pub struct Iter<'a, Pk: MiniscriptKey, Ctx: ScriptContext> {
124 next: Option<&'a Miniscript<Pk, Ctx>>,
125 path: Vec<(&'a Miniscript<Pk, Ctx>, usize)>,
129}
130
131impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iter<'a, Pk, Ctx> {
132 fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
133 Iter {
134 next: Some(miniscript),
135 path: vec![],
136 }
137 }
138}
139
140impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for Iter<'a, Pk, Ctx> {
141 type Item = &'a Miniscript<Pk, Ctx>;
142
143 fn next(&mut self) -> Option<Self::Item> {
165 let mut curr = self.next;
166 if curr.is_none() {
167 while let Some((node, child)) = self.path.pop() {
168 curr = node.get_nth_child(child);
169 if curr.is_some() {
170 self.path.push((node, child + 1));
171 break;
172 }
173 }
174 }
175 if let Some(node) = curr {
176 self.next = node.get_nth_child(0);
177 self.path.push((node, 1));
178 }
179 curr
180 }
181}
182
183pub struct PkIter<'a, Pk: MiniscriptKey, Ctx: ScriptContext> {
186 node_iter: Iter<'a, Pk, Ctx>,
187 curr_node: Option<&'a Miniscript<Pk, Ctx>>,
188 key_index: usize,
189}
190
191impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> PkIter<'a, Pk, Ctx> {
192 fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
193 let mut iter = Iter::new(miniscript);
194 PkIter {
195 curr_node: iter.next(),
196 node_iter: iter,
197 key_index: 0,
198 }
199 }
200}
201
202impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for PkIter<'a, Pk, Ctx> {
203 type Item = Pk;
204
205 fn next(&mut self) -> Option<Self::Item> {
206 loop {
207 match self.curr_node {
208 None => break None,
209 Some(node) => match node.get_nth_pk(self.key_index) {
210 None => {
211 self.curr_node = self.node_iter.next();
212 self.key_index = 0;
213 continue;
214 }
215 Some(pk) => {
216 self.key_index += 1;
217 break Some(pk);
218 }
219 },
220 }
221 }
222 }
223}
224
225#[cfg(test)]
228pub mod test {
229 use bitcoin;
230 use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
231 use bitcoin::secp256k1;
232
233 use super::Miniscript;
234 use crate::miniscript::context::Segwitv0;
235
236 pub type TestData = (
237 Miniscript<bitcoin::PublicKey, Segwitv0>,
238 Vec<bitcoin::PublicKey>,
239 Vec<hash160::Hash>,
240 bool, );
242
243 pub fn gen_secp_pubkeys(n: usize) -> Vec<secp256k1::PublicKey> {
244 let mut ret = Vec::with_capacity(n);
245 let secp = secp256k1::Secp256k1::new();
246 let mut sk = [0; 32];
247
248 for i in 1..n + 1 {
249 sk[0] = i as u8;
250 sk[1] = (i >> 8) as u8;
251 sk[2] = (i >> 16) as u8;
252
253 ret.push(secp256k1::PublicKey::from_secret_key(
254 &secp,
255 &secp256k1::SecretKey::from_slice(&sk[..]).unwrap(),
256 ));
257 }
258 ret
259 }
260
261 pub fn gen_bitcoin_pubkeys(n: usize, compressed: bool) -> Vec<bitcoin::PublicKey> {
262 gen_secp_pubkeys(n)
263 .into_iter()
264 .map(|inner| bitcoin::PublicKey { inner, compressed })
265 .collect()
266 }
267
268 pub fn gen_testcases() -> Vec<TestData> {
269 let k = gen_bitcoin_pubkeys(10, true);
270 let _h: Vec<hash160::Hash> = k
271 .iter()
272 .map(|pk| hash160::Hash::hash(&pk.to_bytes()))
273 .collect();
274
275 let preimage = vec![0xab as u8; 32];
276 let sha256_hash = sha256::Hash::hash(&preimage);
277 let sha256d_hash_rev = sha256d::Hash::hash(&preimage);
278 let mut sha256d_hash_bytes = sha256d_hash_rev.clone().into_inner();
279 sha256d_hash_bytes.reverse();
280 let sha256d_hash = sha256d::Hash::from_inner(sha256d_hash_bytes);
281 let hash160_hash = hash160::Hash::hash(&preimage);
282 let ripemd160_hash = ripemd160::Hash::hash(&preimage);
283
284 vec![
285 (ms_str!("after({})", 1000), vec![], vec![], false),
286 (ms_str!("older({})", 1000), vec![], vec![], false),
287 (ms_str!("sha256({})", sha256_hash), vec![], vec![], false),
288 (ms_str!("hash256({})", sha256d_hash), vec![], vec![], false),
289 (ms_str!("hash160({})", hash160_hash), vec![], vec![], false),
290 (
291 ms_str!("ripemd160({})", ripemd160_hash),
292 vec![],
293 vec![],
294 false,
295 ),
296 (ms_str!("c:pk_k({})", k[0]), vec![k[0]], vec![], true),
297 (ms_str!("c:pk_h({})", k[0]), vec![k[0]], vec![], true),
298 (
299 ms_str!("and_v(vc:pk_k({}),c:pk_h({}))", k[0], k[1]),
300 vec![k[0], k[1]],
301 vec![],
302 false,
303 ),
304 (
305 ms_str!("and_b(c:pk_k({}),sjtv:sha256({}))", k[0], sha256_hash),
306 vec![k[0]],
307 vec![],
308 false,
309 ),
310 (
311 ms_str!(
312 "andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))",
313 k[1],
314 sha256_hash,
315 k[2]
316 ),
317 vec![k[1], k[2]],
318 vec![],
319 false,
320 ),
321 (
322 ms_str!("multi(3,{},{},{},{},{})", k[9], k[8], k[7], k[0], k[1]),
323 vec![k[9], k[8], k[7], k[0], k[1]],
324 vec![],
325 true,
326 ),
327 (
328 ms_str!(
329 "thresh(3,c:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}))",
330 k[2],
331 k[3],
332 k[4],
333 k[5],
334 k[6]
335 ),
336 vec![k[2], k[3], k[4], k[5], k[6]],
337 vec![],
338 false,
339 ),
340 (
341 ms_str!(
342 "or_d(multi(2,{},{}),and_v(v:multi(2,{},{}),older(10000)))",
343 k[6],
344 k[7],
345 k[8],
346 k[9]
347 ),
348 vec![k[6], k[7], k[8], k[9]],
349 vec![],
350 false,
351 ),
352 (
353 ms_str!(
354 "or_d(multi(3,{},{},{},{},{}),\
355 and_v(v:thresh(2,c:pk_h({}),\
356 ac:pk_h({}),ac:pk_h({})),older(10000)))",
357 k[0],
358 k[2],
359 k[4],
360 k[6],
361 k[9],
362 k[1],
363 k[3],
364 k[5]
365 ),
366 vec![k[0], k[2], k[4], k[6], k[9], k[1], k[3], k[5]],
367 vec![],
368 false,
369 ),
370 ]
371 }
372
373 #[test]
374 fn find_keys() {
375 gen_testcases().into_iter().for_each(|(ms, k, _, _)| {
376 assert_eq!(ms.iter_pk().collect::<Vec<bitcoin::PublicKey>>(), k);
377 })
378 }
379}