use std::fmt;
use crate::taproot::{TapNodeHash, TapTweakHash};
use crate::SchnorrSighashType;
use secp256k1_zkp::{self, constants::SCHNORR_SIGNATURE_SIZE, Secp256k1, Verification};
pub use secp256k1_zkp::{Keypair, XOnlyPublicKey};
pub type UntweakedPublicKey = XOnlyPublicKey;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct TweakedPublicKey(XOnlyPublicKey);
pub type UntweakedKeypair = Keypair;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct TweakedKeypair(Keypair);
pub trait TapTweak {
type TweakedAux;
type TweakedKey;
fn tap_tweak<C: Verification>(
self,
secp: &Secp256k1<C>,
merkle_root: Option<TapNodeHash>,
) -> Self::TweakedAux;
fn dangerous_assume_tweaked(self) -> Self::TweakedKey;
}
impl TapTweak for UntweakedPublicKey {
type TweakedAux = (TweakedPublicKey, secp256k1_zkp::Parity);
type TweakedKey = TweakedPublicKey;
fn tap_tweak<C: Verification>(
self,
secp: &Secp256k1<C>,
merkle_root: Option<TapNodeHash>,
) -> (TweakedPublicKey, secp256k1_zkp::Parity) {
let tweak = TapTweakHash::from_key_and_tweak(self, merkle_root).to_scalar();
let (output_key, parity) = self.add_tweak(secp, &tweak).expect("Tap tweak failed");
debug_assert!(self.tweak_add_check(secp, &output_key, parity, tweak));
(TweakedPublicKey(output_key), parity)
}
fn dangerous_assume_tweaked(self) -> TweakedPublicKey {
TweakedPublicKey(self)
}
}
impl TapTweak for UntweakedKeypair {
type TweakedAux = TweakedKeypair;
type TweakedKey = TweakedKeypair;
fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> TweakedKeypair {
let (pubkey, _parity) = XOnlyPublicKey::from_keypair(&self);
let tweak = TapTweakHash::from_key_and_tweak(pubkey, merkle_root).to_scalar();
let tweaked = self.add_xonly_tweak(secp, &tweak).expect("Tap tweak failed");
TweakedKeypair(tweaked)
}
fn dangerous_assume_tweaked(self) -> TweakedKeypair {
TweakedKeypair(self)
}
}
impl TweakedPublicKey {
#[inline]
pub fn from_keypair(keypair: TweakedKeypair) -> Self {
let (xonly, _parity) = keypair.0.x_only_public_key();
TweakedPublicKey(xonly)
}
pub fn new(key: XOnlyPublicKey) -> TweakedPublicKey {
TweakedPublicKey(key)
}
pub fn into_inner(self) -> XOnlyPublicKey {
self.0
}
pub fn as_inner(&self) -> &XOnlyPublicKey {
&self.0
}
}
impl TweakedKeypair {
#[inline]
pub fn dangerous_assume_tweaked(pair: Keypair) -> TweakedKeypair {
TweakedKeypair(pair)
}
#[inline]
pub fn to_inner(self) -> Keypair {
self.0
}
#[inline]
pub fn public_parts(&self) -> (TweakedPublicKey, secp256k1_zkp::Parity) {
let (xonly, parity) = self.0.x_only_public_key();
(TweakedPublicKey(xonly), parity)
}
}
impl From<TweakedPublicKey> for XOnlyPublicKey {
#[inline]
fn from(pair: TweakedPublicKey) -> Self {
pair.0
}
}
impl From<TweakedKeypair> for Keypair {
#[inline]
fn from(pair: TweakedKeypair) -> Self {
pair.0
}
}
impl From<TweakedKeypair> for TweakedPublicKey {
#[inline]
fn from(pair: TweakedKeypair) -> Self {
TweakedPublicKey::from_keypair(pair)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "actual_serde"))]
pub struct SchnorrSig {
pub sig: secp256k1_zkp::schnorr::Signature,
pub hash_ty: SchnorrSighashType,
}
impl SchnorrSig {
pub fn from_slice(sl: &[u8]) -> Result<Self, SchnorrSigError> {
if sl.len() == SCHNORR_SIGNATURE_SIZE {
let sig = secp256k1_zkp::schnorr::Signature::from_slice(sl)
.map_err(|_| SchnorrSigError::InvalidSchnorrSig)?;
return Ok( SchnorrSig { sig, hash_ty : SchnorrSighashType::Default });
}
let (hash_ty, sig) = sl.split_last()
.ok_or(SchnorrSigError::InvalidSchnorrSig)?;
let hash_ty = SchnorrSighashType::from_u8(*hash_ty)
.ok_or(SchnorrSigError::InvalidSighashType(*hash_ty))?;
let sig = secp256k1_zkp::schnorr::Signature::from_slice(sig)
.map_err(|_| SchnorrSigError::InvalidSchnorrSig)?;
Ok(SchnorrSig { sig, hash_ty })
}
pub fn to_vec(&self) -> Vec<u8> {
let mut ser_sig = self.sig.as_ref().to_vec();
if let SchnorrSighashType::Default = self.hash_ty {
} else {
ser_sig.push(self.hash_ty as u8);
}
ser_sig
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum SchnorrSigError {
InvalidSighashType(u8),
InvalidSchnorrSig,
}
impl fmt::Display for SchnorrSigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SchnorrSigError::InvalidSighashType(hash_ty) =>
write!(f, "Invalid signature hash type {}", hash_ty),
SchnorrSigError::InvalidSchnorrSig => write!(f, "Cannot parse Schnorr Signature"),
}
}
}
impl ::std::error::Error for SchnorrSigError {}