Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
28 changes: 1 addition & 27 deletions src/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub use tree::{
};

use crate::sync::Arc;
use crate::{policy, Miniscript, MiniscriptKey, ScriptContext, Terminal};
use crate::{Miniscript, MiniscriptKey, ScriptContext, Terminal};

impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> TreeLike for &'a Miniscript<Pk, Ctx> {
fn as_node(&self) -> Tree<Self> {
Expand Down Expand Up @@ -68,29 +68,3 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> TreeLike for Arc<Miniscript<Pk, Ctx>
}
}
}

impl<'a, Pk: MiniscriptKey> TreeLike for &'a policy::Concrete<Pk> {
fn as_node(&self) -> Tree<Self> {
use policy::Concrete::*;
match *self {
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
And(ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| p.as_ref()).collect()),
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
}
}
}

impl<'a, Pk: MiniscriptKey> TreeLike for Arc<policy::Concrete<Pk>> {
fn as_node(&self) -> Tree<Self> {
use policy::Concrete::*;
match self.as_ref() {
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
And(ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::clone(p)).collect()),
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
}
}
}
30 changes: 29 additions & 1 deletion src/policy/concrete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use {

use super::ENTAILMENT_MAX_TERMINALS;
use crate::expression::{self, FromTree};
use crate::iter::TreeLike;
use crate::iter::{Tree, TreeLike};
use crate::miniscript::types::extra_props::TimelockInfo;
use crate::prelude::*;
use crate::sync::Arc;
Expand Down Expand Up @@ -1114,6 +1114,34 @@ fn generate_combination<Pk: MiniscriptKey>(
ret
}

impl<'a, Pk: MiniscriptKey> TreeLike for &'a Policy<Pk> {
fn as_node(&self) -> Tree<Self> {
use Policy::*;

match *self {
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
And(ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| p.as_ref()).collect()),
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
}
}
}

impl<'a, Pk: MiniscriptKey> TreeLike for Arc<Policy<Pk>> {
fn as_node(&self) -> Tree<Self> {
use Policy::*;

match self.as_ref() {
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
And(ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::clone(p)).collect()),
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
}
}
}

#[cfg(all(test, feature = "compiler"))]
mod compiler_tests {
use core::str::FromStr;
Expand Down
71 changes: 43 additions & 28 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,40 @@ 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(Arc::new).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 +209,22 @@ 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(Arc::new).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(Arc::new).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(Arc::new).collect();
Semantic::Threshold(k, semantic_subs)
}
}
.normalized();
Expand All @@ -223,14 +240,12 @@ mod tests {
use core::str::FromStr;

use bitcoin::Sequence;
#[cfg(feature = "compiler")]
use sync::Arc;

use super::super::miniscript::context::Segwitv0;
use super::super::miniscript::Miniscript;
use super::{Concrete, Liftable, Semantic};
use super::*;
#[cfg(feature = "compiler")]
use crate::descriptor::Tr;
use crate::miniscript::context::Segwitv0;
use crate::miniscript::Miniscript;
use crate::prelude::*;
#[cfg(feature = "compiler")]
use crate::{descriptor::TapTree, Descriptor, Tap};
Expand Down Expand Up @@ -348,14 +363,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