Taproot-related methods for Script type
This commit is contained in:
parent
599c5f9488
commit
91b68a468d
|
@ -41,6 +41,9 @@ use policy::DUST_RELAY_TX_FEE;
|
||||||
|
|
||||||
use util::ecdsa::PublicKey;
|
use util::ecdsa::PublicKey;
|
||||||
use util::address::WitnessVersion;
|
use util::address::WitnessVersion;
|
||||||
|
use util::taproot::{LeafVersion, TapBranchHash, TapLeafHash};
|
||||||
|
use secp256k1::{Secp256k1, Verification};
|
||||||
|
use schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
|
||||||
|
|
||||||
/// A Bitcoin script.
|
/// A Bitcoin script.
|
||||||
#[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
#[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
||||||
|
@ -313,12 +316,27 @@ impl Script {
|
||||||
|
|
||||||
/// Generates P2WPKH-type of scriptPubkey
|
/// Generates P2WPKH-type of scriptPubkey
|
||||||
pub fn new_v0_wpkh(pubkey_hash: &WPubkeyHash) -> Script {
|
pub fn new_v0_wpkh(pubkey_hash: &WPubkeyHash) -> Script {
|
||||||
Script::new_witness_program(WitnessVersion::V0, &pubkey_hash.to_vec())
|
Script::new_witness_program(WitnessVersion::V0, &pubkey_hash[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
|
/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
|
||||||
pub fn new_v0_wsh(script_hash: &WScriptHash) -> Script {
|
pub fn new_v0_wsh(script_hash: &WScriptHash) -> Script {
|
||||||
Script::new_witness_program(WitnessVersion::V0, &script_hash.to_vec())
|
Script::new_witness_program(WitnessVersion::V0, &script_hash[..])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates P2TR for script spending path using an internal public key and some optional
|
||||||
|
/// script tree merkle root.
|
||||||
|
pub fn new_v1_p2tr<C: Verification>(secp: &Secp256k1<C>, internal_key: UntweakedPublicKey, merkle_root: Option<TapBranchHash>) -> Script {
|
||||||
|
let (output_key, _) = internal_key.tap_tweak(secp, merkle_root);
|
||||||
|
Script::new_witness_program(WitnessVersion::V1, &output_key.serialize())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates P2TR for key spending path for a known [`TweakedPublicKey`].
|
||||||
|
///
|
||||||
|
/// NB: Make sure that the used key is indeed tweaked (for instance, it comes from `rawtr`
|
||||||
|
/// descriptor content); otherwise please use [`Script::new_v1_p2tr`] method.
|
||||||
|
pub fn new_v1_p2tr_tweaked(output_key: TweakedPublicKey) -> Script {
|
||||||
|
Script::new_witness_program(WitnessVersion::V1, &output_key.serialize())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
|
/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script
|
||||||
|
@ -373,6 +391,20 @@ impl Script {
|
||||||
Script::new_v0_wsh(&self.wscript_hash())
|
Script::new_v0_wsh(&self.wscript_hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute P2TR output with a given internal key and a single script spending path equal to the
|
||||||
|
/// current script, assuming that the script is a Tapscript
|
||||||
|
#[inline]
|
||||||
|
pub fn to_v1_p2tr<C: Verification>(&self, secp: &Secp256k1<C>, internal_key: UntweakedPublicKey) -> Script {
|
||||||
|
let leaf_hash = TapLeafHash::from_script(&self, LeafVersion::TapScript);
|
||||||
|
let merkle_root = TapBranchHash::from_inner(leaf_hash.into_inner());
|
||||||
|
Script::new_v1_p2tr(&secp, internal_key, Some(merkle_root))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn witness_version(&self) -> Option<WitnessVersion> {
|
||||||
|
WitnessVersion::from_opcode(self.0[0].into()).ok()
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks whether a script pubkey is a p2sh output
|
/// Checks whether a script pubkey is a p2sh output
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_p2sh(&self) -> bool {
|
pub fn is_p2sh(&self) -> bool {
|
||||||
|
@ -428,7 +460,7 @@ impl Script {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_v0_p2wsh(&self) -> bool {
|
pub fn is_v0_p2wsh(&self) -> bool {
|
||||||
self.0.len() == 34 &&
|
self.0.len() == 34 &&
|
||||||
self.0[0] == opcodes::all::OP_PUSHBYTES_0.into_u8() &&
|
self.witness_version() == Some(WitnessVersion::V0) &&
|
||||||
self.0[1] == opcodes::all::OP_PUSHBYTES_32.into_u8()
|
self.0[1] == opcodes::all::OP_PUSHBYTES_32.into_u8()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,10 +468,18 @@ impl Script {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_v0_p2wpkh(&self) -> bool {
|
pub fn is_v0_p2wpkh(&self) -> bool {
|
||||||
self.0.len() == 22 &&
|
self.0.len() == 22 &&
|
||||||
self.0[0] == opcodes::all::OP_PUSHBYTES_0.into_u8() &&
|
self.witness_version() == Some(WitnessVersion::V0) &&
|
||||||
self.0[1] == opcodes::all::OP_PUSHBYTES_20.into_u8()
|
self.0[1] == opcodes::all::OP_PUSHBYTES_20.into_u8()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks whether a script pubkey is a P2TR output
|
||||||
|
#[inline]
|
||||||
|
pub fn is_v1_p2tr(&self) -> bool {
|
||||||
|
self.0.len() == 34 &&
|
||||||
|
self.witness_version() == Some(WitnessVersion::V1) &&
|
||||||
|
self.0[1] == opcodes::all::OP_PUSHBYTES_32.into_u8()
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if this is an OP_RETURN output
|
/// Check if this is an OP_RETURN output
|
||||||
pub fn is_op_return (&self) -> bool {
|
pub fn is_op_return (&self) -> bool {
|
||||||
!self.0.is_empty() && (opcodes::All::from(self.0[0]) == opcodes::all::OP_RETURN)
|
!self.0.is_empty() && (opcodes::All::from(self.0[0]) == opcodes::all::OP_RETURN)
|
||||||
|
|
Loading…
Reference in New Issue