Skip to content

Commit 469c113

Browse files
committed
Merge rust-bitcoin#612: Remove recursion in semantic module
f9307c8 semantic: Remove recursion in sorted (Tobin C. Harding) 09a47cb semantic: Remove recursion in minimum_n_keys (Tobin C. Harding) eb75602 semantic: Remove recursion in n_keys (Tobin C. Harding) d9f9d43 semantic: Remove recursion in at_age and at_lock_time (Tobin C. Harding) c3c5e72 semantic: Remove recursion in real_*_timelocks (Tobin C. Harding) b1ae1ff semantic: Remove recursion in n_terminals (Tobin C. Harding) 211abad semantic: Remove recursion in translate_pk (Tobin C. Harding) 97ba4e9 semantic: Remove recursion in for_each_key (Tobin C. Harding) df3a85a Implement TreeLike for semantic::Policy (Tobin C. Harding) e813ad0 Add Arc to the semantic::Policy::Thresh vector (Tobin C. Harding) 0ef5e54 Move TreeLike impl to concrete module (Tobin C. Harding) 161753c Fix imports in test module (Tobin C. Harding) 2fd42d6 Improve spacing in error string (Tobin C. Harding) 721e16b Use unwrap_or (Tobin C. Harding) 10e5982 Add line of whitespace (Tobin C. Harding) 61b45a9 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 f9307c8 Tree-SHA512: dd2eac15ecd2a672436ffe7b21277c72406c92d3e3434ac2046e7ebd4cba98e02db4ce5e39ed73f0bfcc2388610e871acd578655461bdb99e8beaa2aac4aefb5
2 parents 47d2cc7 + f9307c8 commit 469c113

File tree

6 files changed

+340
-236
lines changed

6 files changed

+340
-236
lines changed

src/descriptor/sortedmulti.rs

+2-1
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

+11-6
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

+1-27
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

+29-1
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

+43-28
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)