Skip to content

Commit 01a31db

Browse files
committed
Implement TreeLike for policy::Concrete
Implement `TreeLike` for `policy::Concrete` as we do for `Miniscript`. Make use of `TreeLike` to remove some recursion from the `policy::concrete` module. QUESTIONS: - Why do we have `PolicyArc`? With this applied `Policy` is the same as `PolicyArc`? - I'm not sure I've got all the `AsRef` stuff correct (ie, written in the most simple way).
1 parent df9fffb commit 01a31db

File tree

3 files changed

+99
-93
lines changed

3 files changed

+99
-93
lines changed

Diff for: src/iter/mod.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use tree::{
1515
};
1616

1717
use crate::sync::Arc;
18-
use crate::{Miniscript, MiniscriptKey, ScriptContext, Terminal};
18+
use crate::{policy, Miniscript, MiniscriptKey, ScriptContext, Terminal};
1919

2020
impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> TreeLike for &'a Miniscript<Pk, Ctx> {
2121
fn as_node(&self) -> Tree<Self> {
@@ -68,3 +68,31 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> TreeLike for Arc<Miniscript<Pk, Ctx>
6868
}
6969
}
7070
}
71+
72+
impl<'a, Pk: MiniscriptKey> TreeLike for &'a policy::Concrete<Pk> {
73+
fn as_node(&self) -> Tree<Self> {
74+
use policy::Concrete::*;
75+
76+
match *self {
77+
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
78+
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
79+
And(ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
80+
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::as_ref(p)).collect()),
81+
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
82+
}
83+
}
84+
}
85+
86+
impl<'a, Pk: MiniscriptKey> TreeLike for Arc<policy::Concrete<Pk>> {
87+
fn as_node(&self) -> Tree<Self> {
88+
use policy::Concrete::*;
89+
90+
match self.as_ref() {
91+
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
92+
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
93+
And(ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
94+
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::clone(p)).collect()),
95+
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
96+
}
97+
}
98+
}

Diff for: src/policy/concrete.rs

+66-90
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use core::{fmt, str};
88
use std::error;
99

1010
use bitcoin::{absolute, Sequence};
11+
use sync::Arc;
1112
#[cfg(feature = "compiler")]
1213
use {
1314
crate::descriptor::TapTree,
@@ -19,11 +20,11 @@ use {
1920
crate::Miniscript,
2021
crate::Tap,
2122
core::cmp::Reverse,
22-
sync::Arc,
2323
};
2424

2525
use super::ENTAILMENT_MAX_TERMINALS;
2626
use crate::expression::{self, FromTree};
27+
use crate::iter::TreeLike;
2728
use crate::miniscript::types::extra_props::TimelockInfo;
2829
use crate::prelude::*;
2930
#[cfg(all(doc, not(feature = "compiler")))]
@@ -58,12 +59,12 @@ pub enum Policy<Pk: MiniscriptKey> {
5859
/// A HASH160 whose preimage must be provided to satisfy the descriptor.
5960
Hash160(Pk::Hash160),
6061
/// A list of sub-policies, all of which must be satisfied.
61-
And(Vec<Policy<Pk>>),
62+
And(Vec<Arc<Policy<Pk>>>),
6263
/// A list of sub-policies, one of which must be satisfied, along with
6364
/// relative probabilities for each one.
64-
Or(Vec<(usize, Policy<Pk>)>),
65+
Or(Vec<(usize, Arc<Policy<Pk>>)>),
6566
/// A set of descriptors, satisfactions must be provided for `k` of them.
66-
Threshold(usize, Vec<Policy<Pk>>),
67+
Threshold(usize, Vec<Arc<Policy<Pk>>>),
6768
}
6869

6970
impl<Pk> Policy<Pk>
@@ -656,30 +657,21 @@ impl<Pk: MiniscriptKey> PolicyArc<Pk> {
656657

657658
impl<Pk: MiniscriptKey> ForEachKey<Pk> for Policy<Pk> {
658659
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool {
659-
self.real_for_each_key(&mut pred)
660-
}
661-
}
662-
663-
impl<Pk: MiniscriptKey> Policy<Pk> {
664-
fn real_for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: &mut F) -> bool {
665-
match *self {
666-
Policy::Unsatisfiable | Policy::Trivial => true,
667-
Policy::Key(ref pk) => pred(pk),
668-
Policy::Sha256(..)
669-
| Policy::Hash256(..)
670-
| Policy::Ripemd160(..)
671-
| Policy::Hash160(..)
672-
| Policy::After(..)
673-
| Policy::Older(..) => true,
674-
Policy::Threshold(_, ref subs) | Policy::And(ref subs) => {
675-
subs.iter().all(|sub| sub.real_for_each_key(&mut *pred))
660+
for policy in self.pre_order_iter() {
661+
match policy {
662+
Policy::Key(ref pk) => {
663+
if !pred(pk) {
664+
return false;
665+
}
666+
}
667+
_ => {}
676668
}
677-
Policy::Or(ref subs) => subs
678-
.iter()
679-
.all(|(_, sub)| sub.real_for_each_key(&mut *pred)),
680669
}
670+
true
681671
}
672+
}
682673

674+
impl<Pk: MiniscriptKey> Policy<Pk> {
683675
/// Converts a policy using one kind of public key to another type of public key.
684676
///
685677
/// For example usage please see [`crate::policy::semantic::Policy::translate_pk`].
@@ -688,81 +680,65 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
688680
T: Translator<Pk, Q, E>,
689681
Q: MiniscriptKey,
690682
{
691-
self._translate_pk(t)
692-
}
693-
694-
fn _translate_pk<Q, E, T>(&self, t: &mut T) -> Result<Policy<Q>, E>
695-
where
696-
T: Translator<Pk, Q, E>,
697-
Q: MiniscriptKey,
698-
{
699-
match *self {
700-
Policy::Unsatisfiable => Ok(Policy::Unsatisfiable),
701-
Policy::Trivial => Ok(Policy::Trivial),
702-
Policy::Key(ref pk) => t.pk(pk).map(Policy::Key),
703-
Policy::Sha256(ref h) => t.sha256(h).map(Policy::Sha256),
704-
Policy::Hash256(ref h) => t.hash256(h).map(Policy::Hash256),
705-
Policy::Ripemd160(ref h) => t.ripemd160(h).map(Policy::Ripemd160),
706-
Policy::Hash160(ref h) => t.hash160(h).map(Policy::Hash160),
707-
Policy::Older(n) => Ok(Policy::Older(n)),
708-
Policy::After(n) => Ok(Policy::After(n)),
709-
Policy::Threshold(k, ref subs) => {
710-
let new_subs: Result<Vec<Policy<Q>>, _> =
711-
subs.iter().map(|sub| sub._translate_pk(t)).collect();
712-
new_subs.map(|ok| Policy::Threshold(k, ok))
713-
}
714-
Policy::And(ref subs) => Ok(Policy::And(
715-
subs.iter()
716-
.map(|sub| sub._translate_pk(t))
717-
.collect::<Result<Vec<Policy<Q>>, E>>()?,
718-
)),
719-
Policy::Or(ref subs) => Ok(Policy::Or(
720-
subs.iter()
721-
.map(|(prob, sub)| Ok((*prob, sub._translate_pk(t)?)))
722-
.collect::<Result<Vec<(usize, Policy<Q>)>, E>>()?,
723-
)),
683+
use Policy::*;
684+
685+
let mut translated = vec![];
686+
for data in Arc::new(self.clone()).post_order_iter() {
687+
// convenience method to reduce typing
688+
let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
689+
690+
let new_policy = match data.node.as_ref() {
691+
Unsatisfiable => Unsatisfiable,
692+
Trivial => Trivial,
693+
Key(ref pk) => t.pk(pk).map(Key)?,
694+
Sha256(ref h) => t.sha256(h).map(Sha256)?,
695+
Hash256(ref h) => t.hash256(h).map(Hash256)?,
696+
Ripemd160(ref h) => t.ripemd160(h).map(Ripemd160)?,
697+
Hash160(ref h) => t.hash160(h).map(Hash160)?,
698+
Older(n) => Older(*n),
699+
After(n) => After(*n),
700+
Threshold(k, ref subs) => Threshold(*k, (0..subs.len()).map(child_n).collect()),
701+
And(ref subs) => And((0..subs.len()).map(child_n).collect()),
702+
Or(ref subs) => Or((0..subs.len()).map(|i| (i, child_n(i))).collect()),
703+
};
704+
translated.push(Arc::new(new_policy));
724705
}
706+
707+
Ok(Arc::try_unwrap(translated.pop().unwrap()).unwrap())
725708
}
726709

727710
/// Translates `Concrete::Key(key)` to `Concrete::Unsatisfiable` when extracting `TapKey`.
728711
pub fn translate_unsatisfiable_pk(self, key: &Pk) -> Policy<Pk> {
729-
match self {
730-
Policy::Key(ref k) if k.clone() == *key => Policy::Unsatisfiable,
731-
Policy::And(subs) => Policy::And(
732-
subs.into_iter()
733-
.map(|sub| sub.translate_unsatisfiable_pk(key))
734-
.collect::<Vec<_>>(),
735-
),
736-
Policy::Or(subs) => Policy::Or(
737-
subs.into_iter()
738-
.map(|(k, sub)| (k, sub.translate_unsatisfiable_pk(key)))
739-
.collect::<Vec<_>>(),
740-
),
741-
Policy::Threshold(k, subs) => Policy::Threshold(
742-
k,
743-
subs.into_iter()
744-
.map(|sub| sub.translate_unsatisfiable_pk(key))
745-
.collect::<Vec<_>>(),
746-
),
747-
x => x,
712+
use Policy::*;
713+
714+
let mut translated = vec![];
715+
for data in Arc::new(self.clone()).post_order_iter() {
716+
// convenience method to reduce typing
717+
let child_n = |n| Arc::clone(&translated[data.child_indices[n]]);
718+
719+
let new_policy = match data.node.as_ref() {
720+
Policy::Key(ref k) if k.clone() == *key => Policy::Unsatisfiable,
721+
Threshold(k, ref subs) => Threshold(*k, (0..subs.len()).map(child_n).collect()),
722+
And(ref subs) => And((0..subs.len()).map(child_n).collect()),
723+
Or(ref subs) => Or((0..subs.len()).map(|i| (i, child_n(i))).collect()),
724+
x => x.clone(),
725+
};
726+
translated.push(Arc::new(new_policy));
748727
}
728+
729+
Arc::try_unwrap(translated.pop().unwrap()).unwrap()
749730
}
750731

751732
/// Gets all keys in the policy.
752733
pub fn keys(&self) -> Vec<&Pk> {
753-
match *self {
754-
Policy::Key(ref pk) => vec![pk],
755-
Policy::Threshold(_k, ref subs) => {
756-
subs.iter().flat_map(|sub| sub.keys()).collect::<Vec<_>>()
734+
let mut keys = vec![];
735+
for policy in self.pre_order_iter() {
736+
match policy {
737+
Policy::Key(ref pk) => keys.push(pk),
738+
_ => {}
757739
}
758-
Policy::And(ref subs) => subs.iter().flat_map(|sub| sub.keys()).collect::<Vec<_>>(),
759-
Policy::Or(ref subs) => subs
760-
.iter()
761-
.flat_map(|(ref _k, ref sub)| sub.keys())
762-
.collect::<Vec<_>>(),
763-
// map all hashes and time
764-
_ => vec![],
765740
}
741+
keys
766742
}
767743

768744
/// Gets the number of [TapLeaf](`TapTree::Leaf`)s considering exhaustive root-level [`Policy::Or`]
@@ -1144,7 +1120,7 @@ impl_block_str!(
11441120
for arg in &top.args {
11451121
subs.push(Policy::from_tree(arg)?);
11461122
}
1147-
Ok(Policy::And(subs))
1123+
Ok(Policy::And(subs.into_iter().map(|p| Arc::new(p)).collect()))
11481124
}
11491125
("or", _) => {
11501126
if top.args.len() != 2 {
@@ -1154,7 +1130,7 @@ impl_block_str!(
11541130
for arg in &top.args {
11551131
subs.push(Policy::from_tree_prob(arg, true)?);
11561132
}
1157-
Ok(Policy::Or(subs))
1133+
Ok(Policy::Or(subs.into_iter().map(|(probability, policy)| (probability, Arc::new(policy))).collect()))
11581134
}
11591135
("thresh", nsubs) => {
11601136
if top.args.is_empty() || !top.args[0].args.is_empty() {
@@ -1170,7 +1146,7 @@ impl_block_str!(
11701146
for arg in &top.args[1..] {
11711147
subs.push(Policy::from_tree(arg)?);
11721148
}
1173-
Ok(Policy::Threshold(thresh as usize, subs))
1149+
Ok(Policy::Threshold(thresh as usize, subs.into_iter().map(|p| Arc::new(p)).collect()))
11741150
}
11751151
_ => Err(errstr(top.name)),
11761152
}

Diff for: src/policy/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Concrete<Pk> {
198198
Concrete::Ripemd160(ref h) => Semantic::Ripemd160(h.clone()),
199199
Concrete::Hash160(ref h) => Semantic::Hash160(h.clone()),
200200
Concrete::And(ref subs) => {
201-
let semantic_subs: Result<_, Error> = subs.iter().map(Liftable::lift).collect();
201+
let semantic_subs: Result<_, Error> =
202+
subs.iter().map(|p| Liftable::lift(p.as_ref())).collect();
202203
Semantic::Threshold(2, semantic_subs?)
203204
}
204205
Concrete::Or(ref subs) => {
@@ -207,7 +208,8 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Concrete<Pk> {
207208
Semantic::Threshold(1, semantic_subs?)
208209
}
209210
Concrete::Threshold(k, ref subs) => {
210-
let semantic_subs: Result<_, Error> = subs.iter().map(Liftable::lift).collect();
211+
let semantic_subs: Result<_, Error> =
212+
subs.iter().map(|p| Liftable::lift(p.as_ref())).collect();
211213
Semantic::Threshold(k, semantic_subs?)
212214
}
213215
}

0 commit comments

Comments
 (0)