Skip to content

Commit 9b00e2c

Browse files
committed
Add feature simplicity
rust-simplicity is still evolving and it might need fixes or interface changes. Make it optional.
1 parent 259f7c4 commit 9b00e2c

File tree

4 files changed

+45
-15
lines changed

4 files changed

+45
-15
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ trace = []
1717
serde = ["actual-serde", "bitcoin/serde", "elements/serde"]
1818
rand = ["bitcoin/rand"]
1919
base64 = ["bitcoin/base64"]
20+
simplicity = ["dep:simplicity"]
2021

2122
[dependencies]
2223
bitcoin = "0.30.0"
2324
elements = "0.23.0"
2425
bitcoin-miniscript = { package = "miniscript", version = "10.0" }
25-
simplicity = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "d5c0d65320816bfdf36411feed4bdff0708b5b12" }
26+
simplicity = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "d5c0d65320816bfdf36411feed4bdff0708b5b12", optional = true }
2627

2728
# Do NOT use this as a feature! Use the `serde` feature instead.
2829
actual-serde = { package = "serde", version = "1.0", optional = true }

contrib/test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
set -ex
44

5-
FEATURES="compiler serde rand base64"
5+
FEATURES="compiler serde rand base64 simplicity"
66

77
cargo --version
88
rustc --version

src/descriptor/tr.rs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub enum TapTree<Pk: MiniscriptKey, Ext: Extension = NoExt> {
3737
// are of Leafversion::default
3838
Leaf(Arc<Miniscript<Pk, Tap, Ext>>),
3939
/// A taproot leaf denoting a spending condition in terms of Simplicity
40+
#[cfg(feature = "simplicity")]
4041
SimplicityLeaf(Arc<simplicity::Policy<Pk>>),
4142
}
4243

@@ -119,7 +120,9 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
119120
TapTree::Tree(ref left_tree, ref right_tree) => {
120121
1 + max(left_tree.taptree_height(), right_tree.taptree_height())
121122
}
122-
TapTree::Leaf(..) | TapTree::SimplicityLeaf(..) => 0,
123+
TapTree::Leaf(..) => 0,
124+
#[cfg(feature = "simplicity")]
125+
TapTree::SimplicityLeaf(..) => 0,
123126
}
124127
}
125128

@@ -138,8 +141,10 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
138141
Q: MiniscriptKey,
139142
Ext: Extension,
140143
{
144+
#[cfg(feature = "simplicity")]
141145
struct SimTranslator<'a, T>(&'a mut T);
142146

147+
#[cfg(feature = "simplicity")]
143148
impl<'a, Pk, T, Q, Error> simplicity::Translator<Pk, Q, Error> for SimTranslator<'a, T>
144149
where
145150
Pk: MiniscriptKey,
@@ -161,6 +166,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
161166
Arc::new(r.translate_helper(t)?),
162167
),
163168
TapTree::Leaf(ms) => TapTree::Leaf(Arc::new(ms.translate_pk(t)?)),
169+
#[cfg(feature = "simplicity")]
164170
TapTree::SimplicityLeaf(sim) => TapTree::SimplicityLeaf(Arc::new(sim.translate(&mut SimTranslator(t))?))
165171
};
166172
Ok(frag)
@@ -179,6 +185,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
179185
Arc::new(r.translate_ext_helper(t)?),
180186
),
181187
TapTree::Leaf(ms) => TapTree::Leaf(Arc::new(ms.translate_ext(t)?)),
188+
#[cfg(feature = "simplicity")]
182189
TapTree::SimplicityLeaf(sim) => TapTree::SimplicityLeaf(Arc::clone(sim)),
183190
};
184191
Ok(frag)
@@ -190,6 +197,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> fmt::Display for TapTree<Pk, Ext> {
190197
match self {
191198
TapTree::Tree(ref left, ref right) => write!(f, "{{{},{}}}", *left, *right),
192199
TapTree::Leaf(ref script) => write!(f, "{}", *script),
200+
#[cfg(feature = "simplicity")]
193201
TapTree::SimplicityLeaf(ref policy) => write!(f, "sim{{{}}}", policy),
194202
}
195203
}
@@ -200,6 +208,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> fmt::Debug for TapTree<Pk, Ext> {
200208
match self {
201209
TapTree::Tree(ref left, ref right) => write!(f, "{{{:?},{:?}}}", *left, *right),
202210
TapTree::Leaf(ref script) => write!(f, "{:?}", *script),
211+
#[cfg(feature = "simplicity")]
203212
TapTree::SimplicityLeaf(ref policy) => write!(f, "{:?}", policy),
204213
}
205214
}
@@ -288,6 +297,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> Tr<Pk, Ext> {
288297
match script {
289298
TapLeafScript::Miniscript(ms) => ms.sanity_check()?,
290299
// TODO: Add sanity check for Simplicity policies
300+
#[cfg(feature = "simplicity")]
291301
TapLeafScript::Simplicity(..) => {},
292302
}
293303
}
@@ -436,6 +446,7 @@ pub enum TapLeafScript<'a, Pk: MiniscriptKey, Ext: Extension> {
436446
/// Miniscript leaf
437447
Miniscript(&'a Miniscript<Pk, Tap, Ext>),
438448
/// Simplicity leaf
449+
#[cfg(feature = "simplicity")]
439450
Simplicity(&'a simplicity::Policy<Pk>)
440451
}
441452

@@ -444,11 +455,13 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
444455
pub fn as_miniscript(&self) -> Option<&'a Miniscript<Pk, Tap, Ext>> {
445456
match self {
446457
TapLeafScript::Miniscript(ms) => Some(ms),
458+
#[cfg(feature = "simplicity")]
447459
_ => None,
448460
}
449461
}
450462

451463
/// Get the Simplicity policy at the leaf, if it exists.
464+
#[cfg(feature = "simplicity")]
452465
pub fn as_simplicity(&self) -> Option<&'a simplicity::Policy<Pk>> {
453466
match self {
454467
TapLeafScript::Simplicity(sim) => Some(sim),
@@ -460,6 +473,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
460473
pub fn version(&self) -> LeafVersion {
461474
match self {
462475
TapLeafScript::Miniscript(..) => LeafVersion::default(),
476+
#[cfg(feature = "simplicity")]
463477
TapLeafScript::Simplicity(..) => simplicity::leaf_version(),
464478
}
465479
}
@@ -469,6 +483,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
469483
match self {
470484
TapLeafScript::Miniscript(ms) => ms.script_size(),
471485
// Simplicity's witness script is always a 32-byte CMR
486+
#[cfg(feature = "simplicity")]
472487
TapLeafScript::Simplicity(..) => 32,
473488
}
474489
}
@@ -482,6 +497,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
482497
// (1) Encoded program+witness
483498
// (2) CMR program
484499
// The third element is the control block, which is not counted by this method.
500+
#[cfg(feature = "simplicity")]
485501
TapLeafScript::Simplicity(..) => Ok(2),
486502
}
487503
}
@@ -493,6 +509,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
493509
// There is currently no way to bound the Simplicity witness size without producing one
494510
// We mark the witness size as malleable since it depends on the chosen spending path
495511
// TODO: Add method to simplicity::Policy and use it here
512+
#[cfg(feature = "simplicity")]
496513
TapLeafScript::Simplicity(..) => Err(Error::AnalysisError(crate::AnalysisError::Malleable))
497514
}
498515
}
@@ -501,6 +518,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
501518
pub fn iter_pk(&self) -> Box<dyn Iterator<Item=Pk> + 'a> {
502519
match self {
503520
TapLeafScript::Miniscript(ms) => Box::new(ms.iter_pk()),
521+
#[cfg(feature = "simplicity")]
504522
TapLeafScript::Simplicity(sim) => Box::new(sim.iter_pk()),
505523
}
506524
}
@@ -511,6 +529,7 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
511529
pub fn encode(&self) -> Script {
512530
match self {
513531
TapLeafScript::Miniscript(ms) => ms.encode(),
532+
#[cfg(feature = "simplicity")]
514533
TapLeafScript::Simplicity(sim) => {
515534
Script::from(sim.cmr().as_ref().to_vec())
516535
}
@@ -522,6 +541,7 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
522541
match self {
523542
TapLeafScript::Miniscript(ms) => ms.satisfy_malleable(satisfier),
524543
// There doesn't (yet?) exist a malleable satisfaction of Simplicity policy
544+
#[cfg(feature = "simplicity")]
525545
TapLeafScript::Simplicity(..) => self.satisfy(satisfier),
526546
}
527547
}
@@ -530,6 +550,7 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
530550
pub fn satisfy<S: Satisfier<Pk>>(&self, satisfier: S) -> Result<Vec<Vec<u8>>, Error> {
531551
match self {
532552
TapLeafScript::Miniscript(ms) => ms.satisfy(satisfier),
553+
#[cfg(feature = "simplicity")]
533554
TapLeafScript::Simplicity(sim) => {
534555
let satisfier = crate::simplicity::SatisfierWrapper::new(satisfier);
535556
let program = sim.satisfy(&satisfier).map_err(|_| Error::CouldNotSatisfy)?;
@@ -577,6 +598,7 @@ where
577598
TapTree::Leaf(ref ms) => {
578599
return Some((depth, TapLeafScript::Miniscript(ms)))
579600
},
601+
#[cfg(feature = "simplicity")]
580602
TapTree::SimplicityLeaf(ref sim) => {
581603
return Some((depth, TapLeafScript::Simplicity(sim)))
582604
}
@@ -593,6 +615,7 @@ impl_block_str!(
593615
// Helper function to parse taproot script path
594616
fn parse_tr_script_spend(tree: &expression::Tree,) -> Result<TapTree<Pk, Ext>, Error> {
595617
match tree {
618+
#[cfg(feature = "simplicity")]
596619
expression::Tree { name, args } if *name == "sim" && args.len() == 1 => {
597620
let policy = crate::simplicity::PolicyWrapper::<Pk>::from_str(args[0].name)?;
598621
Ok(TapTree::SimplicityLeaf(Arc::new(policy.0)))
@@ -771,6 +794,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> Liftable<Pk> for TapTree<Pk, Ext> {
771794
Ok(Policy::Threshold(1, vec![lift_helper(l)?, lift_helper(r)?]))
772795
}
773796
TapTree::Leaf(ref leaf) => leaf.lift(),
797+
#[cfg(feature = "simplicity")]
774798
TapTree::SimplicityLeaf(..) => panic!("FIXME: Cannot lift Simplicity policy to Miniscript semantic policy"),
775799
}
776800
}
@@ -802,6 +826,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> ForEachKey<Pk> for Tr<Pk, Ext> {
802826
.all(|(_d, script)| {
803827
match script {
804828
TapLeafScript::Miniscript(ms) => ms.for_each_key(&mut pred),
829+
#[cfg(feature = "simplicity")]
805830
TapLeafScript::Simplicity(sim) => crate::simplicity::for_each_key(sim, &mut pred),
806831
}
807832
});
@@ -976,17 +1001,20 @@ mod tests {
9761001
&[TapLeafScript::Miniscript(&ms)]
9771002
);
9781003

979-
// Simplicity key spend
980-
let sim = simplicity::Policy::Key("a".to_string());
981-
verify_from_str(
982-
"eltr(internal,sim{pk(a)})#duhmnzmm", "internal",
983-
&[TapLeafScript::Simplicity(&sim)]
984-
);
985-
986-
// Mixed Miniscript and Simplicity
987-
verify_from_str(
988-
"eltr(internal,{pk(a),sim{pk(a)}})#7vmfhpaj", "internal",
989-
&[TapLeafScript::Miniscript(&ms), TapLeafScript::Simplicity(&sim)]
990-
);
1004+
#[cfg(feature = "simplicity")]
1005+
{
1006+
// Simplicity key spend
1007+
let sim = simplicity::Policy::Key("a".to_string());
1008+
verify_from_str(
1009+
"eltr(internal,sim{pk(a)})#duhmnzmm", "internal",
1010+
&[TapLeafScript::Simplicity(&sim)]
1011+
);
1012+
1013+
// Mixed Miniscript and Simplicity
1014+
verify_from_str(
1015+
"eltr(internal,{pk(a),sim{pk(a)}})#7vmfhpaj", "internal",
1016+
&[TapLeafScript::Miniscript(&ms), TapLeafScript::Simplicity(&sim)]
1017+
);
1018+
}
9911019
}
9921020
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub mod psbt;
139139
#[cfg(test)]
140140
mod test_utils;
141141
mod util;
142+
#[cfg(feature = "simplicity")]
142143
mod simplicity;
143144

144145
use std::{cmp, error, fmt, str};

0 commit comments

Comments
 (0)