miniscript/policy/
concrete.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Concrete Policies
4//!
5
6use core::{fmt, str};
7#[cfg(feature = "std")]
8use std::error;
9
10use bitcoin::absolute;
11#[cfg(feature = "compiler")]
12use {
13    crate::descriptor::TapTree,
14    crate::miniscript::ScriptContext,
15    crate::policy::compiler::CompilerError,
16    crate::policy::compiler::OrdF64,
17    crate::policy::{compiler, Concrete, Liftable, Semantic},
18    crate::Descriptor,
19    crate::Miniscript,
20    crate::Tap,
21    core::cmp::Reverse,
22};
23
24use super::ENTAILMENT_MAX_TERMINALS;
25use crate::expression::{self, FromTree};
26use crate::iter::{Tree, TreeLike};
27use crate::miniscript::types::extra_props::TimelockInfo;
28use crate::prelude::*;
29use crate::sync::Arc;
30#[cfg(all(doc, not(feature = "compiler")))]
31use crate::Descriptor;
32use crate::{
33    errstr, AbsLockTime, Error, ForEachKey, FromStrKey, MiniscriptKey, RelLockTime, Threshold,
34    Translator,
35};
36
37/// Maximum TapLeafs allowed in a compiled TapTree
38#[cfg(feature = "compiler")]
39const MAX_COMPILATION_LEAVES: usize = 1024;
40
41/// Concrete policy which corresponds directly to a miniscript structure,
42/// and whose disjunctions are annotated with satisfaction probabilities
43/// to assist the compiler.
44// Currently the vectors in And/Or are limited to two elements, this is a general miniscript thing
45// not specific to rust-miniscript. Eventually we would like to extend these to be n-ary, but first
46// we need to decide on a game plan for how to efficiently compile n-ary disjunctions
47#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
48pub enum Policy<Pk: MiniscriptKey> {
49    /// Unsatisfiable.
50    Unsatisfiable,
51    /// Trivially satisfiable.
52    Trivial,
53    /// A public key which must sign to satisfy the descriptor.
54    Key(Pk),
55    /// An absolute locktime restriction.
56    After(AbsLockTime),
57    /// A relative locktime restriction.
58    Older(RelLockTime),
59    /// A SHA256 whose preimage must be provided to satisfy the descriptor.
60    Sha256(Pk::Sha256),
61    /// A SHA256d whose preimage must be provided to satisfy the descriptor.
62    Hash256(Pk::Hash256),
63    /// A RIPEMD160 whose preimage must be provided to satisfy the descriptor.
64    Ripemd160(Pk::Ripemd160),
65    /// A HASH160 whose preimage must be provided to satisfy the descriptor.
66    Hash160(Pk::Hash160),
67    /// A list of sub-policies, all of which must be satisfied.
68    And(Vec<Arc<Policy<Pk>>>),
69    /// A list of sub-policies, one of which must be satisfied, along with
70    /// relative probabilities for each one.
71    Or(Vec<(usize, Arc<Policy<Pk>>)>),
72    /// A set of descriptors, satisfactions must be provided for `k` of them.
73    Thresh(Threshold<Arc<Policy<Pk>>, 0>),
74}
75
76/// Detailed error type for concrete policies.
77#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
78pub enum PolicyError {
79    /// `And` fragments only support two args.
80    NonBinaryArgAnd,
81    /// `Or` fragments only support two args.
82    NonBinaryArgOr,
83    /// Semantic Policy Error: `And` `Or` fragments must take args: `k > 1`.
84    InsufficientArgsforAnd,
85    /// Semantic policy error: `And` `Or` fragments must take args: `k > 1`.
86    InsufficientArgsforOr,
87    /// Entailment max terminals exceeded.
88    EntailmentMaxTerminals,
89    /// Cannot lift policies that have a combination of height and timelocks.
90    HeightTimelockCombination,
91    /// Duplicate Public Keys.
92    DuplicatePubKeys,
93}
94
95/// Descriptor context for [`Policy`] compilation into a [`Descriptor`].
96pub enum DescriptorCtx<Pk> {
97    /// See docs for [`Descriptor::Bare`].
98    Bare,
99    /// See docs for [`Descriptor::Sh`].
100    Sh,
101    /// See docs for [`Descriptor::Wsh`].
102    Wsh,
103    /// See docs for [`Descriptor::Wsh`].
104    ShWsh,
105    /// [`Descriptor::Tr`] where the `Option<Pk>` corresponds to the internal key if no
106    /// internal key can be inferred from the given policy.
107    Tr(Option<Pk>),
108}
109
110impl fmt::Display for PolicyError {
111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112        match *self {
113            PolicyError::NonBinaryArgAnd => {
114                f.write_str("And policy fragment must take 2 arguments")
115            }
116            PolicyError::NonBinaryArgOr => f.write_str("Or policy fragment must take 2 arguments"),
117            PolicyError::InsufficientArgsforAnd => {
118                f.write_str("Semantic Policy 'And' fragment must have at least 2 args ")
119            }
120            PolicyError::InsufficientArgsforOr => {
121                f.write_str("Semantic Policy 'Or' fragment must have at least 2 args ")
122            }
123            PolicyError::EntailmentMaxTerminals => {
124                write!(f, "Policy entailment only supports {} terminals", ENTAILMENT_MAX_TERMINALS)
125            }
126            PolicyError::HeightTimelockCombination => {
127                f.write_str("Cannot lift policies that have a heightlock and timelock combination")
128            }
129            PolicyError::DuplicatePubKeys => f.write_str("Policy contains duplicate keys"),
130        }
131    }
132}
133
134#[cfg(feature = "std")]
135impl error::Error for PolicyError {
136    fn cause(&self) -> Option<&dyn error::Error> {
137        use self::PolicyError::*;
138
139        match self {
140            NonBinaryArgAnd
141            | NonBinaryArgOr
142            | InsufficientArgsforAnd
143            | InsufficientArgsforOr
144            | EntailmentMaxTerminals
145            | HeightTimelockCombination
146            | DuplicatePubKeys => None,
147        }
148    }
149}
150
151impl<Pk: MiniscriptKey> Policy<Pk> {
152    /// Flattens the [`Policy`] tree structure into a vector of tuples `(leaf script, leaf probability)`
153    /// with leaf probabilities corresponding to odds for each sub-branch in the policy.
154    /// We calculate the probability of selecting the sub-branch at every level and calculate the
155    /// leaf probabilities as the probability of traversing through required branches to reach the
156    /// leaf node, i.e. multiplication of the respective probabilities.
157    ///
158    /// For example, the policy tree:       OR
159    ///                                   /   \
160    ///                                  2     1            odds
161    ///                                /        \
162    ///                               A         OR
163    ///                                        /  \
164    ///                                       3    1        odds
165    ///                                     /       \
166    ///                                    B         C
167    ///
168    /// gives the vector [(2/3, A), (1/3 * 3/4, B), (1/3 * 1/4, C)].
169    ///
170    /// ## Constraints
171    ///
172    /// Since this splitting might lead to exponential blow-up, we constrain the number of
173    /// leaf-nodes to [`MAX_COMPILATION_LEAVES`].
174    #[cfg(feature = "compiler")]
175    fn to_tapleaf_prob_vec(&self, prob: f64) -> Vec<(f64, Policy<Pk>)> {
176        match self {
177            Policy::Or(ref subs) => {
178                let total_odds: usize = subs.iter().map(|(ref k, _)| k).sum();
179                subs.iter()
180                    .flat_map(|(k, ref policy)| {
181                        policy.to_tapleaf_prob_vec(prob * *k as f64 / total_odds as f64)
182                    })
183                    .collect::<Vec<_>>()
184            }
185            Policy::Thresh(ref thresh) if thresh.is_or() => {
186                let total_odds = thresh.n();
187                thresh
188                    .iter()
189                    .flat_map(|policy| policy.to_tapleaf_prob_vec(prob / total_odds as f64))
190                    .collect::<Vec<_>>()
191            }
192            x => vec![(prob, x.clone())],
193        }
194    }
195
196    /// Extracts the internal_key from this policy tree.
197    #[cfg(feature = "compiler")]
198    fn extract_key(self, unspendable_key: Option<Pk>) -> Result<(Pk, Policy<Pk>), Error> {
199        let mut internal_key: Option<Pk> = None;
200        {
201            let mut prob = 0.;
202            let semantic_policy = self.lift()?;
203            let concrete_keys = self.keys();
204            let key_prob_map: BTreeMap<_, _> = self
205                .to_tapleaf_prob_vec(1.0)
206                .into_iter()
207                .filter(|(_, ref pol)| matches!(pol, Concrete::Key(..)))
208                .map(|(prob, key)| (key, prob))
209                .collect();
210
211            for key in concrete_keys.into_iter() {
212                if semantic_policy
213                    .clone()
214                    .satisfy_constraint(&Semantic::Key(key.clone()), true)
215                    == Semantic::Trivial
216                {
217                    match key_prob_map.get(&Concrete::Key(key.clone())) {
218                        Some(val) => {
219                            if *val > prob {
220                                prob = *val;
221                                internal_key = Some(key.clone());
222                            }
223                        }
224                        None => return Err(errstr("Key should have existed in the BTreeMap!")),
225                    }
226                }
227            }
228        }
229        match (internal_key, unspendable_key) {
230            (Some(ref key), _) => Ok((key.clone(), self.translate_unsatisfiable_pk(key))),
231            (_, Some(key)) => Ok((key, self)),
232            _ => Err(errstr("No viable internal key found.")),
233        }
234    }
235
236    /// Compiles the [`Policy`] into a [`Descriptor::Tr`].
237    ///
238    /// ### TapTree compilation
239    ///
240    /// The policy tree constructed by root-level disjunctions over [`Policy::Or`] and
241    /// [`Policy::Thresh`](1, ..) which is flattened into a vector (with respective
242    /// probabilities derived from odds) of policies.
243    ///
244    /// For example, the policy `thresh(1,or(pk(A),pk(B)),and(or(pk(C),pk(D)),pk(E)))` gives the
245    /// vector `[pk(A),pk(B),and(or(pk(C),pk(D)),pk(E)))]`. Each policy in the vector is compiled
246    /// into the respective miniscripts. A Huffman Tree is created from this vector which optimizes
247    /// over the probabilitity of satisfaction for the respective branch in the TapTree.
248    ///
249    /// Refer to [this link](https://gist.github.com/SarcasticNastik/9e70b2b43375aab3e78c51e09c288c89)
250    /// or [doc/Tr compiler.pdf] in the root of the repository to understand why such compilation
251    /// is also *cost-efficient*.
252    // TODO: We might require other compile errors for Taproot.
253    #[cfg(feature = "compiler")]
254    pub fn compile_tr(&self, unspendable_key: Option<Pk>) -> Result<Descriptor<Pk>, Error> {
255        self.is_valid()?; // Check for validity
256        match self.is_safe_nonmalleable() {
257            (false, _) => Err(Error::from(CompilerError::TopLevelNonSafe)),
258            (_, false) => Err(Error::from(CompilerError::ImpossibleNonMalleableCompilation)),
259            _ => {
260                let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
261                policy.check_num_tapleaves()?;
262                let tree = Descriptor::new_tr(
263                    internal_key,
264                    match policy {
265                        Policy::Trivial => None,
266                        policy => {
267                            let vec_policies: Vec<_> = policy.to_tapleaf_prob_vec(1.0);
268                            let mut leaf_compilations: Vec<(OrdF64, Miniscript<Pk, Tap>)> = vec![];
269                            for (prob, pol) in vec_policies {
270                                // policy corresponding to the key (replaced by unsatisfiable) is skipped
271                                if pol == Policy::Unsatisfiable {
272                                    continue;
273                                }
274                                let compilation = compiler::best_compilation::<Pk, Tap>(&pol)?;
275                                compilation.sanity_check()?;
276                                leaf_compilations.push((OrdF64(prob), compilation));
277                            }
278                            let tap_tree = with_huffman_tree::<Pk>(leaf_compilations)?;
279                            Some(tap_tree)
280                        }
281                    },
282                )?;
283                Ok(tree)
284            }
285        }
286    }
287
288    /// Compiles the [`Policy`] into a [`Descriptor::Tr`].
289    ///
290    /// ### TapTree compilation
291    ///
292    /// The policy tree constructed by root-level disjunctions over [`Policy::Or`] and
293    /// [`Policy::Thresh`](k, ..n..) which is flattened into a vector (with respective
294    /// probabilities derived from odds) of policies. For example, the policy
295    /// `thresh(1,or(pk(A),pk(B)),and(or(pk(C),pk(D)),pk(E)))` gives the vector
296    /// `[pk(A),pk(B),and(or(pk(C),pk(D)),pk(E)))]`.
297    ///
298    /// ### Policy enumeration
299    ///
300    /// Generates a root-level disjunctive tree over the given policy tree.
301    ///
302    /// Uses a fixed-point algorithm to enumerate the disjunctions until exhaustive root-level
303    /// enumeration or limits exceed. For a given [`Policy`], we maintain an [ordered
304    /// set](`BTreeSet`) of `(prob, policy)` (ordered by probability) to maintain the list of
305    /// enumerated sub-policies whose disjunction is isomorphic to initial policy (*invariant*).
306    #[cfg(feature = "compiler")]
307    pub fn compile_tr_private_experimental(
308        &self,
309        unspendable_key: Option<Pk>,
310    ) -> Result<Descriptor<Pk>, Error> {
311        self.is_valid()?; // Check for validity
312        match self.is_safe_nonmalleable() {
313            (false, _) => Err(Error::from(CompilerError::TopLevelNonSafe)),
314            (_, false) => Err(Error::from(CompilerError::ImpossibleNonMalleableCompilation)),
315            _ => {
316                let (internal_key, policy) = self.clone().extract_key(unspendable_key)?;
317                let tree = Descriptor::new_tr(
318                    internal_key,
319                    match policy {
320                        Policy::Trivial => None,
321                        policy => {
322                            let leaf_compilations: Vec<_> = policy
323                                .enumerate_policy_tree(1.0)
324                                .into_iter()
325                                .filter(|x| x.1 != Arc::new(Policy::Unsatisfiable))
326                                .map(|(prob, pol)| {
327                                    (
328                                        OrdF64(prob),
329                                        compiler::best_compilation(pol.as_ref()).unwrap(),
330                                    )
331                                })
332                                .collect();
333                            let tap_tree = with_huffman_tree::<Pk>(leaf_compilations).unwrap();
334                            Some(tap_tree)
335                        }
336                    },
337                )?;
338                Ok(tree)
339            }
340        }
341    }
342
343    /// Compiles the [`Policy`] into `desc_ctx` [`Descriptor`]
344    ///
345    /// In case of [`DescriptorCtx::Tr`], `internal_key` is used for the taproot compilation when
346    /// no public key can be inferred from the given policy.
347    ///
348    /// # NOTE:
349    ///
350    /// It is **not recommended** to use policy as a stable identifier for a miniscript. You should
351    /// use the policy compiler once, and then use the miniscript output as a stable identifier. See
352    /// the compiler document in [`doc/compiler.md`] for more details.
353    #[cfg(feature = "compiler")]
354    pub fn compile_to_descriptor<Ctx: ScriptContext>(
355        &self,
356        desc_ctx: DescriptorCtx<Pk>,
357    ) -> Result<Descriptor<Pk>, Error> {
358        self.is_valid()?;
359        match self.is_safe_nonmalleable() {
360            (false, _) => Err(Error::from(CompilerError::TopLevelNonSafe)),
361            (_, false) => Err(Error::from(CompilerError::ImpossibleNonMalleableCompilation)),
362            _ => match desc_ctx {
363                DescriptorCtx::Bare => Descriptor::new_bare(compiler::best_compilation(self)?),
364                DescriptorCtx::Sh => Descriptor::new_sh(compiler::best_compilation(self)?),
365                DescriptorCtx::Wsh => Descriptor::new_wsh(compiler::best_compilation(self)?),
366                DescriptorCtx::ShWsh => Descriptor::new_sh_wsh(compiler::best_compilation(self)?),
367                DescriptorCtx::Tr(unspendable_key) => self.compile_tr(unspendable_key),
368            },
369        }
370    }
371
372    /// Compiles the descriptor into an optimized `Miniscript` representation.
373    ///
374    /// # NOTE:
375    ///
376    /// It is **not recommended** to use policy as a stable identifier for a miniscript. You should
377    /// use the policy compiler once, and then use the miniscript output as a stable identifier. See
378    /// the compiler document in doc/compiler.md for more details.
379    #[cfg(feature = "compiler")]
380    pub fn compile<Ctx: ScriptContext>(&self) -> Result<Miniscript<Pk, Ctx>, CompilerError> {
381        self.is_valid()?;
382        match self.is_safe_nonmalleable() {
383            (false, _) => Err(CompilerError::TopLevelNonSafe),
384            (_, false) => Err(CompilerError::ImpossibleNonMalleableCompilation),
385            _ => compiler::best_compilation(self),
386        }
387    }
388}
389
390#[cfg(feature = "compiler")]
391impl<Pk: MiniscriptKey> Policy<Pk> {
392    /// Returns a vector of policies whose disjunction is isomorphic to the initial one.
393    ///
394    /// This function is supposed to incrementally expand i.e. represent the policy as
395    /// disjunction over sub-policies output by it. The probability calculations are similar
396    /// to [`Policy::to_tapleaf_prob_vec`].
397    #[cfg(feature = "compiler")]
398    fn enumerate_pol(&self, prob: f64) -> Vec<(f64, Arc<Self>)> {
399        match self {
400            Policy::Or(subs) => {
401                let total_odds = subs.iter().fold(0, |acc, x| acc + x.0);
402                subs.iter()
403                    .map(|(odds, pol)| (prob * *odds as f64 / total_odds as f64, pol.clone()))
404                    .collect::<Vec<_>>()
405            }
406            Policy::Thresh(ref thresh) if thresh.is_or() => {
407                let total_odds = thresh.n();
408                thresh
409                    .iter()
410                    .map(|pol| (prob / total_odds as f64, pol.clone()))
411                    .collect::<Vec<_>>()
412            }
413            Policy::Thresh(ref thresh) if !thresh.is_and() => generate_combination(thresh, prob),
414            pol => vec![(prob, Arc::new(pol.clone()))],
415        }
416    }
417
418    /// Generates a root-level disjunctive tree over the given policy tree.
419    ///
420    /// Uses a fixed-point algorithm to enumerate the disjunctions until exhaustive root-level
421    /// enumeration or limits exceed. For a given [`Policy`], we maintain an [ordered
422    /// set](`BTreeSet`) of `(prob, policy)` (ordered by probability) to maintain the list of
423    /// enumerated sub-policies whose disjunction is isomorphic to initial policy (*invariant*).
424    #[cfg(feature = "compiler")]
425    fn enumerate_policy_tree(self, prob: f64) -> Vec<(f64, Arc<Self>)> {
426        let mut tapleaf_prob_vec = BTreeSet::<(Reverse<OrdF64>, Arc<Self>)>::new();
427        // Store probability corresponding to policy in the enumerated tree. This is required since
428        // owing to the current [policy element enumeration algorithm][`Policy::enumerate_pol`],
429        // two passes of the algorithm might result in same sub-policy showing up. Currently, we
430        // merge the nodes by adding up the corresponding probabilities for the same policy.
431        let mut pol_prob_map = BTreeMap::<Arc<Self>, OrdF64>::new();
432
433        let arc_self = Arc::new(self);
434        tapleaf_prob_vec.insert((Reverse(OrdF64(prob)), Arc::clone(&arc_self)));
435        pol_prob_map.insert(Arc::clone(&arc_self), OrdF64(prob));
436
437        // Since we know that policy enumeration *must* result in increase in total number of nodes,
438        // we can maintain the length of the ordered set to check if the
439        // [enumeration pass][`Policy::enumerate_pol`] results in further policy split or not.
440        let mut prev_len = 0usize;
441        // This is required since we merge some corresponding policy nodes, so we can explicitly
442        // store the variables
443        let mut enum_len = tapleaf_prob_vec.len();
444
445        let mut ret: Vec<(f64, Arc<Self>)> = vec![];
446
447        // Stopping condition: When NONE of the inputs can be further enumerated.
448        'outer: loop {
449            //--- FIND a plausible node ---
450            let mut prob: Reverse<OrdF64> = Reverse(OrdF64(0.0));
451            let mut curr_policy: Arc<Self> = Arc::new(Policy::Unsatisfiable);
452            let mut curr_pol_replace_vec: Vec<(f64, Arc<Self>)> = vec![];
453            let mut no_more_enum = false;
454
455            // The nodes which can't be enumerated further are directly appended to ret and removed
456            // from the ordered set.
457            let mut to_del: Vec<(f64, Arc<Self>)> = vec![];
458            'inner: for (i, (p, pol)) in tapleaf_prob_vec.iter().enumerate() {
459                curr_pol_replace_vec = pol.enumerate_pol(p.0 .0);
460                enum_len += curr_pol_replace_vec.len() - 1; // A disjunctive node should have seperated this into more nodes
461                assert!(prev_len <= enum_len);
462
463                if prev_len < enum_len {
464                    // Plausible node found
465                    prob = *p;
466                    curr_policy = Arc::clone(pol);
467                    break 'inner;
468                } else if i == tapleaf_prob_vec.len() - 1 {
469                    // No enumerable node found i.e. STOP
470                    // Move all the elements to final return set
471                    no_more_enum = true;
472                } else {
473                    // Either node is enumerable, or we have
474                    // Mark all non-enumerable nodes to remove,
475                    // if not returning value in the current iteration.
476                    to_del.push((p.0 .0, Arc::clone(pol)));
477                }
478            }
479
480            // --- Sanity Checks ---
481            if enum_len > MAX_COMPILATION_LEAVES || no_more_enum {
482                for (p, pol) in tapleaf_prob_vec.into_iter() {
483                    ret.push((p.0 .0, pol));
484                }
485                break 'outer;
486            }
487
488            // If total number of nodes are in limits, we remove the current node and replace it
489            // with children nodes
490
491            // Remove current node
492            assert!(tapleaf_prob_vec.remove(&(prob, curr_policy.clone())));
493
494            // OPTIMIZATION - Move marked nodes into final vector
495            for (p, pol) in to_del {
496                assert!(tapleaf_prob_vec.remove(&(Reverse(OrdF64(p)), pol.clone())));
497                ret.push((p, pol.clone()));
498            }
499
500            // Append node if not previously exists, else update the respective probability
501            for (p, policy) in curr_pol_replace_vec {
502                match pol_prob_map.get(&policy) {
503                    Some(prev_prob) => {
504                        assert!(tapleaf_prob_vec.remove(&(Reverse(*prev_prob), policy.clone())));
505                        tapleaf_prob_vec.insert((Reverse(OrdF64(prev_prob.0 + p)), policy.clone()));
506                        pol_prob_map.insert(policy.clone(), OrdF64(prev_prob.0 + p));
507                    }
508                    None => {
509                        tapleaf_prob_vec.insert((Reverse(OrdF64(p)), policy.clone()));
510                        pol_prob_map.insert(policy.clone(), OrdF64(p));
511                    }
512                }
513            }
514            // --- Update --- total sub-policies count (considering no merging of nodes)
515            prev_len = enum_len;
516        }
517
518        ret
519    }
520}
521
522impl<Pk: MiniscriptKey> ForEachKey<Pk> for Policy<Pk> {
523    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool {
524        self.pre_order_iter().all(|policy| match policy {
525            Policy::Key(ref pk) => pred(pk),
526            _ => true,
527        })
528    }
529}
530
531impl<Pk: MiniscriptKey> Policy<Pk> {
532    /// Converts a policy using one kind of public key to another type of public key.
533    ///
534    /// For example usage please see [`crate::policy::semantic::Policy::translate_pk`].
535    pub fn translate_pk<Q, E, T>(&self, t: &mut T) -> Result<Policy<Q>, E>
536    where
537        T: Translator<Pk, Q, E>,
538        Q: MiniscriptKey,
539    {
540        use Policy::*;
541
542        let mut translated = vec![];
543        for data in self.post_order_iter() {
544            let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
545
546            let new_policy = match data.node {
547                Unsatisfiable => Unsatisfiable,
548                Trivial => Trivial,
549                Key(ref pk) => t.pk(pk).map(Key)?,
550                Sha256(ref h) => t.sha256(h).map(Sha256)?,
551                Hash256(ref h) => t.hash256(h).map(Hash256)?,
552                Ripemd160(ref h) => t.ripemd160(h).map(Ripemd160)?,
553                Hash160(ref h) => t.hash160(h).map(Hash160)?,
554                Older(ref n) => Older(*n),
555                After(ref n) => After(*n),
556                And(ref subs) => And((0..subs.len()).map(child_n).collect()),
557                Or(ref subs) => Or(subs
558                    .iter()
559                    .enumerate()
560                    .map(|(i, (prob, _))| (*prob, child_n(i)))
561                    .collect()),
562                Thresh(ref thresh) => {
563                    Thresh(thresh.map_from_post_order_iter(&data.child_indices, &translated))
564                }
565            };
566            translated.push(Arc::new(new_policy));
567        }
568        // Unwrap is ok because we know we processed at least one node.
569        let root_node = translated.pop().unwrap();
570        // Unwrap is ok because we know `root_node` is the only strong reference.
571        Ok(Arc::try_unwrap(root_node).unwrap())
572    }
573
574    /// Translates `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting `TapKey`.
575    pub fn translate_unsatisfiable_pk(self, key: &Pk) -> Policy<Pk> {
576        use Policy::*;
577
578        let mut translated = vec![];
579        for data in Arc::new(self).post_order_iter() {
580            let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
581
582            let new_policy = match data.node.as_ref() {
583                Policy::Key(ref k) if k.clone() == *key => Some(Policy::Unsatisfiable),
584                And(ref subs) => Some(And((0..subs.len()).map(child_n).collect())),
585                Or(ref subs) => Some(Or(subs
586                    .iter()
587                    .enumerate()
588                    .map(|(i, (prob, _))| (*prob, child_n(i)))
589                    .collect())),
590                Thresh(ref thresh) => {
591                    Some(Thresh(thresh.map_from_post_order_iter(&data.child_indices, &translated)))
592                }
593                _ => None,
594            };
595            match new_policy {
596                Some(new_policy) => translated.push(Arc::new(new_policy)),
597                None => translated.push(Arc::clone(&data.node)),
598            }
599        }
600        // Ok to unwrap because we know we processed at least one node.
601        let root_node = translated.pop().unwrap();
602        // Ok to unwrap because we know `root_node` is the only strong reference.
603        Arc::try_unwrap(root_node).unwrap()
604    }
605
606    /// Gets all keys in the policy.
607    pub fn keys(&self) -> Vec<&Pk> {
608        self.pre_order_iter()
609            .filter_map(|policy| match policy {
610                Policy::Key(ref pk) => Some(pk),
611                _ => None,
612            })
613            .collect()
614    }
615
616    /// Gets the number of [TapLeaf](`TapTree::Leaf`)s considering exhaustive root-level [`Policy::Or`]
617    /// and [`Policy::Thresh`] disjunctions for the `TapTree`.
618    #[cfg(feature = "compiler")]
619    fn num_tap_leaves(&self) -> usize {
620        use Policy::*;
621
622        let mut nums = vec![];
623        for data in Arc::new(self).post_order_iter() {
624            let num_for_child_n = |n| nums[data.child_indices[n]];
625
626            let num = match data.node {
627                Or(subs) => (0..subs.len()).map(num_for_child_n).sum(),
628                Thresh(thresh) if thresh.is_or() => (0..thresh.n()).map(num_for_child_n).sum(),
629                _ => 1,
630            };
631            nums.push(num);
632        }
633        // Ok to unwrap because we know we processed at least one node.
634        nums.pop().unwrap()
635    }
636
637    /// Does checks on the number of `TapLeaf`s.
638    #[cfg(feature = "compiler")]
639    fn check_num_tapleaves(&self) -> Result<(), Error> {
640        if self.num_tap_leaves() > MAX_COMPILATION_LEAVES {
641            return Err(errstr("Too many Tapleaves"));
642        }
643        Ok(())
644    }
645
646    /// Checks whether the policy contains duplicate public keys.
647    pub fn check_duplicate_keys(&self) -> Result<(), PolicyError> {
648        let pks = self.keys();
649        let pks_len = pks.len();
650        let unique_pks_len = pks.into_iter().collect::<BTreeSet<_>>().len();
651
652        if pks_len > unique_pks_len {
653            Err(PolicyError::DuplicatePubKeys)
654        } else {
655            Ok(())
656        }
657    }
658
659    /// Checks whether the given concrete policy contains a combination of
660    /// timelocks and heightlocks.
661    ///
662    /// # Returns
663    ///
664    /// Returns an error if there is at least one satisfaction that contains
665    /// a combination of heightlock and timelock.
666    pub fn check_timelocks(&self) -> Result<(), PolicyError> {
667        let aggregated_timelock_info = self.timelock_info();
668        if aggregated_timelock_info.contains_combination {
669            Err(PolicyError::HeightTimelockCombination)
670        } else {
671            Ok(())
672        }
673    }
674
675    /// Processes `Policy` using `post_order_iter`, creates a `TimelockInfo` for each `Nullary` node
676    /// and combines them together for `Nary` nodes.
677    ///
678    /// # Returns
679    ///
680    /// A single `TimelockInfo` that is the combination of all others after processing each node.
681    fn timelock_info(&self) -> TimelockInfo {
682        use Policy::*;
683
684        let mut infos = vec![];
685        for data in Arc::new(self).post_order_iter() {
686            let info_for_child_n = |n| infos[data.child_indices[n]];
687
688            let info = match data.node {
689                Policy::After(ref t) => TimelockInfo {
690                    csv_with_height: false,
691                    csv_with_time: false,
692                    cltv_with_height: absolute::LockTime::from(*t).is_block_height(),
693                    cltv_with_time: absolute::LockTime::from(*t).is_block_time(),
694                    contains_combination: false,
695                },
696                Policy::Older(ref t) => TimelockInfo {
697                    csv_with_height: t.is_height_locked(),
698                    csv_with_time: t.is_time_locked(),
699                    cltv_with_height: false,
700                    cltv_with_time: false,
701                    contains_combination: false,
702                },
703                And(ref subs) => {
704                    let iter = (0..subs.len()).map(info_for_child_n);
705                    TimelockInfo::combine_threshold(subs.len(), iter)
706                }
707                Or(ref subs) => {
708                    let iter = (0..subs.len()).map(info_for_child_n);
709                    TimelockInfo::combine_threshold(1, iter)
710                }
711                Thresh(ref thresh) => {
712                    let iter = (0..thresh.n()).map(info_for_child_n);
713                    TimelockInfo::combine_threshold(thresh.k(), iter)
714                }
715                _ => TimelockInfo::default(),
716            };
717            infos.push(info);
718        }
719        // Ok to unwrap, we had to have visited at least one node.
720        infos.pop().unwrap()
721    }
722
723    /// This returns whether the given policy is valid or not. It maybe possible that the policy
724    /// contains Non-two argument `and`, `or` or a `0` arg thresh.
725    /// Validity condition also checks whether there is a possible satisfaction
726    /// combination of timelocks and heightlocks
727    pub fn is_valid(&self) -> Result<(), PolicyError> {
728        use Policy::*;
729
730        self.check_timelocks()?;
731        self.check_duplicate_keys()?;
732
733        for policy in self.pre_order_iter() {
734            match *policy {
735                And(ref subs) => {
736                    if subs.len() != 2 {
737                        return Err(PolicyError::NonBinaryArgAnd);
738                    }
739                }
740                Or(ref subs) => {
741                    if subs.len() != 2 {
742                        return Err(PolicyError::NonBinaryArgOr);
743                    }
744                }
745                _ => {}
746            }
747        }
748        Ok(())
749    }
750
751    /// Checks if any possible compilation of the policy could be compiled
752    /// as non-malleable and safe.
753    ///
754    /// # Returns
755    ///
756    /// Returns a tuple `(safe, non-malleable)` to avoid the fact that
757    /// non-malleability depends on safety and we would like to cache results.
758    pub fn is_safe_nonmalleable(&self) -> (bool, bool) {
759        use Policy::*;
760
761        let mut acc = vec![];
762        for data in Arc::new(self).post_order_iter() {
763            let acc_for_child_n = |n| acc[data.child_indices[n]];
764
765            let new = match data.node {
766                Unsatisfiable | Trivial | Key(_) => (true, true),
767                Sha256(_) | Hash256(_) | Ripemd160(_) | Hash160(_) | After(_) | Older(_) => {
768                    (false, true)
769                }
770                And(ref subs) => {
771                    let (atleast_one_safe, all_non_mall) = (0..subs.len())
772                        .map(acc_for_child_n)
773                        .fold((false, true), |acc, x: (bool, bool)| (acc.0 || x.0, acc.1 && x.1));
774                    (atleast_one_safe, all_non_mall)
775                }
776                Or(ref subs) => {
777                    let (all_safe, atleast_one_safe, all_non_mall) = (0..subs.len())
778                        .map(acc_for_child_n)
779                        .fold((true, false, true), |acc, x| {
780                            (acc.0 && x.0, acc.1 || x.0, acc.2 && x.1)
781                        });
782                    (all_safe, atleast_one_safe && all_non_mall)
783                }
784                Thresh(ref thresh) => {
785                    let (safe_count, non_mall_count) = (0..thresh.n()).map(acc_for_child_n).fold(
786                        (0, 0),
787                        |(safe_count, non_mall_count), (safe, non_mall)| {
788                            (safe_count + safe as usize, non_mall_count + non_mall as usize)
789                        },
790                    );
791                    (
792                        safe_count >= (thresh.n() - thresh.k() + 1),
793                        non_mall_count == thresh.n() && safe_count >= (thresh.n() - thresh.k()),
794                    )
795                }
796            };
797            acc.push(new);
798        }
799        // Ok to unwrap because we know we processed at least one node.
800        acc.pop().unwrap()
801    }
802}
803
804impl<Pk: MiniscriptKey> fmt::Debug for Policy<Pk> {
805    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
806        match *self {
807            Policy::Unsatisfiable => f.write_str("UNSATISFIABLE()"),
808            Policy::Trivial => f.write_str("TRIVIAL()"),
809            Policy::Key(ref pk) => write!(f, "pk({:?})", pk),
810            Policy::After(n) => write!(f, "after({})", n),
811            Policy::Older(n) => write!(f, "older({})", n),
812            Policy::Sha256(ref h) => write!(f, "sha256({})", h),
813            Policy::Hash256(ref h) => write!(f, "hash256({})", h),
814            Policy::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
815            Policy::Hash160(ref h) => write!(f, "hash160({})", h),
816            Policy::And(ref subs) => {
817                f.write_str("and(")?;
818                if !subs.is_empty() {
819                    write!(f, "{:?}", subs[0])?;
820                    for sub in &subs[1..] {
821                        write!(f, ",{:?}", sub)?;
822                    }
823                }
824                f.write_str(")")
825            }
826            Policy::Or(ref subs) => {
827                f.write_str("or(")?;
828                if !subs.is_empty() {
829                    write!(f, "{}@{:?}", subs[0].0, subs[0].1)?;
830                    for sub in &subs[1..] {
831                        write!(f, ",{}@{:?}", sub.0, sub.1)?;
832                    }
833                }
834                f.write_str(")")
835            }
836            Policy::Thresh(ref thresh) => fmt::Debug::fmt(&thresh.debug("thresh", true), f),
837        }
838    }
839}
840
841impl<Pk: MiniscriptKey> fmt::Display for Policy<Pk> {
842    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
843        match *self {
844            Policy::Unsatisfiable => f.write_str("UNSATISFIABLE"),
845            Policy::Trivial => f.write_str("TRIVIAL"),
846            Policy::Key(ref pk) => write!(f, "pk({})", pk),
847            Policy::After(n) => write!(f, "after({})", n),
848            Policy::Older(n) => write!(f, "older({})", n),
849            Policy::Sha256(ref h) => write!(f, "sha256({})", h),
850            Policy::Hash256(ref h) => write!(f, "hash256({})", h),
851            Policy::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
852            Policy::Hash160(ref h) => write!(f, "hash160({})", h),
853            Policy::And(ref subs) => {
854                f.write_str("and(")?;
855                if !subs.is_empty() {
856                    write!(f, "{}", subs[0])?;
857                    for sub in &subs[1..] {
858                        write!(f, ",{}", sub)?;
859                    }
860                }
861                f.write_str(")")
862            }
863            Policy::Or(ref subs) => {
864                f.write_str("or(")?;
865                if !subs.is_empty() {
866                    write!(f, "{}@{}", subs[0].0, subs[0].1)?;
867                    for sub in &subs[1..] {
868                        write!(f, ",{}@{}", sub.0, sub.1)?;
869                    }
870                }
871                f.write_str(")")
872            }
873            Policy::Thresh(ref thresh) => fmt::Display::fmt(&thresh.display("thresh", true), f),
874        }
875    }
876}
877
878impl<Pk: FromStrKey> str::FromStr for Policy<Pk> {
879    type Err = Error;
880    fn from_str(s: &str) -> Result<Policy<Pk>, Error> {
881        expression::check_valid_chars(s)?;
882
883        let tree = expression::Tree::from_str(s)?;
884        let policy: Policy<Pk> = FromTree::from_tree(&tree)?;
885        policy.check_timelocks()?;
886        Ok(policy)
887    }
888}
889
890serde_string_impl_pk!(Policy, "a miniscript concrete policy");
891
892impl<Pk: FromStrKey> Policy<Pk> {
893    /// Helper function for `from_tree` to parse subexpressions with
894    /// names of the form x@y
895    fn from_tree_prob(
896        top: &expression::Tree,
897        allow_prob: bool,
898    ) -> Result<(usize, Policy<Pk>), Error> {
899        let frag_prob;
900        let frag_name;
901        let mut name_split = top.name.split('@');
902        match (name_split.next(), name_split.next(), name_split.next()) {
903            (None, _, _) => {
904                frag_prob = 1;
905                frag_name = "";
906            }
907            (Some(name), None, _) => {
908                frag_prob = 1;
909                frag_name = name;
910            }
911            (Some(prob), Some(name), None) => {
912                if !allow_prob {
913                    return Err(Error::AtOutsideOr(top.name.to_owned()));
914                }
915                frag_prob = expression::parse_num(prob)? as usize;
916                frag_name = name;
917            }
918            (Some(_), Some(_), Some(_)) => {
919                return Err(Error::MultiColon(top.name.to_owned()));
920            }
921        }
922        match (frag_name, top.args.len() as u32) {
923            ("UNSATISFIABLE", 0) => Ok(Policy::Unsatisfiable),
924            ("TRIVIAL", 0) => Ok(Policy::Trivial),
925            ("pk", 1) => expression::terminal(&top.args[0], |pk| Pk::from_str(pk).map(Policy::Key)),
926            ("after", 1) => expression::terminal(&top.args[0], |x| {
927                expression::parse_num(x)
928                    .and_then(|x| AbsLockTime::from_consensus(x).map_err(Error::AbsoluteLockTime))
929                    .map(Policy::After)
930            }),
931            ("older", 1) => expression::terminal(&top.args[0], |x| {
932                expression::parse_num(x)
933                    .and_then(|x| RelLockTime::from_consensus(x).map_err(Error::RelativeLockTime))
934                    .map(Policy::Older)
935            }),
936            ("sha256", 1) => expression::terminal(&top.args[0], |x| {
937                <Pk::Sha256 as core::str::FromStr>::from_str(x).map(Policy::Sha256)
938            }),
939            ("hash256", 1) => expression::terminal(&top.args[0], |x| {
940                <Pk::Hash256 as core::str::FromStr>::from_str(x).map(Policy::Hash256)
941            }),
942            ("ripemd160", 1) => expression::terminal(&top.args[0], |x| {
943                <Pk::Ripemd160 as core::str::FromStr>::from_str(x).map(Policy::Ripemd160)
944            }),
945            ("hash160", 1) => expression::terminal(&top.args[0], |x| {
946                <Pk::Hash160 as core::str::FromStr>::from_str(x).map(Policy::Hash160)
947            }),
948            ("and", _) => {
949                if top.args.len() != 2 {
950                    return Err(Error::PolicyError(PolicyError::NonBinaryArgAnd));
951                }
952                let mut subs = Vec::with_capacity(top.args.len());
953                for arg in &top.args {
954                    subs.push(Arc::new(Policy::from_tree(arg)?));
955                }
956                Ok(Policy::And(subs))
957            }
958            ("or", _) => {
959                if top.args.len() != 2 {
960                    return Err(Error::PolicyError(PolicyError::NonBinaryArgOr));
961                }
962                let mut subs = Vec::with_capacity(top.args.len());
963                for arg in &top.args {
964                    subs.push(Policy::from_tree_prob(arg, true)?);
965                }
966                Ok(Policy::Or(
967                    subs.into_iter()
968                        .map(|(prob, sub)| (prob, Arc::new(sub)))
969                        .collect(),
970                ))
971            }
972            ("thresh", _) => top
973                .to_null_threshold()
974                .map_err(Error::ParseThreshold)?
975                .translate_by_index(|i| Policy::from_tree(&top.args[1 + i]).map(Arc::new))
976                .map(Policy::Thresh),
977            _ => Err(errstr(top.name)),
978        }
979        .map(|res| (frag_prob, res))
980    }
981}
982
983impl<Pk: FromStrKey> expression::FromTree for Policy<Pk> {
984    fn from_tree(top: &expression::Tree) -> Result<Policy<Pk>, Error> {
985        Policy::from_tree_prob(top, false).map(|(_, result)| result)
986    }
987}
988
989/// Creates a Huffman Tree from compiled [`Miniscript`] nodes.
990#[cfg(feature = "compiler")]
991fn with_huffman_tree<Pk: MiniscriptKey>(
992    ms: Vec<(OrdF64, Miniscript<Pk, Tap>)>,
993) -> Result<TapTree<Pk>, Error> {
994    let mut node_weights = BinaryHeap::<(Reverse<OrdF64>, TapTree<Pk>)>::new();
995    for (prob, script) in ms {
996        node_weights.push((Reverse(prob), TapTree::Leaf(Arc::new(script))));
997    }
998    if node_weights.is_empty() {
999        return Err(errstr("Empty Miniscript compilation"));
1000    }
1001    while node_weights.len() > 1 {
1002        let (p1, s1) = node_weights.pop().expect("len must atleast be two");
1003        let (p2, s2) = node_weights.pop().expect("len must atleast be two");
1004
1005        let p = (p1.0).0 + (p2.0).0;
1006        node_weights.push((Reverse(OrdF64(p)), TapTree::combine(s1, s2)));
1007    }
1008
1009    debug_assert!(node_weights.len() == 1);
1010    let node = node_weights
1011        .pop()
1012        .expect("huffman tree algorithm is broken")
1013        .1;
1014    Ok(node)
1015}
1016
1017/// Enumerates a [`Policy::Thresh(k, ..n..)`] into `n` different thresh's.
1018///
1019/// ## Strategy
1020///
1021/// `thresh(k, x_1...x_n) := thresh(1, thresh(k, x_2...x_n), thresh(k, x_1x_3...x_n), ...., thresh(k, x_1...x_{n-1}))`
1022/// by the simple argument that choosing `k` conditions from `n` available conditions might not contain
1023/// any one of the conditions exclusively.
1024#[cfg(feature = "compiler")]
1025fn generate_combination<Pk: MiniscriptKey>(
1026    thresh: &Threshold<Arc<Policy<Pk>>, 0>,
1027    prob: f64,
1028) -> Vec<(f64, Arc<Policy<Pk>>)> {
1029    debug_assert!(thresh.k() < thresh.n());
1030
1031    let prob_over_n = prob / thresh.n() as f64;
1032    let mut ret: Vec<(f64, Arc<Policy<Pk>>)> = vec![];
1033    for i in 0..thresh.n() {
1034        let thresh_less_1 = Threshold::from_iter(
1035            thresh.k(),
1036            thresh
1037                .iter()
1038                .enumerate()
1039                .filter_map(|(j, sub)| if j != i { Some(Arc::clone(sub)) } else { None }),
1040        )
1041        .expect("k is strictly less than n, so (k, n-1) is a valid threshold");
1042        ret.push((prob_over_n, Arc::new(Policy::Thresh(thresh_less_1))));
1043    }
1044    ret
1045}
1046
1047impl<Pk: MiniscriptKey> TreeLike for &'_ Policy<Pk> {
1048    fn as_node(&self) -> Tree<Self> {
1049        use Policy::*;
1050
1051        match *self {
1052            Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
1053            | Ripemd160(_) | Hash160(_) => Tree::Nullary,
1054            And(ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
1055            Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| p.as_ref()).collect()),
1056            Thresh(ref thresh) => Tree::Nary(thresh.iter().map(Arc::as_ref).collect()),
1057        }
1058    }
1059}
1060
1061impl<Pk: MiniscriptKey> TreeLike for Arc<Policy<Pk>> {
1062    fn as_node(&self) -> Tree<Self> {
1063        use Policy::*;
1064
1065        match self.as_ref() {
1066            Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
1067            | Ripemd160(_) | Hash160(_) => Tree::Nullary,
1068            And(ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
1069            Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::clone(p)).collect()),
1070            Thresh(ref thresh) => Tree::Nary(thresh.iter().map(Arc::clone).collect()),
1071        }
1072    }
1073}
1074
1075#[cfg(all(test, feature = "compiler"))]
1076mod compiler_tests {
1077    use core::str::FromStr;
1078
1079    use super::*;
1080
1081    #[test]
1082    fn test_gen_comb() {
1083        let policies: Vec<Arc<Concrete<String>>> = vec!["pk(A)", "pk(B)", "pk(C)", "pk(D)"]
1084            .into_iter()
1085            .map(|st| policy_str!("{}", st))
1086            .map(Arc::new)
1087            .collect();
1088        let thresh = Threshold::new(2, policies).unwrap();
1089
1090        let combinations = generate_combination(&thresh, 1.0);
1091
1092        let comb_a: Vec<Policy<String>> = vec![
1093            policy_str!("pk(B)"),
1094            policy_str!("pk(C)"),
1095            policy_str!("pk(D)"),
1096        ];
1097        let comb_b: Vec<Policy<String>> = vec![
1098            policy_str!("pk(A)"),
1099            policy_str!("pk(C)"),
1100            policy_str!("pk(D)"),
1101        ];
1102        let comb_c: Vec<Policy<String>> = vec![
1103            policy_str!("pk(A)"),
1104            policy_str!("pk(B)"),
1105            policy_str!("pk(D)"),
1106        ];
1107        let comb_d: Vec<Policy<String>> = vec![
1108            policy_str!("pk(A)"),
1109            policy_str!("pk(B)"),
1110            policy_str!("pk(C)"),
1111        ];
1112        let expected_comb = vec![comb_a, comb_b, comb_c, comb_d]
1113            .into_iter()
1114            .map(|sub_pol| {
1115                let expected_thresh =
1116                    Threshold::from_iter(2, sub_pol.into_iter().map(Arc::new)).unwrap();
1117                (0.25, Arc::new(Policy::Thresh(expected_thresh)))
1118            })
1119            .collect::<Vec<_>>();
1120        assert_eq!(combinations, expected_comb);
1121    }
1122}
1123
1124#[cfg(test)]
1125mod tests {
1126    use std::str::FromStr;
1127
1128    use super::*;
1129
1130    #[test]
1131    fn for_each_key_count_keys() {
1132        let liquid_pol = Policy::<String>::from_str(
1133            "or(and(older(4096),thresh(2,pk(A),pk(B),pk(C))),thresh(11,pk(F1),pk(F2),pk(F3),pk(F4),pk(F5),pk(F6),pk(F7),pk(F8),pk(F9),pk(F10),pk(F11),pk(F12),pk(F13),pk(F14)))").unwrap();
1134        let mut count = 0;
1135        assert!(liquid_pol.for_each_key(|_| {
1136            count += 1;
1137            true
1138        }));
1139        assert_eq!(count, 17);
1140    }
1141
1142    #[test]
1143    fn for_each_key_fails_predicate() {
1144        let policy =
1145            Policy::<String>::from_str("or(and(pk(key0),pk(key1)),pk(oddnamedkey))").unwrap();
1146        assert!(!policy.for_each_key(|k| k.starts_with("key")));
1147    }
1148
1149    #[test]
1150    fn tranaslate_pk() {
1151        pub struct TestTranslator;
1152        impl Translator<String, String, ()> for TestTranslator {
1153            fn pk(&mut self, pk: &String) -> Result<String, ()> {
1154                let new = format!("NEW-{}", pk);
1155                Ok(new.to_string())
1156            }
1157            fn sha256(&mut self, hash: &String) -> Result<String, ()> { Ok(hash.to_string()) }
1158            fn hash256(&mut self, hash: &String) -> Result<String, ()> { Ok(hash.to_string()) }
1159            fn ripemd160(&mut self, hash: &String) -> Result<String, ()> { Ok(hash.to_string()) }
1160            fn hash160(&mut self, hash: &String) -> Result<String, ()> { Ok(hash.to_string()) }
1161        }
1162        let policy = Policy::<String>::from_str("or(and(pk(A),pk(B)),pk(C))").unwrap();
1163        let mut t = TestTranslator;
1164
1165        let want = Policy::<String>::from_str("or(and(pk(NEW-A),pk(NEW-B)),pk(NEW-C))").unwrap();
1166        let got = policy
1167            .translate_pk(&mut t)
1168            .expect("failed to translate keys");
1169
1170        assert_eq!(got, want);
1171    }
1172
1173    #[test]
1174    fn translate_unsatisfiable_pk() {
1175        let policy = Policy::<String>::from_str("or(and(pk(A),pk(B)),pk(C))").unwrap();
1176
1177        let want = Policy::<String>::from_str("or(and(pk(A),UNSATISFIABLE),pk(C))").unwrap();
1178        let got = policy.translate_unsatisfiable_pk(&"B".to_string());
1179
1180        assert_eq!(got, want);
1181    }
1182
1183    #[test]
1184    fn keys() {
1185        let policy = Policy::<String>::from_str("or(and(pk(A),pk(B)),pk(C))").unwrap();
1186
1187        let want = vec!["A", "B", "C"];
1188        let got = policy.keys();
1189
1190        assert_eq!(got, want);
1191    }
1192
1193    #[test]
1194    #[cfg(feature = "compiler")]
1195    fn num_tap_leaves() {
1196        let policy = Policy::<String>::from_str("or(and(pk(A),pk(B)),pk(C))").unwrap();
1197        assert_eq!(policy.num_tap_leaves(), 2);
1198    }
1199
1200    #[test]
1201    #[should_panic]
1202    fn check_timelocks() {
1203        // This implicitly tests the check_timelocks API (has height and time locks).
1204        let _ = Policy::<String>::from_str("and(after(10),after(500000000))").unwrap();
1205    }
1206}