Skip to content

Commit 254150a

Browse files
committed
Merge rust-bitcoin/rust-miniscript#612: Remove recursion in semantic module
f9307c8ced48b55b899f1f006117aeded51772e2 semantic: Remove recursion in sorted (Tobin C. Harding) 09a47cb0de9f7be5d6dc85163cd59a1edf2d741b semantic: Remove recursion in minimum_n_keys (Tobin C. Harding) eb75602f8c2ac12fbb514c3ec297c80e04d0ba3b semantic: Remove recursion in n_keys (Tobin C. Harding) d9f9d43e5139c8cab644df067a43a948021cbf61 semantic: Remove recursion in at_age and at_lock_time (Tobin C. Harding) c3c5e726ce79ad797ce5e860b429d5063ba6180c semantic: Remove recursion in real_*_timelocks (Tobin C. Harding) b1ae1ff0b31730a58be26792fcff0e7f0b1b86eb semantic: Remove recursion in n_terminals (Tobin C. Harding) 211abad49a94326a01ee605d3c9bbb929bc940ff semantic: Remove recursion in translate_pk (Tobin C. Harding) 97ba4e9a6500a75e96c56d3a0027ab118419e317 semantic: Remove recursion in for_each_key (Tobin C. Harding) df3a85a76f5cbca2991111eafe7ca636502f16df Implement TreeLike for semantic::Policy (Tobin C. Harding) e813ad0799aeb62526953fb6b22e2c015409b4cb Add Arc to the semantic::Policy::Thresh vector (Tobin C. Harding) 0ef5e54f8ae0110dd67b78d68840149cacba9090 Move TreeLike impl to concrete module (Tobin C. Harding) 161753c41d69ddc594a45b9ae32decb1847e2ca6 Fix imports in test module (Tobin C. Harding) 2fd42d667b7e6900b44dee2f4555ca884fba6edf Improve spacing in error string (Tobin C. Harding) 721e16bc0336e2cb769a9c0264713c322c9804ae Use unwrap_or (Tobin C. Harding) 10e59821a79a7c8a664bf40983b585757adf44d6 Add line of whitespace (Tobin C. Harding) 61b45a911d3756cbd216a673ddfc9e50e0c214e6 Remove code comment (Tobin C. Harding) Pull request description: Remove most of the recursion in the `semantic` module. Does not do `normalized` and associated functions (ones that either call it or take in a normalized policy). Includes 4 trivial preparatory clean up patches at the front. ACKs for top commit: apoelstra: ACK f9307c8ced48b55b899f1f006117aeded51772e2 Tree-SHA512: dd2eac15ecd2a672436ffe7b21277c72406c92d3e3434ac2046e7ebd4cba98e02db4ce5e39ed73f0bfcc2388610e871acd578655461bdb99e8beaa2aac4aefb5
2 parents dd3588b + 303dcbb commit 254150a

File tree

6 files changed

+340
-236
lines changed

6 files changed

+340
-236
lines changed

src/descriptor/sortedmulti.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG;
1717
use crate::miniscript::satisfy::{Placeholder, Satisfaction};
1818
use crate::plan::AssetProvider;
1919
use crate::prelude::*;
20+
use crate::sync::Arc;
2021
use crate::{
2122
errstr, expression, policy, script_num_size, Error, ForEachKey, Miniscript, MiniscriptKey,
2223
Satisfier, ToPublicKey, TranslateErr, Translator,
@@ -201,7 +202,7 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> policy::Liftable<Pk> for SortedMulti
201202
self.k,
202203
self.pks
203204
.iter()
204-
.map(|k| policy::semantic::Policy::Key(k.clone()))
205+
.map(|k| Arc::new(policy::semantic::Policy::Key(k.clone())))
205206
.collect(),
206207
);
207208
Ok(ret)

src/descriptor/tr.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,10 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for TapTree<Pk> {
614614
fn lift(&self) -> Result<Policy<Pk>, Error> {
615615
fn lift_helper<Pk: MiniscriptKey>(s: &TapTree<Pk>) -> Result<Policy<Pk>, Error> {
616616
match *s {
617-
TapTree::Tree { ref left, ref right, height: _ } => {
618-
Ok(Policy::Threshold(1, vec![lift_helper(left)?, lift_helper(right)?]))
619-
}
617+
TapTree::Tree { ref left, ref right, height: _ } => Ok(Policy::Threshold(
618+
1,
619+
vec![Arc::new(lift_helper(left)?), Arc::new(lift_helper(right)?)],
620+
)),
620621
TapTree::Leaf(ref leaf) => leaf.lift(),
621622
}
622623
}
@@ -629,9 +630,13 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for TapTree<Pk> {
629630
impl<Pk: MiniscriptKey> Liftable<Pk> for Tr<Pk> {
630631
fn lift(&self) -> Result<Policy<Pk>, Error> {
631632
match &self.tree {
632-
Some(root) => {
633-
Ok(Policy::Threshold(1, vec![Policy::Key(self.internal_key.clone()), root.lift()?]))
634-
}
633+
Some(root) => Ok(Policy::Threshold(
634+
1,
635+
vec![
636+
Arc::new(Policy::Key(self.internal_key.clone())),
637+
Arc::new(root.lift()?),
638+
],
639+
)),
635640
None => Ok(Policy::Key(self.internal_key.clone())),
636641
}
637642
}

src/iter/mod.rs

Lines changed: 1 addition & 27 deletions
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::{policy, Miniscript, MiniscriptKey, ScriptContext, Terminal};
18+
use crate::{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,29 +68,3 @@ 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-
match *self {
76-
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
77-
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
78-
And(ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
79-
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| p.as_ref()).collect()),
80-
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
81-
}
82-
}
83-
}
84-
85-
impl<Pk: MiniscriptKey> TreeLike for Arc<policy::Concrete<Pk>> {
86-
fn as_node(&self) -> Tree<Self> {
87-
use policy::Concrete::*;
88-
match self.as_ref() {
89-
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
90-
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
91-
And(ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
92-
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::clone(p)).collect()),
93-
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
94-
}
95-
}
96-
}

src/policy/concrete.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use {
2323

2424
use super::ENTAILMENT_MAX_TERMINALS;
2525
use crate::expression::{self, FromTree};
26-
use crate::iter::TreeLike;
26+
use crate::iter::{Tree, TreeLike};
2727
use crate::miniscript::types::extra_props::TimelockInfo;
2828
use crate::prelude::*;
2929
use crate::sync::Arc;
@@ -1114,6 +1114,34 @@ fn generate_combination<Pk: MiniscriptKey>(
11141114
ret
11151115
}
11161116

1117+
impl<'a, Pk: MiniscriptKey> TreeLike for &'a Policy<Pk> {
1118+
fn as_node(&self) -> Tree<Self> {
1119+
use Policy::*;
1120+
1121+
match *self {
1122+
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
1123+
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
1124+
And(ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
1125+
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| p.as_ref()).collect()),
1126+
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::as_ref).collect()),
1127+
}
1128+
}
1129+
}
1130+
1131+
impl<Pk: MiniscriptKey> TreeLike for Arc<Policy<Pk>> {
1132+
fn as_node(&self) -> Tree<Self> {
1133+
use Policy::*;
1134+
1135+
match self.as_ref() {
1136+
Unsatisfiable | Trivial | Key(_) | After(_) | Older(_) | Sha256(_) | Hash256(_)
1137+
| Ripemd160(_) | Hash160(_) => Tree::Nullary,
1138+
And(ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
1139+
Or(ref v) => Tree::Nary(v.iter().map(|(_, p)| Arc::clone(p)).collect()),
1140+
Threshold(_, ref subs) => Tree::Nary(subs.iter().map(Arc::clone).collect()),
1141+
}
1142+
}
1143+
}
1144+
11171145
#[cfg(all(test, feature = "compiler"))]
11181146
mod compiler_tests {
11191147
use core::str::FromStr;

src/policy/mod.rs

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub use self::semantic::Policy as Semantic;
2323
use crate::descriptor::Descriptor;
2424
use crate::miniscript::{Miniscript, ScriptContext};
2525
use crate::sync::Arc;
26-
use crate::{Error, MiniscriptKey, Terminal};
26+
use crate::{Error, MiniscriptKey, Terminal, Vec};
2727

2828
/// Policy entailment algorithm maximum number of terminals allowed.
2929
const ENTAILMENT_MAX_TERMINALS: usize = 20;
@@ -136,28 +136,40 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Liftable<Pk> for Terminal<Pk, Ctx> {
136136
| Terminal::NonZero(ref sub)
137137
| Terminal::ZeroNotEqual(ref sub) => sub.node.lift()?,
138138
Terminal::AndV(ref left, ref right) | Terminal::AndB(ref left, ref right) => {
139-
Semantic::Threshold(2, vec![left.node.lift()?, right.node.lift()?])
139+
Semantic::Threshold(
140+
2,
141+
vec![Arc::new(left.node.lift()?), Arc::new(right.node.lift()?)],
142+
)
140143
}
141144
Terminal::AndOr(ref a, ref b, ref c) => Semantic::Threshold(
142145
1,
143146
vec![
144-
Semantic::Threshold(2, vec![a.node.lift()?, b.node.lift()?]),
145-
c.node.lift()?,
147+
Arc::new(Semantic::Threshold(
148+
2,
149+
vec![Arc::new(a.node.lift()?), Arc::new(b.node.lift()?)],
150+
)),
151+
Arc::new(c.node.lift()?),
146152
],
147153
),
148154
Terminal::OrB(ref left, ref right)
149155
| Terminal::OrD(ref left, ref right)
150156
| Terminal::OrC(ref left, ref right)
151-
| Terminal::OrI(ref left, ref right) => {
152-
Semantic::Threshold(1, vec![left.node.lift()?, right.node.lift()?])
153-
}
157+
| Terminal::OrI(ref left, ref right) => Semantic::Threshold(
158+
1,
159+
vec![Arc::new(left.node.lift()?), Arc::new(right.node.lift()?)],
160+
),
154161
Terminal::Thresh(k, ref subs) => {
155-
let semantic_subs: Result<_, Error> = subs.iter().map(|s| s.node.lift()).collect();
156-
Semantic::Threshold(k, semantic_subs?)
157-
}
158-
Terminal::Multi(k, ref keys) | Terminal::MultiA(k, ref keys) => {
159-
Semantic::Threshold(k, keys.iter().map(|k| Semantic::Key(k.clone())).collect())
162+
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
163+
subs.iter().map(|s| s.node.lift()).collect();
164+
let semantic_subs = semantic_subs?.into_iter().map(Arc::new).collect();
165+
Semantic::Threshold(k, semantic_subs)
160166
}
167+
Terminal::Multi(k, ref keys) | Terminal::MultiA(k, ref keys) => Semantic::Threshold(
168+
k,
169+
keys.iter()
170+
.map(|k| Arc::new(Semantic::Key(k.clone())))
171+
.collect(),
172+
),
161173
}
162174
.normalized();
163175
Ok(ret)
@@ -197,17 +209,22 @@ impl<Pk: MiniscriptKey> Liftable<Pk> for Concrete<Pk> {
197209
Concrete::Ripemd160(ref h) => Semantic::Ripemd160(h.clone()),
198210
Concrete::Hash160(ref h) => Semantic::Hash160(h.clone()),
199211
Concrete::And(ref subs) => {
200-
let semantic_subs: Result<_, Error> = subs.iter().map(Liftable::lift).collect();
201-
Semantic::Threshold(2, semantic_subs?)
212+
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
213+
subs.iter().map(Liftable::lift).collect();
214+
let semantic_subs = semantic_subs?.into_iter().map(Arc::new).collect();
215+
Semantic::Threshold(2, semantic_subs)
202216
}
203217
Concrete::Or(ref subs) => {
204-
let semantic_subs: Result<_, Error> =
218+
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
205219
subs.iter().map(|(_p, sub)| sub.lift()).collect();
206-
Semantic::Threshold(1, semantic_subs?)
220+
let semantic_subs = semantic_subs?.into_iter().map(Arc::new).collect();
221+
Semantic::Threshold(1, semantic_subs)
207222
}
208223
Concrete::Threshold(k, ref subs) => {
209-
let semantic_subs: Result<_, Error> = subs.iter().map(Liftable::lift).collect();
210-
Semantic::Threshold(k, semantic_subs?)
224+
let semantic_subs: Result<Vec<Semantic<Pk>>, Error> =
225+
subs.iter().map(Liftable::lift).collect();
226+
let semantic_subs = semantic_subs?.into_iter().map(Arc::new).collect();
227+
Semantic::Threshold(k, semantic_subs)
211228
}
212229
}
213230
.normalized();
@@ -223,14 +240,12 @@ mod tests {
223240
use core::str::FromStr;
224241

225242
use bitcoin::Sequence;
226-
#[cfg(feature = "compiler")]
227-
use sync::Arc;
228243

229-
use super::super::miniscript::context::Segwitv0;
230-
use super::super::miniscript::Miniscript;
231-
use super::{Concrete, Liftable, Semantic};
244+
use super::*;
232245
#[cfg(feature = "compiler")]
233246
use crate::descriptor::Tr;
247+
use crate::miniscript::context::Segwitv0;
248+
use crate::miniscript::Miniscript;
234249
use crate::prelude::*;
235250
#[cfg(feature = "compiler")]
236251
use crate::{descriptor::TapTree, Descriptor, Tap};
@@ -348,14 +363,14 @@ mod tests {
348363
Semantic::Threshold(
349364
1,
350365
vec![
351-
Semantic::Threshold(
366+
Arc::new(Semantic::Threshold(
352367
2,
353368
vec![
354-
Semantic::Key(key_a),
355-
Semantic::Older(Sequence::from_height(42))
369+
Arc::new(Semantic::Key(key_a)),
370+
Arc::new(Semantic::Older(Sequence::from_height(42)))
356371
]
357-
),
358-
Semantic::Key(key_b)
372+
)),
373+
Arc::new(Semantic::Key(key_b))
359374
]
360375
),
361376
ms_str.lift().unwrap()

0 commit comments

Comments
 (0)