Skip to content

Commit 4f9f3c3

Browse files
Add Taproot compiler private-version
1 parent 96b4e66 commit 4f9f3c3

File tree

2 files changed

+31
-21
lines changed

2 files changed

+31
-21
lines changed

src/policy/concrete.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -195,19 +195,6 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
195195
}
196196
}
197197

198-
/// Compile [`Policy::Or`] and [`Policy::Threshold`] according to odds
199-
#[cfg(feature = "compiler")]
200-
fn compile_tr_policy(&self) -> Result<TapTree<Pk>, Error> {
201-
let leaf_compilations: Vec<_> = self
202-
.to_tapleaf_prob_vec(1.0)
203-
.into_iter()
204-
.filter(|x| x.1 != Policy::Unsatisfiable)
205-
.map(|(prob, ref policy)| (OrdF64(prob), compiler::best_compilation(policy).unwrap()))
206-
.collect();
207-
let taptree = Self::with_huffman_tree(leaf_compilations, |x| x).unwrap();
208-
Ok(taptree)
209-
}
210-
211198
/// Extract the internal_key from policy tree.
212199
#[cfg(feature = "compiler")]
213200
fn extract_key(self, unspendable_key: Option<Pk>) -> Result<(Pk, Policy<Pk>), Error> {
@@ -252,10 +239,15 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
252239
}
253240
}
254241

255-
/// Compile the [`Tr`] descriptor into optimized [`TapTree`] implementation
256-
// TODO: We might require other compile errors for Taproot. Will discuss and update.
242+
/// Compile [`Policy`] into a [`TapTree Descriptor`][`Descriptor::Tr`]
243+
///
244+
/// We recursively expand the policy tree w.r.t root-level [`Policy::Or`]s and
245+
/// [`Policy::Threshold`](1, ...) to obtain (sub)-policies. For example,
246+
/// `thresh(1,and(or(A,B),C),or(or(D, E),and(F, G)),H)` is split into the list
247+
/// [and(or(A,B),C), D,E, and(F, G), H] which are used for generating miniscript compilations
248+
/// required for generating [`TapTree`].
257249
#[cfg(feature = "compiler")]
258-
pub fn compile_tr(&self, unspendable_key: Option<Pk>) -> Result<Descriptor<Pk>, Error> {
250+
pub fn compile_tr_private(&self, unspendable_key: Option<Pk>) -> Result<Descriptor<Pk>, Error> {
259251
self.is_valid()?; // Check for validity
260252
match self.is_safe_nonmalleable() {
261253
(false, _) => Err(Error::from(CompilerError::TopLevelNonSafe)),
@@ -268,7 +260,19 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
268260
internal_key,
269261
match policy {
270262
Policy::Trivial => None,
271-
policy => Some(policy.compile_tr_policy()?),
263+
policy => {
264+
let leaf_compilations: Vec<_> = policy
265+
.to_tapleaf_prob_vec(1.0)
266+
.into_iter()
267+
.filter(|x| x.1 != Policy::Unsatisfiable)
268+
.map(|(prob, ref pol)| {
269+
(OrdF64(prob), compiler::best_compilation(pol).unwrap())
270+
})
271+
.collect();
272+
let taptree =
273+
Self::with_huffman_tree(leaf_compilations, |x| x).unwrap();
274+
Some(taptree)
275+
}
272276
},
273277
)?;
274278
Ok(tree)

src/policy/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,9 @@ mod tests {
382382
let unspendable_key: String = "UNSPENDABLE".to_string();
383383
{
384384
let policy: Concrete<String> = policy_str!("thresh(2,pk(A),pk(B),pk(C),pk(D))");
385-
let descriptor = policy.compile_tr(Some(unspendable_key.clone())).unwrap();
385+
let descriptor = policy
386+
.compile_tr_private(Some(unspendable_key.clone()))
387+
.unwrap();
386388

387389
let ms_compilation: Miniscript<String, Tap> = ms_str!("multi_a(2,A,B,C,D)");
388390
let tree: TapTree<String> = TapTree::Leaf(Arc::new(ms_compilation));
@@ -394,7 +396,9 @@ mod tests {
394396
// Trivial multi-node compilation
395397
{
396398
let policy: Concrete<String> = policy_str!("or(and(pk(A),pk(B)),and(pk(C),pk(D)))");
397-
let descriptor = policy.compile_tr(Some(unspendable_key.clone())).unwrap();
399+
let descriptor = policy
400+
.compile_tr_private(Some(unspendable_key.clone()))
401+
.unwrap();
398402

399403
let left_ms_compilation: Arc<Miniscript<String, Tap>> =
400404
Arc::new(ms_str!("and_v(v:pk(C),pk(D))"));
@@ -411,7 +415,7 @@ mod tests {
411415
{
412416
// Invalid policy compilation (Duplicate PubKeys)
413417
let policy: Concrete<String> = policy_str!("or(and(pk(A),pk(B)),and(pk(A),pk(D)))");
414-
let descriptor = policy.compile_tr(Some(unspendable_key.clone()));
418+
let descriptor = policy.compile_tr_private(Some(unspendable_key.clone()));
415419

416420
assert_eq!(
417421
descriptor.unwrap_err().to_string(),
@@ -448,7 +452,9 @@ mod tests {
448452
node_policies[6]
449453
)
450454
);
451-
let descriptor = policy.compile_tr(Some(unspendable_key.clone())).unwrap();
455+
let descriptor = policy
456+
.compile_tr_private(Some(unspendable_key.clone()))
457+
.unwrap();
452458

453459
let mut sorted_policy_prob = node_policies
454460
.into_iter()

0 commit comments

Comments
 (0)