Skip to content

Commit b80cb46

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 b80cb46

File tree

4 files changed

+46
-15
lines changed

4 files changed

+46
-15
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ base64 = ["bitcoin/base64"]
2222
bitcoin = "0.30.0"
2323
elements = "0.23.0"
2424
bitcoin-miniscript = { package = "miniscript", version = "10.0" }
25-
simplicity = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "d5c0d65320816bfdf36411feed4bdff0708b5b12" }
25+
simplicity = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "d5c0d65320816bfdf36411feed4bdff0708b5b12", optional = true }
2626

2727
# Do NOT use this as a feature! Use the `serde` feature instead.
2828
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: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::{
2828
// Hidden leaves are not yet supported in descriptor spec. Conceptually, it should
2929
// be simple to integrate those here, but it is best to wait on core for the exact syntax.
3030
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
31+
#[non_exhaustive]
3132
pub enum TapTree<Pk: MiniscriptKey, Ext: Extension = NoExt> {
3233
/// A taproot tree structure
3334
Tree(Arc<TapTree<Pk, Ext>>, Arc<TapTree<Pk, Ext>>),
@@ -37,6 +38,7 @@ pub enum TapTree<Pk: MiniscriptKey, Ext: Extension = NoExt> {
3738
// are of Leafversion::default
3839
Leaf(Arc<Miniscript<Pk, Tap, Ext>>),
3940
/// A taproot leaf denoting a spending condition in terms of Simplicity
41+
#[cfg(feature = "simplicity")]
4042
SimplicityLeaf(Arc<simplicity::Policy<Pk>>),
4143
}
4244

@@ -119,7 +121,9 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
119121
TapTree::Tree(ref left_tree, ref right_tree) => {
120122
1 + max(left_tree.taptree_height(), right_tree.taptree_height())
121123
}
122-
TapTree::Leaf(..) | TapTree::SimplicityLeaf(..) => 0,
124+
TapTree::Leaf(..) => 0,
125+
#[cfg(feature = "simplicity")]
126+
TapTree::SimplicityLeaf(..) => 0,
123127
}
124128
}
125129

@@ -138,8 +142,10 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
138142
Q: MiniscriptKey,
139143
Ext: Extension,
140144
{
145+
#[cfg(feature = "simplicity")]
141146
struct SimTranslator<'a, T>(&'a mut T);
142147

148+
#[cfg(feature = "simplicity")]
143149
impl<'a, Pk, T, Q, Error> simplicity::Translator<Pk, Q, Error> for SimTranslator<'a, T>
144150
where
145151
Pk: MiniscriptKey,
@@ -161,6 +167,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
161167
Arc::new(r.translate_helper(t)?),
162168
),
163169
TapTree::Leaf(ms) => TapTree::Leaf(Arc::new(ms.translate_pk(t)?)),
170+
#[cfg(feature = "simplicity")]
164171
TapTree::SimplicityLeaf(sim) => TapTree::SimplicityLeaf(Arc::new(sim.translate(&mut SimTranslator(t))?))
165172
};
166173
Ok(frag)
@@ -179,6 +186,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
179186
Arc::new(r.translate_ext_helper(t)?),
180187
),
181188
TapTree::Leaf(ms) => TapTree::Leaf(Arc::new(ms.translate_ext(t)?)),
189+
#[cfg(feature = "simplicity")]
182190
TapTree::SimplicityLeaf(sim) => TapTree::SimplicityLeaf(Arc::clone(sim)),
183191
};
184192
Ok(frag)
@@ -190,6 +198,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> fmt::Display for TapTree<Pk, Ext> {
190198
match self {
191199
TapTree::Tree(ref left, ref right) => write!(f, "{{{},{}}}", *left, *right),
192200
TapTree::Leaf(ref script) => write!(f, "{}", *script),
201+
#[cfg(feature = "simplicity")]
193202
TapTree::SimplicityLeaf(ref policy) => write!(f, "sim{{{}}}", policy),
194203
}
195204
}
@@ -200,6 +209,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> fmt::Debug for TapTree<Pk, Ext> {
200209
match self {
201210
TapTree::Tree(ref left, ref right) => write!(f, "{{{:?},{:?}}}", *left, *right),
202211
TapTree::Leaf(ref script) => write!(f, "{:?}", *script),
212+
#[cfg(feature = "simplicity")]
203213
TapTree::SimplicityLeaf(ref policy) => write!(f, "{:?}", policy),
204214
}
205215
}
@@ -288,6 +298,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> Tr<Pk, Ext> {
288298
match script {
289299
TapLeafScript::Miniscript(ms) => ms.sanity_check()?,
290300
// TODO: Add sanity check for Simplicity policies
301+
#[cfg(feature = "simplicity")]
291302
TapLeafScript::Simplicity(..) => {},
292303
}
293304
}
@@ -432,10 +443,12 @@ impl<Pk: MiniscriptKey + ToPublicKey, Ext: ParseableExt> Tr<Pk, Ext> {
432443

433444
/// Script at a tap leaf.
434445
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
446+
#[non_exhaustive]
435447
pub enum TapLeafScript<'a, Pk: MiniscriptKey, Ext: Extension> {
436448
/// Miniscript leaf
437449
Miniscript(&'a Miniscript<Pk, Tap, Ext>),
438450
/// Simplicity leaf
451+
#[cfg(feature = "simplicity")]
439452
Simplicity(&'a simplicity::Policy<Pk>)
440453
}
441454

@@ -444,11 +457,13 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
444457
pub fn as_miniscript(&self) -> Option<&'a Miniscript<Pk, Tap, Ext>> {
445458
match self {
446459
TapLeafScript::Miniscript(ms) => Some(ms),
460+
#[cfg(feature = "simplicity")]
447461
_ => None,
448462
}
449463
}
450464

451465
/// Get the Simplicity policy at the leaf, if it exists.
466+
#[cfg(feature = "simplicity")]
452467
pub fn as_simplicity(&self) -> Option<&'a simplicity::Policy<Pk>> {
453468
match self {
454469
TapLeafScript::Simplicity(sim) => Some(sim),
@@ -460,6 +475,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
460475
pub fn version(&self) -> LeafVersion {
461476
match self {
462477
TapLeafScript::Miniscript(..) => LeafVersion::default(),
478+
#[cfg(feature = "simplicity")]
463479
TapLeafScript::Simplicity(..) => simplicity::leaf_version(),
464480
}
465481
}
@@ -469,6 +485,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
469485
match self {
470486
TapLeafScript::Miniscript(ms) => ms.script_size(),
471487
// Simplicity's witness script is always a 32-byte CMR
488+
#[cfg(feature = "simplicity")]
472489
TapLeafScript::Simplicity(..) => 32,
473490
}
474491
}
@@ -482,6 +499,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
482499
// (1) Encoded program+witness
483500
// (2) CMR program
484501
// The third element is the control block, which is not counted by this method.
502+
#[cfg(feature = "simplicity")]
485503
TapLeafScript::Simplicity(..) => Ok(2),
486504
}
487505
}
@@ -493,6 +511,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
493511
// There is currently no way to bound the Simplicity witness size without producing one
494512
// We mark the witness size as malleable since it depends on the chosen spending path
495513
// TODO: Add method to simplicity::Policy and use it here
514+
#[cfg(feature = "simplicity")]
496515
TapLeafScript::Simplicity(..) => Err(Error::AnalysisError(crate::AnalysisError::Malleable))
497516
}
498517
}
@@ -501,6 +520,7 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
501520
pub fn iter_pk(&self) -> Box<dyn Iterator<Item=Pk> + 'a> {
502521
match self {
503522
TapLeafScript::Miniscript(ms) => Box::new(ms.iter_pk()),
523+
#[cfg(feature = "simplicity")]
504524
TapLeafScript::Simplicity(sim) => Box::new(sim.iter_pk()),
505525
}
506526
}
@@ -511,6 +531,7 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
511531
pub fn encode(&self) -> Script {
512532
match self {
513533
TapLeafScript::Miniscript(ms) => ms.encode(),
534+
#[cfg(feature = "simplicity")]
514535
TapLeafScript::Simplicity(sim) => {
515536
Script::from(sim.cmr().as_ref().to_vec())
516537
}
@@ -522,6 +543,7 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
522543
match self {
523544
TapLeafScript::Miniscript(ms) => ms.satisfy_malleable(satisfier),
524545
// There doesn't (yet?) exist a malleable satisfaction of Simplicity policy
546+
#[cfg(feature = "simplicity")]
525547
TapLeafScript::Simplicity(..) => self.satisfy(satisfier),
526548
}
527549
}
@@ -530,6 +552,7 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
530552
pub fn satisfy<S: Satisfier<Pk>>(&self, satisfier: S) -> Result<Vec<Vec<u8>>, Error> {
531553
match self {
532554
TapLeafScript::Miniscript(ms) => ms.satisfy(satisfier),
555+
#[cfg(feature = "simplicity")]
533556
TapLeafScript::Simplicity(sim) => {
534557
let satisfier = crate::simplicity::SatisfierWrapper::new(satisfier);
535558
let program = sim.satisfy(&satisfier).map_err(|_| Error::CouldNotSatisfy)?;
@@ -577,6 +600,7 @@ where
577600
TapTree::Leaf(ref ms) => {
578601
return Some((depth, TapLeafScript::Miniscript(ms)))
579602
},
603+
#[cfg(feature = "simplicity")]
580604
TapTree::SimplicityLeaf(ref sim) => {
581605
return Some((depth, TapLeafScript::Simplicity(sim)))
582606
}
@@ -593,6 +617,7 @@ impl_block_str!(
593617
// Helper function to parse taproot script path
594618
fn parse_tr_script_spend(tree: &expression::Tree,) -> Result<TapTree<Pk, Ext>, Error> {
595619
match tree {
620+
#[cfg(feature = "simplicity")]
596621
expression::Tree { name, args } if *name == "sim" && args.len() == 1 => {
597622
let policy = crate::simplicity::PolicyWrapper::<Pk>::from_str(args[0].name)?;
598623
Ok(TapTree::SimplicityLeaf(Arc::new(policy.0)))
@@ -771,6 +796,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> Liftable<Pk> for TapTree<Pk, Ext> {
771796
Ok(Policy::Threshold(1, vec![lift_helper(l)?, lift_helper(r)?]))
772797
}
773798
TapTree::Leaf(ref leaf) => leaf.lift(),
799+
#[cfg(feature = "simplicity")]
774800
TapTree::SimplicityLeaf(..) => panic!("FIXME: Cannot lift Simplicity policy to Miniscript semantic policy"),
775801
}
776802
}
@@ -802,6 +828,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> ForEachKey<Pk> for Tr<Pk, Ext> {
802828
.all(|(_d, script)| {
803829
match script {
804830
TapLeafScript::Miniscript(ms) => ms.for_each_key(&mut pred),
831+
#[cfg(feature = "simplicity")]
805832
TapLeafScript::Simplicity(sim) => crate::simplicity::for_each_key(sim, &mut pred),
806833
}
807834
});
@@ -976,17 +1003,20 @@ mod tests {
9761003
&[TapLeafScript::Miniscript(&ms)]
9771004
);
9781005

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-
);
1006+
#[cfg(feature = "simplicity")]
1007+
{
1008+
// Simplicity key spend
1009+
let sim = simplicity::Policy::Key("a".to_string());
1010+
verify_from_str(
1011+
"eltr(internal,sim{pk(a)})#duhmnzmm", "internal",
1012+
&[TapLeafScript::Simplicity(&sim)]
1013+
);
1014+
1015+
// Mixed Miniscript and Simplicity
1016+
verify_from_str(
1017+
"eltr(internal,{pk(a),sim{pk(a)}})#7vmfhpaj", "internal",
1018+
&[TapLeafScript::Miniscript(&ms), TapLeafScript::Simplicity(&sim)]
1019+
);
1020+
}
9911021
}
9921022
}

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)