|
23 | 23 |
|
24 | 24 | use super::ENTAILMENT_MAX_TERMINALS;
|
25 | 25 | use crate::expression::{self, FromTree};
|
| 26 | +use crate::iter::TreeLike; |
26 | 27 | use crate::miniscript::types::extra_props::TimelockInfo;
|
27 | 28 | use crate::prelude::*;
|
28 | 29 | use crate::sync::Arc;
|
@@ -623,28 +624,34 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
|
623 | 624 |
|
624 | 625 | /// Translates `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting `TapKey`.
|
625 | 626 | pub fn translate_unsatisfiable_pk(self, key: &Pk) -> Policy<Pk> {
|
626 |
| - match self { |
627 |
| - Policy::Key(ref k) if k.clone() == *key => Policy::Unsatisfiable, |
628 |
| - Policy::And(subs) => Policy::And( |
629 |
| - subs.into_iter() |
630 |
| - .map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key))) |
631 |
| - .collect::<Vec<_>>(), |
632 |
| - ), |
633 |
| - Policy::Or(subs) => Policy::Or( |
634 |
| - subs.into_iter() |
635 |
| - .map(|(k, sub)| { |
636 |
| - (k, Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key))) |
637 |
| - }) |
638 |
| - .collect::<Vec<_>>(), |
639 |
| - ), |
640 |
| - Policy::Threshold(k, subs) => Policy::Threshold( |
641 |
| - k, |
642 |
| - subs.into_iter() |
643 |
| - .map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key))) |
644 |
| - .collect::<Vec<_>>(), |
645 |
| - ), |
646 |
| - x => x, |
| 627 | + use Policy::*; |
| 628 | + |
| 629 | + let mut translated = vec![]; |
| 630 | + for data in Arc::new(self).post_order_iter() { |
| 631 | + let child_n = |n| Arc::clone(&translated[data.child_indices[n]]); |
| 632 | + |
| 633 | + let new_policy = match data.node.as_ref() { |
| 634 | + Policy::Key(ref k) if k.clone() == *key => Some(Policy::Unsatisfiable), |
| 635 | + Threshold(k, ref subs) => { |
| 636 | + Some(Threshold(*k, (0..subs.len()).map(child_n).collect())) |
| 637 | + } |
| 638 | + And(ref subs) => Some(And((0..subs.len()).map(child_n).collect())), |
| 639 | + Or(ref subs) => Some(Or(subs |
| 640 | + .iter() |
| 641 | + .enumerate() |
| 642 | + .map(|(i, (prob, _))| (*prob, child_n(i))) |
| 643 | + .collect())), |
| 644 | + _ => None, |
| 645 | + }; |
| 646 | + match new_policy { |
| 647 | + Some(new_policy) => translated.push(Arc::new(new_policy)), |
| 648 | + None => translated.push(Arc::clone(&data.node)), |
| 649 | + } |
647 | 650 | }
|
| 651 | + // Ok to unwrap because we know we processed at least one node. |
| 652 | + let root_node = translated.pop().unwrap(); |
| 653 | + // Ok to unwrap because we know `root_node` is the only strong reference. |
| 654 | + Arc::try_unwrap(root_node).unwrap() |
648 | 655 | }
|
649 | 656 |
|
650 | 657 | /// Gets all keys in the policy.
|
|
0 commit comments