|
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;
|
@@ -635,31 +636,34 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
|
635 | 636 |
|
636 | 637 | /// Translates `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting `TapKey`.
|
637 | 638 | pub fn translate_unsatisfiable_pk(self, key: &Pk) -> Policy<Pk> {
|
638 |
| - match self { |
639 |
| - Policy::Key(ref k) if k.clone() == *key => Policy::Unsatisfiable, |
640 |
| - Policy::And(subs) => Policy::And( |
641 |
| - subs.into_iter() |
642 |
| - .map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key))) |
643 |
| - .collect::<Vec<_>>(), |
644 |
| - ), |
645 |
| - Policy::Or(subs) => Policy::Or( |
646 |
| - subs.into_iter() |
647 |
| - .map(|(k, sub)| { |
648 |
| - ( |
649 |
| - k, |
650 |
| - Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key)), |
651 |
| - ) |
652 |
| - }) |
653 |
| - .collect::<Vec<_>>(), |
654 |
| - ), |
655 |
| - Policy::Threshold(k, subs) => Policy::Threshold( |
656 |
| - k, |
657 |
| - subs.into_iter() |
658 |
| - .map(|sub| Arc::new(sub.as_ref().clone().translate_unsatisfiable_pk(key))) |
659 |
| - .collect::<Vec<_>>(), |
660 |
| - ), |
661 |
| - x => x, |
| 639 | + use Policy::*; |
| 640 | + |
| 641 | + let mut translated = vec![]; |
| 642 | + for data in Arc::new(self).post_order_iter() { |
| 643 | + let child_n = |n| Arc::clone(&translated[data.child_indices[n]]); |
| 644 | + |
| 645 | + let new_policy = match data.node.as_ref() { |
| 646 | + Policy::Key(ref k) if k.clone() == *key => Some(Policy::Unsatisfiable), |
| 647 | + Threshold(k, ref subs) => { |
| 648 | + Some(Threshold(*k, (0..subs.len()).map(child_n).collect())) |
| 649 | + } |
| 650 | + And(ref subs) => Some(And((0..subs.len()).map(child_n).collect())), |
| 651 | + Or(ref subs) => Some(Or(subs |
| 652 | + .iter() |
| 653 | + .enumerate() |
| 654 | + .map(|(i, (prob, _))| (*prob, child_n(i))) |
| 655 | + .collect())), |
| 656 | + _ => None, |
| 657 | + }; |
| 658 | + match new_policy { |
| 659 | + Some(new_policy) => translated.push(Arc::new(new_policy)), |
| 660 | + None => translated.push(Arc::clone(&data.node)), |
| 661 | + } |
662 | 662 | }
|
| 663 | + // Ok to unwrap because we know we processed at least one node. |
| 664 | + let root_node = translated.pop().unwrap(); |
| 665 | + // Ok to unwrap because we know `root_node` is the only strong reference. |
| 666 | + Arc::try_unwrap(root_node).unwrap() |
663 | 667 | }
|
664 | 668 |
|
665 | 669 | /// Gets all keys in the policy.
|
|
0 commit comments