Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Cargo-minimal.lock
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ dependencies = [

[[package]]
name = "miniscript"
version = "12.3.5"
version = "12.3.6"
dependencies = [
"bech32",
"bitcoin",
Expand Down
2 changes: 1 addition & 1 deletion Cargo-recent.lock
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ dependencies = [

[[package]]
name = "miniscript"
version = "12.3.5"
version = "12.3.6"
dependencies = [
"bech32",
"bitcoin",
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "miniscript"
version = "12.3.5"
version = "12.3.6"
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>, Sanket Kanjalkar <sanket1729@gmail.com>"]
license = "CC0-1.0"
homepage = "https://github.com/rust-bitcoin/rust-miniscript/"
Expand Down
100 changes: 96 additions & 4 deletions src/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,18 @@ impl Plan {
})
.into_script(),
),
DescriptorType::Wpkh
| DescriptorType::Wsh
DescriptorType::Wpkh | DescriptorType::Tr => (stack, ScriptBuf::new()),
DescriptorType::ShWpkh => (stack, self.descriptor.unsigned_script_sig()),
DescriptorType::Wsh
| DescriptorType::WshSortedMulti
| DescriptorType::Tr => (stack, ScriptBuf::new()),
DescriptorType::ShWsh | DescriptorType::ShWshSortedMulti | DescriptorType::ShWpkh => {
| DescriptorType::ShWsh
| DescriptorType::ShWshSortedMulti => {
let mut stack = stack;
let witness_script = self
.descriptor
.explicit_script()
.expect("wsh descriptors have explicit script");
stack.push(witness_script.into_bytes());
(stack, self.descriptor.unsigned_script_sig())
}
})
Expand Down Expand Up @@ -1150,4 +1157,89 @@ mod test {
assert!(psbt_input.redeem_script.is_none(), "Redeem script present");
assert_eq!(psbt_input.bip32_derivation.len(), 2, "Unexpected number of bip32_derivation");
}

#[test]
fn test_plan_satisfy_wsh() {
use std::collections::BTreeMap;

use bitcoin::secp256k1::{self, Secp256k1};

let secp = Secp256k1::new();

let sk =
secp256k1::SecretKey::from_slice(&b"sally was a secret key, she said"[..]).unwrap();
let pk = bitcoin::PublicKey::new(secp256k1::PublicKey::from_secret_key(&secp, &sk));

let desc =
Descriptor::<DefiniteDescriptorKey>::from_str(&format!("wsh(pk({}))", pk)).unwrap();

let sighash =
secp256k1::Message::from_digest_slice(&b"michael was a message, amusingly"[..])
.expect("32 bytes");
let ecdsa_sig = bitcoin::ecdsa::Signature {
signature: secp.sign_ecdsa(&sighash, &sk),
sighash_type: bitcoin::sighash::EcdsaSighashType::All,
};

// This witness script should exist in the witness stack returned by `Plan::satisfy`.
let exp_witness_script = desc.explicit_script().expect("wsh has explicit script");

let mut satisfier = BTreeMap::<DefiniteDescriptorKey, bitcoin::ecdsa::Signature>::new();
satisfier.insert(DefiniteDescriptorKey::from_str(&pk.to_string()).unwrap(), ecdsa_sig);

let assets = Assets::new().add(DescriptorPublicKey::from_str(&pk.to_string()).unwrap());
let plan = desc.plan(&assets).expect("plan should succeed");

let (witness, script_sig) = plan.satisfy(&satisfier).expect("satisfy should succeed");

// For native P2WSH:
// - script_sig should be empty
// - witness should contain [signature, witness_script]
assert_eq!(script_sig, ScriptBuf::new());
assert_eq!(witness.len(), 2);
assert_eq!(witness.last().unwrap(), &exp_witness_script.into_bytes());
}

#[test]
fn test_plan_satisfy_sh_wsh() {
use std::collections::BTreeMap;

use bitcoin::secp256k1::{self, Secp256k1};

let secp = Secp256k1::new();
let sk =
secp256k1::SecretKey::from_slice(&b"sally was a secret key, she said"[..]).unwrap();
let pk = bitcoin::PublicKey::new(secp256k1::PublicKey::from_secret_key(&secp, &sk));

let desc =
Descriptor::<DefiniteDescriptorKey>::from_str(&format!("sh(wsh(pk({})))", pk)).unwrap();

let sighash =
secp256k1::Message::from_digest_slice(&b"michael was a message, amusingly"[..])
.expect("32 bytes");
let ecdsa_sig = bitcoin::ecdsa::Signature {
signature: secp.sign_ecdsa(&sighash, &sk),
sighash_type: bitcoin::sighash::EcdsaSighashType::All,
};

// Get expected values before plan() consumes the descriptor.
let exp_witness_script = desc.explicit_script().expect("sh-wsh has explicit script");
let exp_script_sig = desc.unsigned_script_sig();

let mut satisfier: BTreeMap<DefiniteDescriptorKey, bitcoin::ecdsa::Signature> =
BTreeMap::new();
satisfier.insert(DefiniteDescriptorKey::from_str(&pk.to_string()).unwrap(), ecdsa_sig);

let assets = Assets::new().add(DescriptorPublicKey::from_str(&pk.to_string()).unwrap());
let plan = desc.plan(&assets).expect("plan should succeed");

let (witness, script_sig) = plan.satisfy(&satisfier).expect("satisfy should succeed");

// For P2SH-P2WSH:
// - script_sig should be the unsigned_script_sig (pushes the P2WSH redeemScript)
// - witness should contain [signature, witness_script]
assert_eq!(script_sig, exp_script_sig);
assert_eq!(witness.len(), 2);
assert_eq!(witness.last().unwrap(), &exp_witness_script.into_bytes());
}
}
2 changes: 1 addition & 1 deletion src/policy/concrete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
///
/// It is **not recommended** to use policy as a stable identifier for a miniscript. You should
/// use the policy compiler once, and then use the miniscript output as a stable identifier. See
/// the compiler document in [`doc/compiler.md`] for more details.
/// the compiler document in `doc/compiler.md` for more details.
#[cfg(feature = "compiler")]
pub fn compile_to_descriptor<Ctx: ScriptContext>(
&self,
Expand Down
Loading