Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# 0.5.0 - Aug 26, 2025

- bump rust elements dep to 0.26.0
- get CI up to date; pin nightly rust version; fix some clippy lints [#98](https://github.com/ElementsProject/elements-miniscript/pull/98)
- Pegin desc wildcard [#96](https://github.com/ElementsProject/elements-miniscript/pull/96)
- Remove inner checksum in pegin descriptor [#95](https://github.com/ElementsProject/elements-miniscript/pull/95)
- simplicity: swap program and witness data in satisfaction [#94](https://github.com/ElementsProject/elements-miniscript/pull/94)

# 0.4.0 - Oct 8, 2024

- Use rust-bitcoin 0.32.0 and rust-elements 0.25.0 [#90](https://github.com/ElementsProject/elements-miniscript/pull/90)
Expand Down
18 changes: 15 additions & 3 deletions Cargo-latest.lock
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ name = "elements"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81b2569d3495bfdfce36c504fd4d78752ff4a7699f8a33e6f3ee523bddf9f6ad"
dependencies = [
"bech32 0.11.0",
"bitcoin 0.32.7",
"secp256k1-zkp",
"serde_json",
]

[[package]]
name = "elements"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26f0d9d44c103b7df345677d60264db216f3031a79423f7b3d4891f9d83eac75"
dependencies = [
"bech32 0.11.0",
"bitcoin 0.32.7",
Expand All @@ -269,11 +281,11 @@ dependencies = [

[[package]]
name = "elements-miniscript"
version = "0.4.0"
version = "0.5.0"
dependencies = [
"base64 0.13.1",
"bitcoin 0.32.7",
"elements",
"elements 0.26.0",
"getrandom",
"miniscript",
"rand",
Expand Down Expand Up @@ -696,7 +708,7 @@ dependencies = [
"bitcoin 0.32.7",
"bitcoin_hashes 0.14.0",
"byteorder",
"elements",
"elements 0.25.2",
"getrandom",
"hex-conservative 0.1.2",
"miniscript",
Expand Down
9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "elements-miniscript"
version = "0.4.0"
version = "0.5.0"
authors = ["Andrew Poelstra <[email protected]>, Sanket Kanjalkar <[email protected]>"]
repository = "https://github.com/ElementsProject/elements-miniscript"
description = "Elements Miniscript: Miniscript, but for elements"
Expand All @@ -21,9 +21,9 @@ base64 = ["bitcoin/base64", "elements/base64"]

[dependencies]
bitcoin = "0.32.0"
elements = "0.25.0"
elements = "0.25.3"
bitcoin-miniscript = { package = "miniscript", version = "12.0" }
simplicity = { package = "simplicity-lang", version = "0.3.0", optional = true }
simplicity = { package = "simplicity-lang", version = "0.5.0", optional = true }

# Do NOT use this as a feature! Use the `serde` feature instead.
actual-serde = { package = "serde", version = "1.0", optional = true }
Expand Down Expand Up @@ -112,3 +112,6 @@ unnecessary_wraps = "warn"
unsafe_derive_deserialize = "warn"
unused_async = "warn"
unused_self = "warn"

[patch.crates-io]
elements = { git = "https://github.com/ElementsProject/rust-elements", rev = "3dc8cd2872524d50e067bee512342c620578cd07" }
97 changes: 67 additions & 30 deletions src/descriptor/tr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ impl<Pk: MiniscriptKey, Ext: Extension> TapTree<Pk, Ext> {
),
TapTree::Leaf(ms) => TapTree::Leaf(Arc::new(ms.translate_pk(t)?)),
#[cfg(feature = "simplicity")]
TapTree::SimplicityLeaf(sim) => TapTree::SimplicityLeaf(Arc::new(sim.translate(&mut SimTranslator(t))?))
TapTree::SimplicityLeaf(sim) => {
TapTree::SimplicityLeaf(Arc::new(sim.translate(&mut SimTranslator(t))?))
}
};
Ok(frag)
}
Expand Down Expand Up @@ -296,7 +298,7 @@ impl<Pk: MiniscriptKey, Ext: Extension> Tr<Pk, Ext> {
TapLeafScript::Miniscript(ms) => ms.sanity_check()?,
// TODO: Add sanity check for Simplicity policies
#[cfg(feature = "simplicity")]
TapLeafScript::Simplicity(..) => {},
TapLeafScript::Simplicity(..) => {}
}
}
Ok(())
Expand Down Expand Up @@ -446,7 +448,7 @@ pub enum TapLeafScript<'a, Pk: MiniscriptKey, Ext: Extension> {
Miniscript(&'a Miniscript<Pk, Tap, Ext>),
/// Simplicity leaf
#[cfg(feature = "simplicity")]
Simplicity(&'a simplicity::Policy<Pk>)
Simplicity(&'a simplicity::Policy<Pk>),
}

impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
Expand Down Expand Up @@ -509,12 +511,14 @@ impl<'a, Pk: MiniscriptKey, Ext: Extension> TapLeafScript<'a, Pk, Ext> {
// We mark the witness size as malleable since it depends on the chosen spending path
// TODO: Add method to simplicity::Policy and use it here
#[cfg(feature = "simplicity")]
TapLeafScript::Simplicity(..) => Err(Error::AnalysisError(crate::AnalysisError::Malleable))
TapLeafScript::Simplicity(..) => {
Err(Error::AnalysisError(crate::AnalysisError::Malleable))
}
}
}

/// Return an iterator over the plain public keys (and not key hash values) of the leaf script.
pub fn iter_pk(&self) -> Box<dyn Iterator<Item=Pk> + 'a> {
pub fn iter_pk(&self) -> Box<dyn Iterator<Item = Pk> + 'a> {
match self {
TapLeafScript::Miniscript(ms) => Box::new(ms.iter_pk()),
#[cfg(feature = "simplicity")]
Expand All @@ -529,9 +533,7 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
match self {
TapLeafScript::Miniscript(ms) => ms.encode(),
#[cfg(feature = "simplicity")]
TapLeafScript::Simplicity(sim) => {
Script::from(sim.cmr().as_ref().to_vec())
}
TapLeafScript::Simplicity(sim) => Script::from(sim.cmr().as_ref().to_vec()),
}
}

Expand All @@ -551,15 +553,44 @@ impl<'a, Pk: ToPublicKey, Ext: ParseableExt> TapLeafScript<'a, Pk, Ext> {
TapLeafScript::Miniscript(ms) => ms.satisfy(satisfier),
#[cfg(feature = "simplicity")]
TapLeafScript::Simplicity(sim) => {
let env = dummy_env();
let satisfier = crate::simplicity::SatisfierWrapper::new(satisfier);
let program = sim.satisfy(&satisfier).map_err(|_| Error::CouldNotSatisfy)?;
let (program_bytes, witness_bytes) = program.encode_to_vec();
let program = sim
.satisfy(&satisfier, &env)
.map_err(|_| Error::CouldNotSatisfy)?;
let (program_bytes, witness_bytes) = program.to_vec_with_witness();
Ok(vec![witness_bytes, program_bytes])
}
}
}
}

#[cfg(feature = "simplicity")]
fn dummy_env() -> simplicity::jet::elements::ElementsEnv<std::sync::Arc<elements::Transaction>> {
use elements::hashes::Hash;

let ctrl_blk: [u8; 33] = [
0xc0, 0xeb, 0x04, 0xb6, 0x8e, 0x9a, 0x26, 0xd1, 0x16, 0x04, 0x6c, 0x76, 0xe8, 0xff, 0x47,
0x33, 0x2f, 0xb7, 0x1d, 0xda, 0x90, 0xff, 0x4b, 0xef, 0x53, 0x70, 0xf2, 0x52, 0x26, 0xd3,
0xbc, 0x09, 0xfc,
];
let env = simplicity::jet::elements::ElementsEnv::new(
Arc::new(simplicity::elements::Transaction {
version: 0,
lock_time: simplicity::elements::LockTime::ZERO,
input: vec![],
output: vec![],
}),
vec![],
0,
simplicity::Cmr::unit(),
simplicity::elements::taproot::ControlBlock::from_slice(&ctrl_blk).unwrap(),
None,
simplicity::elements::BlockHash::all_zeros(),
);
env
}

/// Iterator over the leaves of a tap tree.
///
/// Each leaf consists is a pair of (depth, script).
Expand Down Expand Up @@ -594,9 +625,7 @@ where
self.stack.push((depth + 1, r));
self.stack.push((depth + 1, l));
}
TapTree::Leaf(ref ms) => {
return Some((depth, TapLeafScript::Miniscript(ms)))
},
TapTree::Leaf(ref ms) => return Some((depth, TapLeafScript::Miniscript(ms))),
#[cfg(feature = "simplicity")]
TapTree::SimplicityLeaf(ref sim) => {
return Some((depth, TapLeafScript::Simplicity(sim)))
Expand Down Expand Up @@ -790,7 +819,9 @@ impl<Pk: MiniscriptKey, Ext: Extension> Liftable<Pk> for TapTree<Pk, Ext> {
}
TapTree::Leaf(ref leaf) => leaf.lift(),
#[cfg(feature = "simplicity")]
TapTree::SimplicityLeaf(..) => panic!("FIXME: Cannot lift Simplicity policy to Miniscript semantic policy"),
TapTree::SimplicityLeaf(..) => {
panic!("FIXME: Cannot lift Simplicity policy to Miniscript semantic policy")
}
}
}

Expand All @@ -816,15 +847,11 @@ impl<Pk: MiniscriptKey, Ext: Extension> ForEachKey<Pk> for Tr<Pk, Ext> {
where
Pk: 'a,
{
let script_keys_res = self
.iter_scripts()
.all(|(_d, script)| {
match script {
TapLeafScript::Miniscript(ms) => ms.for_each_key(&mut pred),
#[cfg(feature = "simplicity")]
TapLeafScript::Simplicity(sim) => crate::simplicity::for_each_key(sim, &mut pred),
}
});
let script_keys_res = self.iter_scripts().all(|(_d, script)| match script {
TapLeafScript::Miniscript(ms) => ms.for_each_key(&mut pred),
#[cfg(feature = "simplicity")]
TapLeafScript::Simplicity(sim) => crate::simplicity::for_each_key(sim, &mut pred),
});
script_keys_res && pred(&self.internal_key)
}
}
Expand Down Expand Up @@ -970,7 +997,11 @@ mod tests {
assert!(!tr.for_each_key(|k| k.starts_with("acc")));
}

fn verify_from_str(desc_str: &str, internal_key: &str, scripts: &[TapLeafScript<String, NoExt>]) {
fn verify_from_str(
desc_str: &str,
internal_key: &str,
scripts: &[TapLeafScript<String, NoExt>],
) {
let desc = Tr::<String, NoExt>::from_str(desc_str).unwrap();
assert_eq!(desc_str, &desc.to_string());
assert_eq!(internal_key, &desc.internal_key);
Expand All @@ -992,23 +1023,29 @@ mod tests {
// Miniscript key spend
let ms = Miniscript::<String, Tap>::from_str("pk(a)").unwrap();
verify_from_str(
"eltr(internal,pk(a))#vadmk9gd", "internal",
&[TapLeafScript::Miniscript(&ms)]
"eltr(internal,pk(a))#vadmk9gd",
"internal",
&[TapLeafScript::Miniscript(&ms)],
);

#[cfg(feature = "simplicity")]
{
// Simplicity key spend
let sim = simplicity::Policy::Key("a".to_string());
verify_from_str(
"eltr(internal,sim{pk(a)})#duhmnzmm", "internal",
&[TapLeafScript::Simplicity(&sim)]
"eltr(internal,sim{pk(a)})#duhmnzmm",
"internal",
&[TapLeafScript::Simplicity(&sim)],
);

// Mixed Miniscript and Simplicity
verify_from_str(
"eltr(internal,{pk(a),sim{pk(a)}})#7vmfhpaj", "internal",
&[TapLeafScript::Miniscript(&ms), TapLeafScript::Simplicity(&sim)]
"eltr(internal,{pk(a),sim{pk(a)}})#7vmfhpaj",
"internal",
&[
TapLeafScript::Miniscript(&ms),
TapLeafScript::Simplicity(&sim),
],
);
}
}
Expand Down
Loading