1use core::ops::Deref;
9
10use sync::Arc;
11
12use super::decode::Terminal;
13use super::{Miniscript, MiniscriptKey, ScriptContext};
14use crate::prelude::*;
15
16impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
18 pub fn iter(&self) -> Iter<'_, Pk, Ctx> { Iter::new(self) }
22
23 pub fn iter_pk(&self) -> PkIter<'_, Pk, Ctx> { PkIter::new(self) }
27
28 pub fn branches(&self) -> Vec<&Miniscript<Pk, Ctx>> {
31 match self.node {
32 Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) | Terminal::Multi(_) => {
33 vec![]
34 }
35
36 Terminal::Alt(ref node)
37 | Terminal::Swap(ref node)
38 | Terminal::Check(ref node)
39 | Terminal::DupIf(ref node)
40 | Terminal::Verify(ref node)
41 | Terminal::NonZero(ref node)
42 | Terminal::ZeroNotEqual(ref node) => vec![node],
43
44 Terminal::AndV(ref node1, ref node2)
45 | Terminal::AndB(ref node1, ref node2)
46 | Terminal::OrB(ref node1, ref node2)
47 | Terminal::OrD(ref node1, ref node2)
48 | Terminal::OrC(ref node1, ref node2)
49 | Terminal::OrI(ref node1, ref node2) => vec![node1, node2],
50
51 Terminal::AndOr(ref node1, ref node2, ref node3) => vec![node1, node2, node3],
52
53 Terminal::Thresh(ref thresh) => thresh.iter().map(Arc::deref).collect(),
54
55 _ => vec![],
56 }
57 }
58
59 pub fn get_nth_child(&self, n: usize) -> Option<&Miniscript<Pk, Ctx>> {
61 match (n, &self.node) {
62 (0, Terminal::Alt(node))
63 | (0, Terminal::Swap(node))
64 | (0, Terminal::Check(node))
65 | (0, Terminal::DupIf(node))
66 | (0, Terminal::Verify(node))
67 | (0, Terminal::NonZero(node))
68 | (0, Terminal::ZeroNotEqual(node))
69 | (0, Terminal::AndV(node, _))
70 | (0, Terminal::AndB(node, _))
71 | (0, Terminal::OrB(node, _))
72 | (0, Terminal::OrD(node, _))
73 | (0, Terminal::OrC(node, _))
74 | (0, Terminal::OrI(node, _))
75 | (1, Terminal::AndV(_, node))
76 | (1, Terminal::AndB(_, node))
77 | (1, Terminal::OrB(_, node))
78 | (1, Terminal::OrD(_, node))
79 | (1, Terminal::OrC(_, node))
80 | (1, Terminal::OrI(_, node))
81 | (0, Terminal::AndOr(node, _, _))
82 | (1, Terminal::AndOr(_, node, _))
83 | (2, Terminal::AndOr(_, _, node)) => Some(node),
84
85 (n, Terminal::Thresh(thresh)) => thresh.data().get(n).map(|x| &**x),
86
87 _ => None,
88 }
89 }
90
91 pub fn get_nth_pk(&self, n: usize) -> Option<Pk> {
96 match (&self.node, n) {
97 (Terminal::PkK(key), 0) | (Terminal::PkH(key), 0) => Some(key.clone()),
98 (Terminal::Multi(thresh), _) => thresh.data().get(n).cloned(),
99 (Terminal::MultiA(thresh), _) => thresh.data().get(n).cloned(),
100 _ => None,
101 }
102 }
103}
104
105pub struct Iter<'a, Pk: MiniscriptKey, Ctx: ScriptContext> {
108 next: Option<&'a Miniscript<Pk, Ctx>>,
109 path: Vec<(&'a Miniscript<Pk, Ctx>, usize)>,
113}
114
115impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iter<'a, Pk, Ctx> {
116 fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
117 Iter { next: Some(miniscript), path: vec![] }
118 }
119}
120
121impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for Iter<'a, Pk, Ctx> {
122 type Item = &'a Miniscript<Pk, Ctx>;
123
124 fn next(&mut self) -> Option<Self::Item> {
146 let mut curr = self.next;
147 if curr.is_none() {
148 while let Some((node, child)) = self.path.pop() {
149 curr = node.get_nth_child(child);
150 if curr.is_some() {
151 self.path.push((node, child + 1));
152 break;
153 }
154 }
155 }
156 if let Some(node) = curr {
157 self.next = node.get_nth_child(0);
158 self.path.push((node, 1));
159 }
160 curr
161 }
162}
163
164pub struct PkIter<'a, Pk: MiniscriptKey, Ctx: ScriptContext> {
167 node_iter: Iter<'a, Pk, Ctx>,
168 curr_node: Option<&'a Miniscript<Pk, Ctx>>,
169 key_index: usize,
170}
171
172impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> PkIter<'a, Pk, Ctx> {
173 fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
174 let mut iter = Iter::new(miniscript);
175 PkIter { curr_node: iter.next(), node_iter: iter, key_index: 0 }
176 }
177}
178
179impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for PkIter<'a, Pk, Ctx> {
180 type Item = Pk;
181
182 fn next(&mut self) -> Option<Self::Item> {
183 loop {
184 match self.curr_node {
185 None => break None,
186 Some(node) => match node.get_nth_pk(self.key_index) {
187 None => {
188 self.curr_node = self.node_iter.next();
189 self.key_index = 0;
190 continue;
191 }
192 Some(pk) => {
193 self.key_index += 1;
194 break Some(pk);
195 }
196 },
197 }
198 }
199 }
200}
201
202#[cfg(test)]
205pub mod test {
206 use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
207
208 use super::Miniscript;
209 use crate::miniscript::context::Segwitv0;
210
211 pub type TestData = (
213 Miniscript<bitcoin::PublicKey, Segwitv0>,
214 Vec<bitcoin::PublicKey>,
215 Vec<hash160::Hash>,
216 bool, );
218
219 pub fn gen_secp_pubkeys(n: usize) -> Vec<secp256k1::PublicKey> {
221 let mut ret = Vec::with_capacity(n);
222 let secp = secp256k1::Secp256k1::new();
223 let mut sk = [0; 32];
224
225 for i in 1..n + 1 {
226 sk[0] = i as u8;
227 sk[1] = (i >> 8) as u8;
228 sk[2] = (i >> 16) as u8;
229
230 ret.push(secp256k1::PublicKey::from_secret_key(
231 &secp,
232 &secp256k1::SecretKey::from_slice(&sk[..]).unwrap(),
233 ));
234 }
235 ret
236 }
237
238 pub fn gen_bitcoin_pubkeys(n: usize, compressed: bool) -> Vec<bitcoin::PublicKey> {
240 gen_secp_pubkeys(n)
241 .into_iter()
242 .map(|inner| bitcoin::PublicKey { inner, compressed })
243 .collect()
244 }
245
246 pub fn gen_testcases() -> Vec<TestData> {
248 let k = gen_bitcoin_pubkeys(10, true);
249 let _h: Vec<hash160::Hash> = k
250 .iter()
251 .map(|pk| hash160::Hash::hash(&pk.to_bytes()))
252 .collect();
253
254 let preimage = vec![0xab; 32];
255 let sha256_hash = sha256::Hash::hash(&preimage);
256 let sha256d_hash_rev = sha256d::Hash::hash(&preimage);
257 let mut sha256d_hash_bytes = sha256d_hash_rev.to_byte_array();
258 sha256d_hash_bytes.reverse();
259 let sha256d_hash = sha256d::Hash::from_byte_array(sha256d_hash_bytes);
260 let hash160_hash = hash160::Hash::hash(&preimage);
261 let ripemd160_hash = ripemd160::Hash::hash(&preimage);
262
263 vec![
264 (ms_str!("after({})", 1000), vec![], vec![], false),
265 (ms_str!("older({})", 1000), vec![], vec![], false),
266 (ms_str!("sha256({})", sha256_hash), vec![], vec![], false),
267 (ms_str!("hash256({})", sha256d_hash), vec![], vec![], false),
268 (ms_str!("hash160({})", hash160_hash), vec![], vec![], false),
269 (ms_str!("ripemd160({})", ripemd160_hash), vec![], vec![], false),
270 (ms_str!("c:pk_k({})", k[0]), vec![k[0]], vec![], true),
271 (ms_str!("c:pk_h({})", k[0]), vec![k[0]], vec![], true),
272 (
273 ms_str!("and_v(vc:pk_k({}),c:pk_h({}))", k[0], k[1]),
274 vec![k[0], k[1]],
275 vec![],
276 false,
277 ),
278 (
279 ms_str!("and_b(c:pk_k({}),sjtv:sha256({}))", k[0], sha256_hash),
280 vec![k[0]],
281 vec![],
282 false,
283 ),
284 (
285 ms_str!("andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))", k[1], sha256_hash, k[2]),
286 vec![k[1], k[2]],
287 vec![],
288 false,
289 ),
290 (
291 ms_str!("multi(3,{},{},{},{},{})", k[9], k[8], k[7], k[0], k[1]),
292 vec![k[9], k[8], k[7], k[0], k[1]],
293 vec![],
294 true,
295 ),
296 (
297 ms_str!(
298 "thresh(3,c:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}))",
299 k[2],
300 k[3],
301 k[4],
302 k[5],
303 k[6]
304 ),
305 vec![k[2], k[3], k[4], k[5], k[6]],
306 vec![],
307 false,
308 ),
309 (
310 ms_str!(
311 "or_d(multi(2,{},{}),and_v(v:multi(2,{},{}),older(10000)))",
312 k[6],
313 k[7],
314 k[8],
315 k[9]
316 ),
317 vec![k[6], k[7], k[8], k[9]],
318 vec![],
319 false,
320 ),
321 (
322 ms_str!(
323 "or_d(multi(3,{},{},{},{},{}),\
324 and_v(v:thresh(2,c:pk_h({}),\
325 ac:pk_h({}),ac:pk_h({})),older(10000)))",
326 k[0],
327 k[2],
328 k[4],
329 k[6],
330 k[9],
331 k[1],
332 k[3],
333 k[5]
334 ),
335 vec![k[0], k[2], k[4], k[6], k[9], k[1], k[3], k[5]],
336 vec![],
337 false,
338 ),
339 ]
340 }
341
342 #[test]
343 fn find_keys() {
344 gen_testcases().into_iter().for_each(|(ms, k, _, _)| {
345 assert_eq!(ms.iter_pk().collect::<Vec<bitcoin::PublicKey>>(), k);
346 })
347 }
348}