sapio_miniscript/miniscript/
iter.rs

1// Miniscript
2// Written in 2020 by
3//     Dr Maxim Orlovsky <orlovsky@pandoracore.com>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! Miniscript Iterators
16//!
17//! Iterators for Miniscript with special functions for iterating
18//! over Public Keys, Public Key Hashes or both.
19use super::decode::Terminal;
20use super::{Miniscript, MiniscriptKey, ScriptContext};
21use std::ops::Deref;
22use std::sync::Arc;
23
24/// Iterator-related extensions for [Miniscript]
25impl<Pk: MiniscriptKey, Ctx: ScriptContext> Miniscript<Pk, Ctx> {
26    /// Creates a new [Iter] iterator that will iterate over all [Miniscript] items within
27    /// AST by traversing its branches. For the specific algorithm please see
28    /// [Iter::next] function.
29    pub fn iter(&self) -> Iter<Pk, Ctx> {
30        Iter::new(self)
31    }
32
33    /// Creates a new [PkIter] iterator that will iterate over all plain public keys (and not
34    /// key hash values) present in [Miniscript] items within AST by traversing all its branches.
35    /// For the specific algorithm please see [PkIter::next] function.
36    pub fn iter_pk(&self) -> PkIter<Pk, Ctx> {
37        PkIter::new(self)
38    }
39
40    /// Creates a new [PkhIter] iterator that will iterate over all public keys hashes (and not
41    /// plain public keys) present in Miniscript items within AST by traversing all its branches.
42    /// For the specific algorithm please see [PkhIter::next] function.
43    pub fn iter_pkh(&self) -> PkhIter<Pk, Ctx> {
44        PkhIter::new(self)
45    }
46
47    /// Creates a new [PkPkhIter] iterator that will iterate over all plain public keys and
48    /// key hash values present in Miniscript items within AST by traversing all its branches.
49    /// For the specific algorithm please see [PkPkhIter::next] function.
50    pub fn iter_pk_pkh(&self) -> PkPkhIter<Pk, Ctx> {
51        PkPkhIter::new(self)
52    }
53
54    /// Enumerates all child nodes of the current AST node (`self`) and returns a `Vec` referencing
55    /// them.
56    pub fn branches(&self) -> Vec<&Miniscript<Pk, Ctx>> {
57        match self.node {
58            Terminal::PkK(_) | Terminal::PkH(_) | Terminal::Multi(_, _) => vec![],
59
60            Terminal::Alt(ref node)
61            | Terminal::Swap(ref node)
62            | Terminal::Check(ref node)
63            | Terminal::DupIf(ref node)
64            | Terminal::Verify(ref node)
65            | Terminal::NonZero(ref node)
66            | Terminal::ZeroNotEqual(ref node) => vec![node],
67
68            Terminal::AndV(ref node1, ref node2)
69            | Terminal::AndB(ref node1, ref node2)
70            | Terminal::OrB(ref node1, ref node2)
71            | Terminal::OrD(ref node1, ref node2)
72            | Terminal::OrC(ref node1, ref node2)
73            | Terminal::OrI(ref node1, ref node2) => vec![node1, node2],
74
75            Terminal::AndOr(ref node1, ref node2, ref node3) => vec![node1, node2, node3],
76
77            Terminal::Thresh(_, ref node_vec) => node_vec.iter().map(Arc::deref).collect(),
78
79            _ => vec![],
80        }
81    }
82
83    /// Returns child node with given index, if any
84    pub fn get_nth_child(&self, n: usize) -> Option<&Miniscript<Pk, Ctx>> {
85        match (n, &self.node) {
86            (0, &Terminal::Alt(ref node))
87            | (0, &Terminal::Swap(ref node))
88            | (0, &Terminal::Check(ref node))
89            | (0, &Terminal::DupIf(ref node))
90            | (0, &Terminal::Verify(ref node))
91            | (0, &Terminal::NonZero(ref node))
92            | (0, &Terminal::ZeroNotEqual(ref node))
93            | (0, &Terminal::AndV(ref node, _))
94            | (0, &Terminal::AndB(ref node, _))
95            | (0, &Terminal::OrB(ref node, _))
96            | (0, &Terminal::OrD(ref node, _))
97            | (0, &Terminal::OrC(ref node, _))
98            | (0, &Terminal::OrI(ref node, _))
99            | (1, &Terminal::AndV(_, ref node))
100            | (1, &Terminal::AndB(_, ref node))
101            | (1, &Terminal::OrB(_, ref node))
102            | (1, &Terminal::OrD(_, ref node))
103            | (1, &Terminal::OrC(_, ref node))
104            | (1, &Terminal::OrI(_, ref node))
105            | (0, &Terminal::AndOr(ref node, _, _))
106            | (1, &Terminal::AndOr(_, ref node, _))
107            | (2, &Terminal::AndOr(_, _, ref node)) => Some(node),
108
109            (n, &Terminal::Thresh(_, ref node_vec)) => node_vec.get(n).map(|x| &**x),
110
111            _ => None,
112        }
113    }
114
115    /// Returns `Vec` with cloned version of all public keys from the current miniscript item,
116    /// if any. Otherwise returns an empty `Vec`.
117    ///
118    /// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
119    /// To obtain a list of all public keys within AST use [Miniscript::iter_pk()] function, for example
120    /// `miniscript.iter_pubkeys().collect()`.
121    pub fn get_leaf_pk(&self) -> Vec<Pk> {
122        match self.node {
123            Terminal::PkK(ref key) => vec![key.clone()],
124            Terminal::Multi(_, ref keys) | Terminal::MultiA(_, ref keys) => keys.clone(),
125            _ => vec![],
126        }
127    }
128
129    /// Returns `Vec` with hashes of all public keys from the current miniscript item, if any.
130    /// Otherwise returns an empty `Vec`.
131    ///
132    /// For each public key the function computes hash; for each hash of the public key the function
133    /// returns its cloned copy.
134    ///
135    /// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
136    /// To obtain a list of all public key hashes within AST use [Miniscript::iter_pkh()] function,
137    /// for example `miniscript.iter_pubkey_hashes().collect()`.
138    pub fn get_leaf_pkh(&self) -> Vec<Pk::Hash> {
139        match self.node {
140            Terminal::PkH(ref hash) => vec![hash.clone()],
141            Terminal::PkK(ref key) => vec![key.to_pubkeyhash()],
142            Terminal::Multi(_, ref keys) | Terminal::MultiA(_, ref keys) => {
143                keys.iter().map(Pk::to_pubkeyhash).collect()
144            }
145            _ => vec![],
146        }
147    }
148
149    /// Returns `Vec` of [PkPkh] entries, representing either public keys or public key
150    /// hashes, depending on the data from the current miniscript item. If there is no public
151    /// keys or hashes, the function returns an empty `Vec`.
152    ///
153    /// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
154    /// To obtain a list of all public keys or hashes within AST use [Miniscript::iter_pk_pkh()]
155    /// function, for example `miniscript.iter_pubkeys_and_hashes().collect()`.
156    pub fn get_leaf_pk_pkh(&self) -> Vec<PkPkh<Pk>> {
157        match self.node {
158            Terminal::PkH(ref hash) => vec![PkPkh::HashedPubkey(hash.clone())],
159            Terminal::PkK(ref key) => vec![PkPkh::PlainPubkey(key.clone())],
160            Terminal::Multi(_, ref keys) | Terminal::MultiA(_, ref keys) => keys
161                .into_iter()
162                .map(|key| PkPkh::PlainPubkey(key.clone()))
163                .collect(),
164            _ => vec![],
165        }
166    }
167
168    /// Returns `Option::Some` with cloned n'th public key from the current miniscript item,
169    /// if any. Otherwise returns `Option::None`.
170    ///
171    /// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
172    pub fn get_nth_pk(&self, n: usize) -> Option<Pk> {
173        match (&self.node, n) {
174            (&Terminal::PkK(ref key), 0) => Some(key.clone()),
175            (&Terminal::Multi(_, ref keys), _) | (&Terminal::MultiA(_, ref keys), _) => {
176                keys.get(n).cloned()
177            }
178            _ => None,
179        }
180    }
181
182    /// Returns `Option::Some` with hash of n'th public key from the current miniscript item,
183    /// if any. Otherwise returns `Option::None`.
184    ///
185    /// For each public key the function computes hash; for each hash of the public key the function
186    /// returns it cloned copy.
187    ///
188    /// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
189    pub fn get_nth_pkh(&self, n: usize) -> Option<Pk::Hash> {
190        match (&self.node, n) {
191            (&Terminal::PkH(ref hash), 0) => Some(hash.clone()),
192            (&Terminal::PkK(ref key), 0) => Some(key.to_pubkeyhash()),
193            (&Terminal::Multi(_, ref keys), _) | (&Terminal::MultiA(_, ref keys), _) => {
194                keys.get(n).map(Pk::to_pubkeyhash)
195            }
196            _ => None,
197        }
198    }
199
200    /// Returns `Option::Some` with hash of n'th public key or hash from the current miniscript item,
201    /// if any. Otherwise returns `Option::None`.
202    ///
203    /// NB: The function analyzes only single miniscript item and not any of its descendants in AST.
204    pub fn get_nth_pk_pkh(&self, n: usize) -> Option<PkPkh<Pk>> {
205        match (&self.node, n) {
206            (&Terminal::PkH(ref hash), 0) => Some(PkPkh::HashedPubkey(hash.clone())),
207            (&Terminal::PkK(ref key), 0) => Some(PkPkh::PlainPubkey(key.clone())),
208            (&Terminal::Multi(_, ref keys), _) | (&Terminal::MultiA(_, ref keys), _) => {
209                keys.get(n).map(|key| PkPkh::PlainPubkey(key.clone()))
210            }
211            _ => None,
212        }
213    }
214}
215
216/// Iterator for traversing all [Miniscript] miniscript AST references starting from some specific
217/// node which constructs the iterator via [Miniscript::iter] method.
218pub struct Iter<'a, Pk: 'a + MiniscriptKey, Ctx: 'a + ScriptContext> {
219    next: Option<&'a Miniscript<Pk, Ctx>>,
220    // Here we store vec of path elements, where each element is a tuple, consisting of:
221    // 1. Miniscript node on the path
222    // 2. Index of the current branch
223    path: Vec<(&'a Miniscript<Pk, Ctx>, usize)>,
224}
225
226impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iter<'a, Pk, Ctx> {
227    fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
228        Iter {
229            next: Some(miniscript),
230            path: vec![],
231        }
232    }
233}
234
235impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for Iter<'a, Pk, Ctx> {
236    type Item = &'a Miniscript<Pk, Ctx>;
237
238    /// First, the function returns `self`, then the first child of the self (if any),
239    /// then proceeds to the child of the child — down to a leaf of the tree in its first branch.
240    /// When the leaf is reached, it goes in the reverse direction on the same branch until it
241    /// founds a first branching node that had more than a single branch and returns it, traversing
242    /// it with the same algorithm again.
243    ///
244    /// For example, for the given AST
245    /// ```text
246    /// A --+--> B -----> C --+--> D -----> E
247    ///     |                 |
248    ///     |                 +--> F
249    ///     |                 |
250    ///     |                 +--> G --+--> H
251    ///     |                          |
252    ///     |                          +--> I -----> J
253    ///     +--> K
254    /// ```
255    /// `Iter::next()` will iterate over the nodes in the following order:
256    /// `A > B > C > D > E > F > G > H > I > J > K`
257    ///
258    /// To enumerate the branches iterator uses [Miniscript::branches] function.
259    fn next(&mut self) -> Option<Self::Item> {
260        let mut curr = self.next;
261        if let None = curr {
262            while let Some((node, child)) = self.path.pop() {
263                curr = node.get_nth_child(child);
264                if curr.is_some() {
265                    self.path.push((node, child + 1));
266                    break;
267                }
268            }
269        }
270        if let Some(node) = curr {
271            self.next = node.get_nth_child(0);
272            self.path.push((node, 1));
273        }
274        curr
275    }
276}
277
278/// Iterator for traversing all [MiniscriptKey]'s in AST starting from some specific node which
279/// constructs the iterator via [Miniscript::iter_pk] method.
280pub struct PkIter<'a, Pk: 'a + MiniscriptKey, Ctx: 'a + ScriptContext> {
281    node_iter: Iter<'a, Pk, Ctx>,
282    curr_node: Option<&'a Miniscript<Pk, Ctx>>,
283    key_index: usize,
284}
285
286impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> PkIter<'a, Pk, Ctx> {
287    fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
288        let mut iter = Iter::new(miniscript);
289        PkIter {
290            curr_node: iter.next(),
291            node_iter: iter,
292            key_index: 0,
293        }
294    }
295}
296
297impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for PkIter<'a, Pk, Ctx> {
298    type Item = Pk;
299
300    fn next(&mut self) -> Option<Self::Item> {
301        loop {
302            match self.curr_node {
303                None => break None,
304                Some(node) => match node.get_nth_pk(self.key_index) {
305                    None => {
306                        self.curr_node = self.node_iter.next();
307                        self.key_index = 0;
308                        continue;
309                    }
310                    Some(pk) => {
311                        self.key_index += 1;
312                        break Some(pk);
313                    }
314                },
315            }
316        }
317    }
318}
319
320/// Iterator for traversing all [MiniscriptKey] hashes in AST starting from some specific node which
321/// constructs the iterator via [Miniscript::iter_pkh] method.
322pub struct PkhIter<'a, Pk: 'a + MiniscriptKey, Ctx: 'a + ScriptContext> {
323    node_iter: Iter<'a, Pk, Ctx>,
324    curr_node: Option<&'a Miniscript<Pk, Ctx>>,
325    key_index: usize,
326}
327
328impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> PkhIter<'a, Pk, Ctx> {
329    fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
330        let mut iter = Iter::new(miniscript);
331        PkhIter {
332            curr_node: iter.next(),
333            node_iter: iter,
334            key_index: 0,
335        }
336    }
337}
338
339impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for PkhIter<'a, Pk, Ctx> {
340    type Item = Pk::Hash;
341
342    fn next(&mut self) -> Option<Self::Item> {
343        loop {
344            match self.curr_node {
345                None => break None,
346                Some(node) => match node.get_nth_pkh(self.key_index) {
347                    None => {
348                        self.curr_node = self.node_iter.next();
349                        self.key_index = 0;
350                        continue;
351                    }
352                    Some(pk) => {
353                        self.key_index += 1;
354                        break Some(pk);
355                    }
356                },
357            }
358        }
359    }
360}
361
362/// Enum representing either key or a key hash value coming from a miniscript item inside AST
363#[derive(Clone, PartialEq, Eq, Debug)]
364pub enum PkPkh<Pk: MiniscriptKey> {
365    /// Plain public key
366    PlainPubkey(Pk),
367    /// Hashed public key
368    HashedPubkey(Pk::Hash),
369}
370
371/// Iterator for traversing all [MiniscriptKey]'s and hashes, depending what data are present in AST,
372/// starting from some specific node which constructs the iterator via
373/// [Miniscript::iter_pk_pkh] method.
374pub struct PkPkhIter<'a, Pk: 'a + MiniscriptKey, Ctx: 'a + ScriptContext> {
375    node_iter: Iter<'a, Pk, Ctx>,
376    curr_node: Option<&'a Miniscript<Pk, Ctx>>,
377    key_index: usize,
378}
379
380impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> PkPkhIter<'a, Pk, Ctx> {
381    fn new(miniscript: &'a Miniscript<Pk, Ctx>) -> Self {
382        let mut iter = Iter::new(miniscript);
383        PkPkhIter {
384            curr_node: iter.next(),
385            node_iter: iter,
386            key_index: 0,
387        }
388    }
389
390    /// Returns a `Option`, listing all public keys found in AST starting from this
391    /// `Miniscript` item, or `None` signifying that at least one key hash was found, making
392    /// impossible to enumerate all source public keys from the script.
393    ///
394    /// * Differs from `Miniscript::iter_pubkeys().collect()` in the way that this function fails on
395    ///   the first met public key hash, while [PkIter] just ignores them.
396    /// * Differs from `Miniscript::iter_pubkeys_and_hashes().collect()` in the way that it lists
397    ///   only public keys, and not their hashes
398    ///
399    /// Unlike these functions, [PkPkhIter::pk_only] returns an `Option` value with `Vec`, not an iterator,
400    /// and consumes the iterator object.
401    pub fn pk_only(self) -> Option<Vec<Pk>> {
402        let mut keys = vec![];
403        for item in self {
404            match item {
405                PkPkh::HashedPubkey(_) => return None,
406                PkPkh::PlainPubkey(key) => {
407                    keys.push(key);
408                }
409            }
410        }
411        Some(keys)
412    }
413}
414
415impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> Iterator for PkPkhIter<'a, Pk, Ctx> {
416    type Item = PkPkh<Pk>;
417
418    fn next(&mut self) -> Option<Self::Item> {
419        loop {
420            match self.curr_node {
421                None => break None,
422                Some(node) => match node.get_nth_pk_pkh(self.key_index) {
423                    None => {
424                        self.curr_node = self.node_iter.next();
425                        self.key_index = 0;
426                        continue;
427                    }
428                    Some(pk) => {
429                        self.key_index += 1;
430                        break Some(pk);
431                    }
432                },
433            }
434        }
435    }
436}
437
438// Module is public since it export testcase generation which may be used in
439// dependent libraries for their own tasts based on Miniscript AST
440#[cfg(test)]
441pub mod test {
442    use super::{Miniscript, PkPkh};
443    use bitcoin;
444    use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
445    use bitcoin::secp256k1;
446    use miniscript::context::Segwitv0;
447
448    pub type TestData = (
449        Miniscript<bitcoin::PublicKey, Segwitv0>,
450        Vec<bitcoin::PublicKey>,
451        Vec<hash160::Hash>,
452        bool, // Indicates that the top-level contains public key or hashes
453    );
454
455    pub fn gen_secp_pubkeys(n: usize) -> Vec<secp256k1::PublicKey> {
456        let mut ret = Vec::with_capacity(n);
457        let secp = secp256k1::Secp256k1::new();
458        let mut sk = [0; 32];
459
460        for i in 1..n + 1 {
461            sk[0] = i as u8;
462            sk[1] = (i >> 8) as u8;
463            sk[2] = (i >> 16) as u8;
464
465            ret.push(secp256k1::PublicKey::from_secret_key(
466                &secp,
467                &secp256k1::SecretKey::from_slice(&sk[..]).unwrap(),
468            ));
469        }
470        ret
471    }
472
473    pub fn gen_bitcoin_pubkeys(n: usize, compressed: bool) -> Vec<bitcoin::PublicKey> {
474        gen_secp_pubkeys(n)
475            .into_iter()
476            .map(|inner| bitcoin::PublicKey { inner, compressed })
477            .collect()
478    }
479
480    pub fn gen_testcases() -> Vec<TestData> {
481        let k = gen_bitcoin_pubkeys(10, true);
482        let h: Vec<hash160::Hash> = k
483            .iter()
484            .map(|pk| hash160::Hash::hash(&pk.to_bytes()))
485            .collect();
486
487        let preimage = vec![0xab as u8; 32];
488        let sha256_hash = sha256::Hash::hash(&preimage);
489        let sha256d_hash_rev = sha256d::Hash::hash(&preimage);
490        let mut sha256d_hash_bytes = sha256d_hash_rev.clone().into_inner();
491        sha256d_hash_bytes.reverse();
492        let sha256d_hash = sha256d::Hash::from_inner(sha256d_hash_bytes);
493        let hash160_hash = hash160::Hash::hash(&preimage);
494        let ripemd160_hash = ripemd160::Hash::hash(&preimage);
495
496        vec![
497            (ms_str!("after({})", 1000), vec![], vec![], false),
498            (ms_str!("older({})", 1000), vec![], vec![], false),
499            (ms_str!("sha256({})", sha256_hash), vec![], vec![], false),
500            (ms_str!("hash256({})", sha256d_hash), vec![], vec![], false),
501            (ms_str!("hash160({})", hash160_hash), vec![], vec![], false),
502            (
503                ms_str!("ripemd160({})", ripemd160_hash),
504                vec![],
505                vec![],
506                false,
507            ),
508            (ms_str!("c:pk_k({})", k[0]), vec![k[0]], vec![], true),
509            (ms_str!("c:pk_h({})", h[6]), vec![], vec![h[6]], true),
510            (
511                ms_str!("and_v(vc:pk_k({}),c:pk_h({}))", k[0], h[1]),
512                vec![k[0]],
513                vec![h[1]],
514                false,
515            ),
516            (
517                ms_str!("and_b(c:pk_k({}),sjtv:sha256({}))", k[0], sha256_hash),
518                vec![k[0]],
519                vec![],
520                false,
521            ),
522            (
523                ms_str!(
524                    "andor(c:pk_k({}),jtv:sha256({}),c:pk_h({}))",
525                    k[1],
526                    sha256_hash,
527                    h[2]
528                ),
529                vec![k[1]],
530                vec![h[2]],
531                false,
532            ),
533            (
534                ms_str!("multi(3,{},{},{},{},{})", k[9], k[8], k[7], k[0], k[1]),
535                vec![k[9], k[8], k[7], k[0], k[1]],
536                vec![],
537                true,
538            ),
539            (
540                ms_str!(
541                    "thresh(3,c:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}),sc:pk_k({}))",
542                    k[2],
543                    k[3],
544                    k[4],
545                    k[5],
546                    k[6]
547                ),
548                vec![k[2], k[3], k[4], k[5], k[6]],
549                vec![],
550                false,
551            ),
552            (
553                ms_str!(
554                    "or_d(multi(2,{},{}),and_v(v:multi(2,{},{}),older(10000)))",
555                    k[6],
556                    k[7],
557                    k[8],
558                    k[9]
559                ),
560                vec![k[6], k[7], k[8], k[9]],
561                vec![],
562                false,
563            ),
564            (
565                ms_str!(
566                    "or_d(multi(3,{},{},{},{},{}),\
567                      and_v(v:thresh(2,c:pk_h({}),\
568                      ac:pk_h({}),ac:pk_h({})),older(10000)))",
569                    k[0],
570                    k[2],
571                    k[4],
572                    k[6],
573                    k[9],
574                    h[8],
575                    h[7],
576                    h[0]
577                ),
578                vec![k[0], k[2], k[4], k[6], k[9]],
579                vec![h[8], h[7], h[0]],
580                false,
581            ),
582        ]
583    }
584
585    #[test]
586    fn get_keys() {
587        gen_testcases()
588            .into_iter()
589            .for_each(|(ms, k, _, test_top_level)| {
590                if !test_top_level {
591                    return;
592                }
593                let ms = *ms.branches().first().unwrap_or(&&ms);
594                assert_eq!(ms.get_leaf_pk(), k);
595            })
596    }
597
598    #[test]
599    fn get_hashes() {
600        gen_testcases()
601            .into_iter()
602            .for_each(|(ms, k, h, test_top_level)| {
603                if !test_top_level {
604                    return;
605                }
606                let ms = *ms.branches().first().unwrap_or(&&ms);
607                let mut all: Vec<hash160::Hash> = k
608                    .iter()
609                    .map(|p| hash160::Hash::hash(&p.to_bytes()))
610                    .collect();
611                // In our test cases we always have plain keys going first
612                all.extend(h);
613                assert_eq!(ms.get_leaf_pkh(), all);
614            })
615    }
616
617    #[test]
618    fn get_pubkey_and_hashes() {
619        gen_testcases()
620            .into_iter()
621            .for_each(|(ms, k, h, test_top_level)| {
622                if !test_top_level {
623                    return;
624                }
625                let ms = *ms.branches().first().unwrap_or(&&ms);
626                let r: Vec<PkPkh<bitcoin::PublicKey>> = if k.is_empty() {
627                    h.into_iter().map(|h| PkPkh::HashedPubkey(h)).collect()
628                } else {
629                    k.into_iter().map(|k| PkPkh::PlainPubkey(k)).collect()
630                };
631                assert_eq!(ms.get_leaf_pk_pkh(), r);
632            })
633    }
634
635    #[test]
636    fn find_keys() {
637        gen_testcases().into_iter().for_each(|(ms, k, _, _)| {
638            assert_eq!(ms.iter_pk().collect::<Vec<bitcoin::PublicKey>>(), k);
639        })
640    }
641
642    #[test]
643    fn find_hashes() {
644        gen_testcases().into_iter().for_each(|(ms, k, h, _)| {
645            let mut all: Vec<hash160::Hash> = k
646                .iter()
647                .map(|p| hash160::Hash::hash(&p.to_bytes()))
648                .collect();
649            // In our test cases we always have plain keys going first
650            all.extend(h);
651            assert_eq!(ms.iter_pkh().collect::<Vec<hash160::Hash>>(), all);
652        })
653    }
654
655    #[test]
656    fn find_pubkeys_and_hashes() {
657        gen_testcases().into_iter().for_each(|(ms, k, h, _)| {
658            let mut all: Vec<PkPkh<bitcoin::PublicKey>> =
659                k.into_iter().map(|k| PkPkh::PlainPubkey(k)).collect();
660            all.extend(h.into_iter().map(|h| PkPkh::HashedPubkey(h)));
661            assert_eq!(
662                ms.iter_pk_pkh().collect::<Vec<PkPkh<bitcoin::PublicKey>>>(),
663                all
664            );
665        })
666    }
667}