Skip to content

Commit

Permalink
Add Arc to the semantic::Policy::Thresh vector
Browse files Browse the repository at this point in the history
In preparation for removing recursive algorithms in the `semantic`
module add an `Arc` wrapper around the policies in the `Thresh` vector.

Note we use the more explicit `Arc::new` instead of `into` because a lot
of these should be removed when we remove recursion, later it may be
necessary to check that we are not creating new references when a clone
will suffice, the explicit `Arc::new` is easier to check. In tests
however just use `into`.
  • Loading branch information
tcharding committed Oct 11, 2023
1 parent 3335434 commit 9de17fc
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 70 deletions.
3 changes: 2 additions & 1 deletion src/descriptor/sortedmulti.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
use crate::miniscript::satisfy::{Placeholder, Satisfaction};
use crate::plan::AssetProvider;
use crate::prelude::*;
use crate::sync::Arc;
use crate::{
errstr, expression, policy, script_num_size, Error, ForEachKey, Miniscript, MiniscriptKey,
Satisfier, ToPublicKey, TranslateErr, Translator,
Expand Down Expand Up @@ -201,7 +202,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> policy::Liftable<Pk> for SortedMulti
self.k,
self.pks
.iter()
.map(|k| policy::semantic::Policy::Key(k.clone()))
.map(|k| Arc::new(policy::semantic::Policy::Key(k.clone())))
.collect(),
);
Ok(ret)
Expand Down
17 changes: 11 additions & 6 deletions src/descriptor/tr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,10 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for TapTree<Pk> {
fn lift(&self) -> Result<Policy<Pk>, Error> {
fn lift_helper<Pk: MiniscriptKey>(s: &TapTree<Pk>) -> Result<Policy<Pk>, Error> {
match *s {
TapTree::Tree { ref left, ref right, height: _ } => {
Ok(Policy::Threshold(1, vec![lift_helper(left)?, lift_helper(right)?]))
}
TapTree::Tree { ref left, ref right, height: _ } => Ok(Policy::Threshold(
1,
vec![Arc::new(lift_helper(left)?), Arc::new(lift_helper(right)?)],
)),
TapTree::Leaf(ref leaf) => leaf.lift(),
}
}
Expand All @@ -635,9 +636,13 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for TapTree<Pk> {
impl<Pk: MiniscriptKey> Liftable<Pk> for Tr<Pk> {
fn lift(&self) -> Result<Policy<Pk>, Error> {
match &self.tree {
Some(root) => {
Ok(Policy::Threshold(1, vec![Policy::Key(self.internal_key.clone()), root.lift()?]))
}
Some(root) => Ok(Policy::Threshold(
1,
vec![
Arc::new(Policy::Key(self.internal_key.clone())),
Arc::new(root.lift()?),
],
)),
None => Ok(Policy::Key(self.internal_key.clone())),
}
}
Expand Down
75 changes: 52 additions & 23 deletions src/policy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub use self::semantic::Policy as Semantic;
use crate::descriptor::Descriptor;
use crate::miniscript::{Miniscript, ScriptContext};
use crate::sync::Arc;
use crate::{Error, MiniscriptKey, Terminal};
use crate::{Error, MiniscriptKey, Terminal, Vec};

/// Policy entailment algorithm maximum number of terminals allowed.
const ENTAILMENT_MAX_TERMINALS: usize = 20;
Expand Down Expand Up @@ -136,28 +136,43 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Liftable<Pk> for Terminal<Pk, Ctx> {
| Terminal::NonZero(ref sub)
| Terminal::ZeroNotEqual(ref sub) => sub.node.lift()?,
Terminal::AndV(ref left, ref right) | Terminal::AndB(ref left, ref right) => {
Semantic::Threshold(2, vec![left.node.lift()?, right.node.lift()?])
Semantic::Threshold(
2,
vec![Arc::new(left.node.lift()?), Arc::new(right.node.lift()?)],
)
}
Terminal::AndOr(ref a, ref b, ref c) => Semantic::Threshold(
1,
vec![
Semantic::Threshold(2, vec![a.node.lift()?, b.node.lift()?]),
c.node.lift()?,
Arc::new(Semantic::Threshold(
2,
vec![Arc::new(a.node.lift()?), Arc::new(b.node.lift()?)],
)),
Arc::new(c.node.lift()?),
],
),
Terminal::OrB(ref left, ref right)
| Terminal::OrD(ref left, ref right)
| Terminal::OrC(ref left, ref right)
| Terminal::OrI(ref left, ref right) => {
Semantic::Threshold(1, vec![left.node.lift()?, right.node.lift()?])
}
| Terminal::OrI(ref left, ref right) => Semantic::Threshold(
1,
vec![Arc::new(left.node.lift()?), Arc::new(right.node.lift()?)],
),
Terminal::Thresh(k, ref subs) => {
let semantic_subs: Result<_, Error> = subs.iter().map(|s| s.node.lift()).collect();
Semantic::Threshold(k, semantic_subs?)
}
Terminal::Multi(k, ref keys) | Terminal::MultiA(k, ref keys) => {
Semantic::Threshold(k, keys.iter().map(|k| Semantic::Key(k.clone())).collect())
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
subs.iter().map(|s| s.node.lift()).collect();
let semantic_subs = semantic_subs?
.into_iter()
.map(|sub| Arc::new(sub))
.collect();
Semantic::Threshold(k, semantic_subs)
}
Terminal::Multi(k, ref keys) | Terminal::MultiA(k, ref keys) => Semantic::Threshold(
k,
keys.iter()
.map(|k| Arc::new(Semantic::Key(k.clone())))
.collect(),
),
}
.normalized();
Ok(ret)
Expand Down Expand Up @@ -197,17 +212,31 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Concrete<Pk> {
Concrete::Ripemd160(ref h) => Semantic::Ripemd160(h.clone()),
Concrete::Hash160(ref h) => Semantic::Hash160(h.clone()),
Concrete::And(ref subs) => {
let semantic_subs: Result<_, Error> = subs.iter().map(Liftable::lift).collect();
Semantic::Threshold(2, semantic_subs?)
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
subs.iter().map(Liftable::lift).collect();
let semantic_subs = semantic_subs?
.into_iter()
.map(|sub| Arc::new(sub))
.collect();
Semantic::Threshold(2, semantic_subs)
}
Concrete::Or(ref subs) => {
let semantic_subs: Result<_, Error> =
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
subs.iter().map(|(_p, sub)| sub.lift()).collect();
Semantic::Threshold(1, semantic_subs?)
let semantic_subs = semantic_subs?
.into_iter()
.map(|sub| Arc::new(sub))
.collect();
Semantic::Threshold(1, semantic_subs)
}
Concrete::Threshold(k, ref subs) => {
let semantic_subs: Result<_, Error> = subs.iter().map(Liftable::lift).collect();
Semantic::Threshold(k, semantic_subs?)
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
subs.iter().map(Liftable::lift).collect();
let semantic_subs = semantic_subs?
.into_iter()
.map(|sub| Arc::new(sub))
.collect();
Semantic::Threshold(k, semantic_subs)
}
}
.normalized();
Expand Down Expand Up @@ -346,14 +375,14 @@ mod tests {
Semantic::Threshold(
1,
vec![
Semantic::Threshold(
Arc::new(Semantic::Threshold(
2,
vec![
Semantic::Key(key_a),
Semantic::Older(Sequence::from_height(42))
Arc::new(Semantic::Key(key_a)),
Arc::new(Semantic::Older(Sequence::from_height(42)))
]
),
Semantic::Key(key_b)
)),
Arc::new(Semantic::Key(key_b))
]
),
ms_str.lift().unwrap()
Expand Down
Loading

0 comments on commit 9de17fc

Please sign in to comment.