Repository: rust-bitcoin/rust-bitcoin
Pull request #1597 (2023-01-27 01:02:39)

Move sighash types around
This PR is now part 1 of great sighash clean up. It does not attempt to split ecdsa into two parts as discussed below, that is WIP and will be done in a separate PR after this upcoming release. Does however create `LegacySighash` and `SegwitV0Sighash` types.

This PR moves us along the road by doing:

- Move `sighash` to the `crypto` module, where I should have put it ages ago :)
- Move the taproot keys to the `keys` module
- Rename the `schnorr` module -> `taproot`
- Rename `TapSighashHash` -> `TapSighash`
- Rename `SchnorrSighashType` -> `TapSighashType`
- Fix a bunch of other schnorr usage (including pub/priv methods).

This leaves us in a situation where we have taproot sig and sighash type, and non-taproot ones prefixed with "ecdsa". Its not uniform but it kind of makes sense.

Fix: #1542
Fix: #1550

tcharding: Needs https://github.com/rust-bitcoin/rust-bitcoin/pull/1594 to get past clippy.
Kixunil: Yeah, I guess this is worth rebasing. :)

The following is is only important if we need to distinguish between hash-creating algos rather than signing algos. I suspect it's the latter.

I'm not sure about if it should be `schnorr::Sighash` or `taproot::Sighash`. What if a new sighash is created that still uses schnorr but not taproot? Presumably this could be the case for CISA. Also is "taproot" the name of witness v1 or of the construction? because if witness v2 uses same construction but different sighash algorithm then it'd still be confusing.

Maybe they should be called `LegacySighash` and `WitnessV1Sighash`.
apoelstra: @Kixunil I think we should go with `taproot::SigHash` and then deprecate it in the (far?) future when we know how it's wrong.

I definitely agree with you in principle that associating the sighash with "Taproot" is not the right categorization (though I do think it's better than "schnorr"). But the next sighash version could appear in several ways:
* a new segwit version greater than 1
* a whole new transaction format, maybe in an extension block or something
* a new tapleaf version not equal to `0xc0`
* a new CHECKSIG opcode using the same segwit/tapleaf version
* some sort of weird hybrid thing that uses the "same" sighash but adds meaningful data to the annex field, which is currently policy-limited to be empty but has no consensus limits whatsoever

The first couple are far-fetched but if I had to put odds on the what the next sighash version would look like, I'd give double-digit percentages to each of the last 3. And it would be pretty hard for us to specify all of those in the name of a type, while still making it discoverable and explainable.

Maybe when the next taproot leaf version comes out we'll deprecate much of the `taproot` module and replace it with a more specific `tapleaf_c0` module or something. But I think it's just too hard to predict this from here.

Kixunil: Wouldn't it be better to just not track the algorithm which *produced* the type but only track which *signing* algorithm needs to be used? Similar to what we did with `TapNode`. I can't imagine a reasonable use case where one would want to distinguish them.

Also it just occurred to me we could simply start using tagging with a default if we wanted backwards-compatibility at all costs.
apoelstra: I'm skeptical. I suppose that distinguishing between ECDSA and Schnorr may make certain kinds of signing APIs more type-safe, but this seems like a weird and arbitrary place to stop using the type system.

Legacy and Taproot sighashe types are generated differently, but also encoded differently, used in different kinds of outputs, and commit to different sets of transaction data. All of those differences will be true between Taproot sighashtypes and future kinds of sighashtypes.

We should probably also distinguish between legacy and segwit sighash types, because even though they have the same names, they commit to very different sets of data and have different security implications for signers.
tcharding: This uncovers a bit of tangle in the `taproot` code.
- taproot keys could go in `crypto/keys.rs`
- We could remove ecdsa/schnorr in favour of taproot.rs/legacy.rs/segwit_v0.rs (holds signatures, sighash, and sighash types, currently types in ecdsa would need to be duplicated for legacy/segwit_v0
- We get naming conflicts with `crate::taproot` and the re-export of `crate::crypto::taproot` (after re-name) but we could re-export the crypto stuff from `crate::taproot`.
- Some stuff in `crate::taproot` should probably be over in `crate::crypto::taproot`

I can probably do this all in two separate PRs, one for taproot stuff and one for ecdsa -> legacy/segwit_v0 if we get a bit of consensus on the direction.

Kixunil: @apoelstra that convinced me. I agree with also separating legacy vs segwit v0.

@tcharding can you be more specific about naming conflict in `crate::taproot`?

I know there would be a naming conflict at top-level. IME sighashes are not *that* commonly used, so I would just *not* reexport them.

Separating into two PRs sounds fine.
tcharding: We have `bitcoin/src/taproot.rs` and we reexport `crate::crypto::schnorr` so folks can use `schnorr::Sighash`. If that becomes `taproot::Sighash` it becomes impossible for lib users to use both modules at the same time (considering we now favour disambiguating by way of a single level of additional path). All the stuff in `src/taproot.rs` currently has `Tap` prefixes but I still do not think we should be having multiple modules with the same name without doing reexports because sooner or later it will break.

The only reason to have all the crypto stuff separate is for users to _not_ use the soon-to-be-created `crypto` crate, but for 'normal' users we can feature gate the reexport so they just use `crate::taproot` for all taproot stuff.

Anyways, I'll do a PR to showcase it.
apoelstra: I'd appreciate a PR. I agree with Kix that it'd be fine to just not export these types. You can only obtain them from non-generic funcitons (I'm pretty sure) so whenever users handle these they should be able to use type inference. I also think it's fine to drop `schnorr::Sighash` (or to deprecate this and require they switch to `taproot::Sighash`. I also think the various `Tap` prefixes are fine, even if you have to do ugly stuff like `taproot::TapBranch`. This is because words like "tapbranch" are standard terms by themselves.


tcharding: > I'd appreciate a PR.

Been working on this, thought I had a draft with some problems and while writing the PR description I gave myself some new ideas. Hence I pushed the first part to this branch, second part to come. Spoiler - the taproot stuff was easy.
Kixunil: > This is because words like "tapbranch" are standard terms by themselves.

Indeed, that's my thinking as well.
tcharding: BTW  team, lets not test against the strings in error messages, it is super painful to maintain.
tcharding: For anyone following along closely I got confused with the `Sighash` and `TapSighashHash` types, this PR has never touched them but I erroneously claimed yesterday to fix #1550. We now have #1620 to do that. My bad.
tcharding: > BTW team, lets not test against the strings in error messages, it is super painful to maintain.

EDIT: Oooh, I see why we did this now, since we no longer derive `Eq` on error types and we don't have `matches!` yet its a PITA to check a function returns the expected error type. Perhaps after MSRV bump the situation will improve. Worth keeping in mind during the error overhaul.
Kixunil: Nothing prevents us from writing the compiler-version-gated `matches!` macro ourselves. (similar to what we plan to do with `unsigned_abs`).
tcharding: Rebased to fix merge conflicts, no other changes.
tcharding: Rebase only, no changes.

Patch:
diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs
index d68bd90d..55d6dd34 100644
--- a/bitcoin/examples/taproot-psbt.rs
+++ b/bitcoin/examples/taproot-psbt.rs
@@ -81,18 +81,18 @@
 use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint};
 use bitcoin::consensus::encode;
 use bitcoin::constants::COIN_VALUE;
+use bitcoin::crypto::taproot;
 use bitcoin::hashes::Hash;
-use bitcoin::key::XOnlyPublicKey;
+use bitcoin::key::{TapTweak, XOnlyPublicKey};
 use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP};
 use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType};
-use bitcoin::schnorr::{self, TapTweak};
 use bitcoin::secp256k1::{Message, Secp256k1};
-use bitcoin::sighash::{self, SchnorrSighashType, SighashCache};
+use bitcoin::sighash::{self, TapSighashType, SighashCache};
 use bitcoin::taproot::{
-    LeafVersion, TapLeafHash, TapSighashHash, TaprootBuilder, TaprootSpendInfo,
+    LeafVersion, TapLeafHash, TapSighash, TaprootBuilder, TaprootSpendInfo,
 };
 use bitcoin::{
-    absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Witness,
+    absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut,  Witness,
 };
 
 fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -283,8 +283,8 @@ fn generate_bip86_key_spend_tx(
         |(vout, input)| {
             let hash_ty = input
                 .sighash_type
-                .and_then(|psbt_sighash_type| psbt_sighash_type.schnorr_hash_ty().ok())
-                .unwrap_or(SchnorrSighashType::All);
+                .and_then(|psbt_sighash_type| psbt_sighash_type.taproot_hash_ty().ok())
+                .unwrap_or(TapSighashType::All);
             let hash = SighashCache::new(&unsigned_tx).taproot_key_spend_signature_hash(
                 vout,
                 &sighash::Prevouts::All(&[TxOut {
@@ -300,7 +300,7 @@ fn generate_bip86_key_spend_tx(
                 .ok_or("Missing taproot key origin")?;
 
             let secret_key = master_xpriv.derive_priv(secp, &derivation_path)?.to_priv().inner;
-            sign_psbt_schnorr(
+            sign_psbt_taproot(
                 &secret_key,
                 input.tap_internal_key.unwrap(),
                 None,
@@ -518,8 +518,8 @@ fn refresh_tx(
 
             let hash_ty = input
                 .sighash_type
-                .and_then(|psbt_sighash_type| psbt_sighash_type.schnorr_hash_ty().ok())
-                .unwrap_or(SchnorrSighashType::All);
+                .and_then(|psbt_sighash_type| psbt_sighash_type.taproot_hash_ty().ok())
+                .unwrap_or(TapSighashType::All);
             let hash = SighashCache::new(&psbt.unsigned_tx).taproot_key_spend_signature_hash(
                 0,
                 &sighash::Prevouts::All(&[TxOut {
@@ -536,7 +536,7 @@ fn refresh_tx(
                     .ok_or("Missing taproot key origin")?;
                 let secret_key =
                     self.master_xpriv.derive_priv(&self.secp, &derivation_path)?.to_priv().inner;
-                sign_psbt_schnorr(
+                sign_psbt_taproot(
                     &secret_key,
                     spend_info.internal_key(),
                     None,
@@ -660,7 +660,7 @@ fn spend_inheritance(
             let secret_key =
                 self.master_xpriv.derive_priv(&self.secp, &derivation_path)?.to_priv().inner;
             for lh in leaf_hashes {
-                let hash_ty = SchnorrSighashType::All;
+                let hash_ty = TapSighashType::All;
                 let hash = SighashCache::new(&unsigned_tx).taproot_script_spend_signature_hash(
                     0,
                     &sighash::Prevouts::All(&[TxOut {
@@ -670,7 +670,7 @@ fn spend_inheritance(
                     *lh,
                     hash_ty,
                 )?;
-                sign_psbt_schnorr(
+                sign_psbt_taproot(
                     &secret_key,
                     *x_only_pubkey,
                     Some(*lh),
@@ -730,13 +730,13 @@ fn spend_inheritance(
 // licenses.
 
 // Calling this with `leaf_hash` = `None` will sign for key-spend
-fn sign_psbt_schnorr(
+fn sign_psbt_taproot(
     secret_key: &secp256k1::SecretKey,
     pubkey: XOnlyPublicKey,
     leaf_hash: Option<TapLeafHash>,
     psbt_input: &mut psbt::Input,
-    hash: TapSighashHash,
-    hash_ty: SchnorrSighashType,
+    hash: TapSighash,
+    hash_ty: TapSighashType,
     secp: &Secp256k1<secp256k1::All>,
 ) {
     let keypair = secp256k1::KeyPair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
@@ -747,7 +747,7 @@ fn sign_psbt_schnorr(
 
     let sig = secp.sign_schnorr(&Message::from_slice(&hash.into_inner()[..]).unwrap(), &keypair);
 
-    let final_signature = schnorr::Signature { sig, hash_ty };
+    let final_signature = taproot::Signature { sig, hash_ty };
 
     if let Some(lh) = leaf_hash {
         psbt_input.tap_script_sigs.insert((pubkey, lh), final_signature);
diff --git a/bitcoin/src/address.rs b/bitcoin/src/address.rs
index e1cdc0ea..e83eb8bd 100644
--- a/bitcoin/src/address.rs
+++ b/bitcoin/src/address.rs
@@ -44,8 +44,7 @@
 use crate::blockdata::opcodes;
 use crate::blockdata::opcodes::all::*;
 use crate::blockdata::script::{self, Instruction, Script, ScriptBuf, PushBytes, PushBytesBuf, PushBytesErrorReport};
-use crate::crypto::key::PublicKey;
-use crate::crypto::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
+use crate::crypto::key::{PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey};
 use crate::error::ParseIntError;
 use crate::hash_types::{PubkeyHash, ScriptHash};
 use crate::hashes::{sha256, Hash, HashEngine};
diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs
index 94e0d1e2..676e4eb2 100644
--- a/bitcoin/src/blockdata/script/borrowed.rs
+++ b/bitcoin/src/blockdata/script/borrowed.rs
@@ -17,10 +17,9 @@
 use crate::consensus::Encodable;
 use crate::hash_types::{ScriptHash, WScriptHash};
 use crate::hashes::Hash;
-use crate::key::PublicKey;
+use crate::key::{PublicKey, UntweakedPublicKey};
 use crate::policy::DUST_RELAY_TX_FEE;
 use crate::prelude::*;
-use crate::schnorr::UntweakedPublicKey;
 use crate::taproot::{LeafVersion, TapNodeHash, TapLeafHash};
 
 /// Bitcoin script slice.
diff --git a/bitcoin/src/blockdata/script/owned.rs b/bitcoin/src/blockdata/script/owned.rs
index 89157634..d545a827 100644
--- a/bitcoin/src/blockdata/script/owned.rs
+++ b/bitcoin/src/blockdata/script/owned.rs
@@ -11,9 +11,8 @@
 use crate::blockdata::script::{opcode_to_verify, Builder, Instruction, Script, PushBytes};
 use crate::hashes::hex;
 use crate::hash_types::{PubkeyHash, WPubkeyHash, ScriptHash, WScriptHash};
-use crate::key::PublicKey;
+use crate::key::{PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey};
 use crate::prelude::*;
-use crate::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey};
 use crate::taproot::TapNodeHash;
 
 /// An owned, growable script.
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 10bb53ef..af8e4d48 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -30,14 +30,15 @@
 use crate::blockdata::locktime::absolute::{self, Height, Time};
 use crate::blockdata::locktime::relative;
 use crate::consensus::{encode, Decodable, Encodable};
-use crate::hash_types::{Sighash, Txid, Wtxid};
+use crate::crypto::sighash::LegacySighash;
+use crate::hash_types::{Txid, Wtxid};
 use crate::VarInt;
 use crate::internal_macros::impl_consensus_encoding;
 use crate::parse::impl_parse_str_through_int;
 use super::Weight;
 
 #[cfg(doc)]
-use crate::sighash::{EcdsaSighashType, SchnorrSighashType};
+use crate::sighash::{EcdsaSighashType, TapSighashType};
 
 /// A reference to a transaction output.
 ///
@@ -589,16 +590,17 @@ impl<E> EncodeSigningDataResult<E> {
     /// ```rust
     /// # use bitcoin::consensus::deserialize;
     /// # use bitcoin::Transaction;
-    /// # use bitcoin::hash_types::Sighash;
+    /// # use bitcoin::crypto::sighash::{LegacySighash, SighashCache};
     /// # use bitcoin_hashes::{Hash, hex::FromHex};
-    /// # let mut writer = Sighash::engine();
+    /// # let mut writer = LegacySighash::engine();
     /// # let input_index = 0;
     /// # let script_pubkey = bitcoin::ScriptBuf::new();
     /// # let sighash_u32 = 0u32;
     /// # const SOME_TX: &'static str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
     /// # let raw_tx = Vec::from_hex(SOME_TX).unwrap();
     /// # let tx: Transaction = deserialize(&raw_tx).unwrap();
-    /// if tx.encode_signing_data_to(&mut writer, input_index, &script_pubkey, sighash_u32)
+    /// # let cache = SighashCache::new(&tx);
+    /// if cache.legacy_encode_signing_data_to(&mut writer, input_index, &script_pubkey, sighash_u32)
     ///         .is_sighash_single_bug()
     ///         .expect("writer can't fail") {
     ///     // use a hash value of "1", instead of computing the actual hash due to SIGHASH_SINGLE bug
@@ -835,7 +837,7 @@ pub fn signature_hash(
         input_index: usize,
         script_pubkey: &Script,
         sighash_u32: u32
-    ) -> Sighash {
+    ) -> LegacySighash {
         assert!(input_index < self.input.len());  // Panic on OOB, enables expect below.
 
         let cache = crate::sighash::SighashCache::new(self);
diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs
index acad5fa1..83af9989 100644
--- a/bitcoin/src/crypto/key.rs
+++ b/bitcoin/src/crypto/key.rs
@@ -12,12 +12,14 @@
 use core::fmt::{self, Write};
 
 use bitcoin_internals::write_err;
-pub use secp256k1::{self, Secp256k1, XOnlyPublicKey, KeyPair};
+
+pub use secp256k1::{self, constants, Secp256k1, KeyPair, XOnlyPublicKey, Verification, Parity};
 
 use crate::{base58, io};
 use crate::network::constants::Network;
 use crate::hashes::{Hash, hash160, hex, hex::FromHex};
 use crate::hash_types::{PubkeyHash, WPubkeyHash};
+use crate::taproot::{TapNodeHash, TapTweakHash};
 
 /// A key-related error.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@@ -546,6 +548,215 @@ fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
     }
 }
 
+/// Untweaked BIP-340 X-coord-only public key
+pub type UntweakedPublicKey = XOnlyPublicKey;
+
+/// Tweaked BIP-340 X-coord-only public key
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
+#[cfg_attr(feature = "serde", serde(transparent))]
+pub struct TweakedPublicKey(XOnlyPublicKey);
+
+impl fmt::LowerHex for TweakedPublicKey {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::LowerHex::fmt(&self.0, f)
+    }
+}
+
+impl fmt::Display for TweakedPublicKey {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
+
+/// Untweaked BIP-340 key pair
+pub type UntweakedKeyPair = KeyPair;
+
+/// Tweaked BIP-340 key pair
+///
+/// # Examples
+/// ```
+/// # #[cfg(feature = "rand-std")] {
+/// # use bitcoin::crypto::key::{KeyPair, TweakedKeyPair, TweakedPublicKey};
+/// # use bitcoin::secp256k1::{rand, Secp256k1};
+/// # let secp = Secp256k1::new();
+/// # let keypair = TweakedKeyPair::dangerous_assume_tweaked(KeyPair::new(&secp, &mut rand::thread_rng()));
+/// // There are various conversion methods available to get a tweaked pubkey from a tweaked keypair.
+/// let (_pk, _parity) = keypair.public_parts();
+/// let _pk  = TweakedPublicKey::from_keypair(keypair);
+/// let _pk = TweakedPublicKey::from(keypair);
+/// # }
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
+#[cfg_attr(feature = "serde", serde(transparent))]
+pub struct TweakedKeyPair(KeyPair);
+
+/// A trait for tweaking BIP340 key types (x-only public keys and key pairs).
+pub trait TapTweak {
+    /// Tweaked key type with optional auxiliary information
+    type TweakedAux;
+    /// Tweaked key type
+    type TweakedKey;
+
+    /// Tweaks an untweaked key with corresponding public key value and optional script tree merkle
+    /// root. For the [`KeyPair`] type this also tweaks the private key in the pair.
+    ///
+    /// This is done by using the equation Q = P + H(P|c)G, where
+    ///  * Q is the tweaked public key
+    ///  * P is the internal public key
+    ///  * H is the hash function
+    ///  * c is the commitment data
+    ///  * G is the generator point
+    ///
+    /// # Returns
+    /// The tweaked key and its parity.
+    fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> Self::TweakedAux;
+
+    /// Directly converts an [`UntweakedPublicKey`] to a [`TweakedPublicKey`]
+    ///
+    /// This method is dangerous and can lead to loss of funds if used incorrectly.
+    /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
+    fn dangerous_assume_tweaked(self) -> Self::TweakedKey;
+}
+
+impl TapTweak for UntweakedPublicKey {
+    type TweakedAux = (TweakedPublicKey, Parity);
+    type TweakedKey = TweakedPublicKey;
+
+    /// Tweaks an untweaked public key with corresponding public key value and optional script tree
+    /// merkle root.
+    ///
+    /// This is done by using the equation Q = P + H(P|c)G, where
+    ///  * Q is the tweaked public key
+    ///  * P is the internal public key
+    ///  * H is the hash function
+    ///  * c is the commitment data
+    ///  * G is the generator point
+    ///
+    /// # Returns
+    /// The tweaked key and its parity.
+    fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> (TweakedPublicKey, 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;
+
+    /// Tweaks private and public keys within an untweaked [`KeyPair`] with corresponding public key
+    /// value and optional script tree merkle root.
+    ///
+    /// This is done by tweaking private key within the pair using the equation q = p + H(P|c), where
+    ///  * q is the tweaked private key
+    ///  * p is the internal private key
+    ///  * H is the hash function
+    ///  * c is the commitment data
+    /// The public key is generated from a private key by multiplying with generator point, Q = qG.
+    ///
+    /// # Returns
+    /// The tweaked key and its parity.
+    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 {
+    /// Returns the [`TweakedPublicKey`] for `keypair`.
+    #[inline]
+    pub fn from_keypair(keypair: TweakedKeyPair) -> Self {
+        let (xonly, _parity) = keypair.0.x_only_public_key();
+        TweakedPublicKey(xonly)
+    }
+
+    /// Creates a new [`TweakedPublicKey`] from a [`XOnlyPublicKey`]. No tweak is applied, consider
+    /// calling `tap_tweak` on an [`UntweakedPublicKey`] instead of using this constructor.
+    ///
+    /// This method is dangerous and can lead to loss of funds if used incorrectly.
+    /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
+    #[inline]
+    pub fn dangerous_assume_tweaked(key: XOnlyPublicKey) -> TweakedPublicKey {
+        TweakedPublicKey(key)
+    }
+
+    /// Returns the underlying public key.
+    pub fn to_inner(self) -> XOnlyPublicKey {
+        self.0
+    }
+
+    /// Serialize the key as a byte-encoded pair of values. In compressed form
+    /// the y-coordinate is represented by only a single bit, as x determines
+    /// it up to one bit.
+    #[inline]
+    pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] {
+        self.0.serialize()
+    }
+}
+
+impl TweakedKeyPair {
+    /// Creates a new [`TweakedKeyPair`] from a [`KeyPair`]. No tweak is applied, consider
+    /// calling `tap_tweak` on an [`UntweakedKeyPair`] instead of using this constructor.
+    ///
+    /// This method is dangerous and can lead to loss of funds if used incorrectly.
+    /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
+    #[inline]
+    pub fn dangerous_assume_tweaked(pair: KeyPair) -> TweakedKeyPair {
+        TweakedKeyPair(pair)
+    }
+
+    /// Returns the underlying key pair.
+    #[inline]
+    pub fn to_inner(self) -> KeyPair {
+        self.0
+    }
+
+    /// Returns the [`TweakedPublicKey`] and its [`Parity`] for this [`TweakedKeyPair`].
+    #[inline]
+    pub fn public_parts(&self) -> (TweakedPublicKey, 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)
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/bitcoin/src/crypto/mod.rs b/bitcoin/src/crypto/mod.rs
index b36b0134..4c4d5129 100644
--- a/bitcoin/src/crypto/mod.rs
+++ b/bitcoin/src/crypto/mod.rs
@@ -8,4 +8,5 @@
 
 pub mod ecdsa;
 pub mod key;
-pub mod schnorr;
+pub mod sighash;
+pub mod taproot;
diff --git a/bitcoin/src/crypto/schnorr.rs b/bitcoin/src/crypto/schnorr.rs
deleted file mode 100644
index 3f1630c6..00000000
--- a/bitcoin/src/crypto/schnorr.rs
+++ /dev/null
@@ -1,323 +0,0 @@
-// Written in 2014 by Andrew Poelstra <apoelstra@wpsoftware.net>
-// SPDX-License-Identifier: CC0-1.0
-
-//! Schnorr Bitcoin keys.
-//!
-//! This module provides Schnorr keys used in Bitcoin, reexporting Secp256k1
-//! Schnorr key types.
-//!
-
-use core::fmt;
-
-use bitcoin_internals::write_err;
-
-pub use secp256k1::{self, constants, Secp256k1, KeyPair, XOnlyPublicKey, Verification, Parity};
-
-use crate::prelude::*;
-
-use crate::taproot::{TapNodeHash, TapTweakHash};
-use crate::sighash::SchnorrSighashType;
-
-/// Untweaked BIP-340 X-coord-only public key
-pub type UntweakedPublicKey = XOnlyPublicKey;
-
-/// Tweaked BIP-340 X-coord-only public key
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
-#[cfg_attr(feature = "serde", serde(transparent))]
-pub struct TweakedPublicKey(XOnlyPublicKey);
-
-impl fmt::LowerHex for TweakedPublicKey {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::LowerHex::fmt(&self.0, f)
-    }
-}
-
-impl fmt::Display for TweakedPublicKey {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.0, f)
-    }
-}
-
-/// Untweaked BIP-340 key pair
-pub type UntweakedKeyPair = KeyPair;
-
-/// Tweaked BIP-340 key pair
-///
-/// # Examples
-/// ```
-/// # #[cfg(feature = "rand-std")] {
-/// # use bitcoin::schnorr::{KeyPair, TweakedKeyPair, TweakedPublicKey};
-/// # use bitcoin::secp256k1::{rand, Secp256k1};
-/// # let secp = Secp256k1::new();
-/// # let keypair = TweakedKeyPair::dangerous_assume_tweaked(KeyPair::new(&secp, &mut rand::thread_rng()));
-/// // There are various conversion methods available to get a tweaked pubkey from a tweaked keypair.
-/// let (_pk, _parity) = keypair.public_parts();
-/// let _pk  = TweakedPublicKey::from_keypair(keypair);
-/// let _pk = TweakedPublicKey::from(keypair);
-/// # }
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
-#[cfg_attr(feature = "serde", serde(transparent))]
-pub struct TweakedKeyPair(KeyPair);
-
-/// A trait for tweaking BIP340 key types (x-only public keys and key pairs).
-pub trait TapTweak {
-    /// Tweaked key type with optional auxiliary information
-    type TweakedAux;
-    /// Tweaked key type
-    type TweakedKey;
-
-    /// Tweaks an untweaked key with corresponding public key value and optional script tree merkle
-    /// root. For the [`KeyPair`] type this also tweaks the private key in the pair.
-    ///
-    /// This is done by using the equation Q = P + H(P|c)G, where
-    ///  * Q is the tweaked public key
-    ///  * P is the internal public key
-    ///  * H is the hash function
-    ///  * c is the commitment data
-    ///  * G is the generator point
-    ///
-    /// # Returns
-    /// The tweaked key and its parity.
-    fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> Self::TweakedAux;
-
-    /// Directly converts an [`UntweakedPublicKey`] to a [`TweakedPublicKey`]
-    ///
-    /// This method is dangerous and can lead to loss of funds if used incorrectly.
-    /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
-    fn dangerous_assume_tweaked(self) -> Self::TweakedKey;
-}
-
-impl TapTweak for UntweakedPublicKey {
-    type TweakedAux = (TweakedPublicKey, Parity);
-    type TweakedKey = TweakedPublicKey;
-
-    /// Tweaks an untweaked public key with corresponding public key value and optional script tree
-    /// merkle root.
-    ///
-    /// This is done by using the equation Q = P + H(P|c)G, where
-    ///  * Q is the tweaked public key
-    ///  * P is the internal public key
-    ///  * H is the hash function
-    ///  * c is the commitment data
-    ///  * G is the generator point
-    ///
-    /// # Returns
-    /// The tweaked key and its parity.
-    fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> (TweakedPublicKey, 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;
-
-    /// Tweaks private and public keys within an untweaked [`KeyPair`] with corresponding public key
-    /// value and optional script tree merkle root.
-    ///
-    /// This is done by tweaking private key within the pair using the equation q = p + H(P|c), where
-    ///  * q is the tweaked private key
-    ///  * p is the internal private key
-    ///  * H is the hash function
-    ///  * c is the commitment data
-    /// The public key is generated from a private key by multiplying with generator point, Q = qG.
-    ///
-    /// # Returns
-    /// The tweaked key and its parity.
-    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 {
-    /// Returns the [`TweakedPublicKey`] for `keypair`.
-    #[inline]
-    pub fn from_keypair(keypair: TweakedKeyPair) -> Self {
-        let (xonly, _parity) = keypair.0.x_only_public_key();
-        TweakedPublicKey(xonly)
-    }
-
-    /// Creates a new [`TweakedPublicKey`] from a [`XOnlyPublicKey`]. No tweak is applied, consider
-    /// calling `tap_tweak` on an [`UntweakedPublicKey`] instead of using this constructor.
-    ///
-    /// This method is dangerous and can lead to loss of funds if used incorrectly.
-    /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
-    #[inline]
-    pub fn dangerous_assume_tweaked(key: XOnlyPublicKey) -> TweakedPublicKey {
-        TweakedPublicKey(key)
-    }
-
-    /// Returns the underlying public key.
-    pub fn to_inner(self) -> XOnlyPublicKey {
-        self.0
-    }
-
-    /// Serialize the key as a byte-encoded pair of values. In compressed form
-    /// the y-coordinate is represented by only a single bit, as x determines
-    /// it up to one bit.
-    #[inline]
-    pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] {
-        self.0.serialize()
-    }
-}
-
-impl TweakedKeyPair {
-    /// Creates a new [`TweakedKeyPair`] from a [`KeyPair`]. No tweak is applied, consider
-    /// calling `tap_tweak` on an [`UntweakedKeyPair`] instead of using this constructor.
-    ///
-    /// This method is dangerous and can lead to loss of funds if used incorrectly.
-    /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
-    #[inline]
-    pub fn dangerous_assume_tweaked(pair: KeyPair) -> TweakedKeyPair {
-        TweakedKeyPair(pair)
-    }
-
-    /// Returns the underlying key pair.
-    #[inline]
-    pub fn to_inner(self) -> KeyPair {
-        self.0
-    }
-
-    /// Returns the [`TweakedPublicKey`] and its [`Parity`] for this [`TweakedKeyPair`].
-    #[inline]
-    pub fn public_parts(&self) -> (TweakedPublicKey, 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)
-    }
-}
-
-/// A BIP340-341 serialized schnorr signature with the corresponding hash type.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
-pub struct Signature {
-    /// The underlying schnorr signature
-    pub sig: secp256k1::schnorr::Signature,
-    /// The corresponding hash type
-    pub hash_ty: SchnorrSighashType,
-}
-
-impl Signature {
-    /// Deserialize from slice
-    pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
-        match sl.len() {
-            64 => {
-                // default type
-                let sig = secp256k1::schnorr::Signature::from_slice(sl)
-                    .map_err(Error::Secp256k1)?;
-                Ok(Signature { sig, hash_ty: SchnorrSighashType::Default })
-            },
-            65 => {
-                let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65");
-                let hash_ty = SchnorrSighashType::from_consensus_u8(*hash_ty)
-                    .map_err(|_| Error::InvalidSighashType(*hash_ty))?;
-                let sig = secp256k1::schnorr::Signature::from_slice(sig)
-                    .map_err(Error::Secp256k1)?;
-                Ok(Signature { sig, hash_ty })
-            }
-            len => {
-                Err(Error::InvalidSignatureSize(len))
-            }
-        }
-    }
-
-    /// Serialize Signature
-    pub fn to_vec(self) -> Vec<u8> {
-        // TODO: add support to serialize to a writer to SerializedSig
-        let mut ser_sig = self.sig.as_ref().to_vec();
-        if self.hash_ty == SchnorrSighashType::Default {
-            // default sighash type, don't add extra sighash byte
-        } else {
-            ser_sig.push(self.hash_ty as u8);
-        }
-        ser_sig
-    }
-
-}
-
-/// A schnorr sig related error.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[non_exhaustive]
-pub enum Error {
-    /// Base58 encoding error
-    InvalidSighashType(u8),
-    /// Signature has valid size but does not parse correctly
-    Secp256k1(secp256k1::Error),
-    /// Invalid schnorr signature size
-    InvalidSignatureSize(usize),
-}
-
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Error::InvalidSighashType(hash_ty) =>
-                write!(f, "Invalid signature hash type {}", hash_ty),
-            Error::Secp256k1(ref e) =>
-                write_err!(f, "Schnorr signature has correct len but is malformed"; e),
-            Error::InvalidSignatureSize(sz) =>
-                write!(f, "Invalid Schnorr signature size: {}", sz),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
-impl std::error::Error for Error {
-    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-        use self::Error::*;
-
-        match self {
-            Secp256k1(e) => Some(e),
-            InvalidSighashType(_) | InvalidSignatureSize(_) => None,
-        }
-    }
-}
-
-impl From<secp256k1::Error> for Error {
-
-    fn from(e: secp256k1::Error) -> Error {
-        Error::Secp256k1(e)
-    }
-}
diff --git a/bitcoin/src/sighash.rs b/bitcoin/src/crypto/sighash.rs
similarity index 86%
rename from bitcoin/src/sighash.rs
rename to bitcoin/src/crypto/sighash.rs
index bc9dae04..4b85e1b1 100644
--- a/bitcoin/src/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -19,10 +19,9 @@
 use crate::blockdata::witness::Witness;
 use crate::consensus::{encode, Encodable};
 use crate::error::impl_std_error;
-use crate::hashes::{sha256, sha256d, Hash};
-use crate::hash_types::Sighash;
+use crate::hashes::{hash_newtype, sha256, sha256t_hash_newtype, sha256d, Hash};
 use crate::prelude::*;
-use crate::taproot::{LeafVersion, TapLeafHash, TapSighashHash, TAPROOT_ANNEX_PREFIX};
+use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX};
 
 /// Used for signature hash for invalid use of SIGHASH_SINGLE.
 #[rustfmt::skip]
@@ -33,6 +32,39 @@
     0, 0, 0, 0, 0, 0, 0, 0
 ];
 
+/// The SHA-256 midstate value for the [`TapSighash`].
+pub(crate) const MIDSTATE_TAPSIGHASH: [u8; 32] = [
+    245, 4, 164, 37, 215, 248, 120, 59, 19, 99, 134, 138, 227, 229, 86, 88, 110, 238, 148, 93, 188,
+    120, 136, 221, 2, 166, 226, 195, 24, 115, 254, 159,
+];
+// f504a425d7f8783b1363868ae3e556586eee945dbc7888dd02a6e2c31873fe9f
+
+macro_rules! impl_thirty_two_byte_hash {
+    ($ty:ident) => {
+        impl secp256k1::ThirtyTwoByteHash for $ty {
+            fn into_32(self) -> [u8; 32] { self.into_inner() }
+        }
+    }
+}
+
+#[rustfmt::skip]
+hash_newtype!(LegacySighash, sha256d::Hash, 32,
+    doc="Hash of a transaction according to the legacy signature algorithm", false);
+impl_thirty_two_byte_hash!(LegacySighash);
+
+#[rustfmt::skip]
+hash_newtype!(SegwitV0Sighash, sha256d::Hash, 32,
+    doc="Hash of a transaction according to the segwit version 0 signature algorithm", false);
+impl_thirty_two_byte_hash!(SegwitV0Sighash);
+
+#[rustfmt::skip]
+sha256t_hash_newtype!(TapSighash, TapSighashTag, MIDSTATE_TAPSIGHASH, 64,
+    doc="Taproot-tagged hash with tag \"TapSighash\".
+
+This hash type is used for computing taproot signature hash.", false
+);
+impl_thirty_two_byte_hash!(TapSighash);
+
 /// Efficiently calculates signature hash message for legacy, segwit and taproot inputs.
 #[derive(Debug)]
 pub struct SighashCache<T: Borrow<Transaction>> {
@@ -77,7 +109,7 @@ struct TaprootCache {
     script_pubkeys: sha256::Hash,
 }
 
-/// Contains outputs of previous transactions. In the case [`SchnorrSighashType`] variant is
+/// Contains outputs of previous transactions. In the case [`TapSighashType`] variant is
 /// `SIGHASH_ANYONECANPAY`, [`Prevouts::One`] may be used.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub enum Prevouts<'u, T>
@@ -107,8 +139,8 @@ pub struct ScriptPath<'s> {
 /// Hashtype of an input's signature, encoded in the last byte of the signature.
 /// Fixed values so they can be cast as integer types for encoding.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub enum SchnorrSighashType {
-    /// 0x0: Used when not explicitly specified, defaults to [`SchnorrSighashType::All`]
+pub enum TapSighashType {
+    /// 0x0: Used when not explicitly specified, defaults to [`TapSighashType::All`]
     Default = 0x00,
     /// 0x1: Sign all outputs.
     All = 0x01,
@@ -127,35 +159,39 @@ pub enum SchnorrSighashType {
     SinglePlusAnyoneCanPay = 0x83,
 }
 #[cfg(feature = "serde")]
-crate::serde_utils::serde_string_impl!(SchnorrSighashType, "a SchnorrSighashType data");
+crate::serde_utils::serde_string_impl!(TapSighashType, "a TapSighashType data");
 
-impl fmt::Display for SchnorrSighashType {
+impl fmt::Display for TapSighashType {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use TapSighashType::*;
+
         let s = match self {
-            SchnorrSighashType::Default => "SIGHASH_DEFAULT",
-            SchnorrSighashType::All => "SIGHASH_ALL",
-            SchnorrSighashType::None => "SIGHASH_NONE",
-            SchnorrSighashType::Single => "SIGHASH_SINGLE",
-            SchnorrSighashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
-            SchnorrSighashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
-            SchnorrSighashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
+            Default => "SIGHASH_DEFAULT",
+            All => "SIGHASH_ALL",
+            None => "SIGHASH_NONE",
+            Single => "SIGHASH_SINGLE",
+            AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
+            NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
+            SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
         };
         f.write_str(s)
     }
 }
 
-impl str::FromStr for SchnorrSighashType {
+impl str::FromStr for TapSighashType {
     type Err = SighashTypeParseError;
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
+        use TapSighashType::*;
+
         match s {
-            "SIGHASH_DEFAULT" => Ok(SchnorrSighashType::Default),
-            "SIGHASH_ALL" => Ok(SchnorrSighashType::All),
-            "SIGHASH_NONE" => Ok(SchnorrSighashType::None),
-            "SIGHASH_SINGLE" => Ok(SchnorrSighashType::Single),
-            "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::AllPlusAnyoneCanPay),
-            "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::NonePlusAnyoneCanPay),
-            "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SchnorrSighashType::SinglePlusAnyoneCanPay),
+            "SIGHASH_DEFAULT" => Ok(Default),
+            "SIGHASH_ALL" => Ok(All),
+            "SIGHASH_NONE" => Ok(None),
+            "SIGHASH_SINGLE" => Ok(Single),
+            "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(AllPlusAnyoneCanPay),
+            "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(NonePlusAnyoneCanPay),
+            "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SinglePlusAnyoneCanPay),
             _ => Err(SighashTypeParseError { unrecognized: s.to_owned() }),
         }
     }
@@ -207,15 +243,17 @@ pub enum Error {
 
 impl fmt::Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use Error::*;
+
         match self {
-            Error::Io(error_kind) => write!(f, "writer errored: {:?}", error_kind),
-            Error::IndexOutOfInputsBounds { index, inputs_size } => write!(f, "Requested index ({}) is greater or equal than the number of transaction inputs ({})", index, inputs_size),
-            Error::SingleWithoutCorrespondingOutput { index, outputs_size } => write!(f, "SIGHASH_SINGLE for input ({}) haven't a corresponding output (#outputs:{})", index, outputs_size),
-            Error::PrevoutsSize => write!(f, "Number of supplied prevouts differs from the number of inputs in transaction"),
-            Error::PrevoutIndex => write!(f, "The index requested is greater than available prevouts or different from the provided [Provided::Anyone] index"),
-            Error::PrevoutKind => write!(f, "A single prevout has been provided but all prevouts are needed without `ANYONECANPAY`"),
-            Error::WrongAnnex => write!(f, "Annex must be at least one byte long and the first bytes must be `0x50`"),
-            Error::InvalidSighashType(hash_ty) => write!(f, "Invalid schnorr Signature hash type : {} ", hash_ty),
+            Io(error_kind) => write!(f, "writer errored: {:?}", error_kind),
+            IndexOutOfInputsBounds { index, inputs_size } => write!(f, "Requested index ({}) is greater or equal than the number of transaction inputs ({})", index, inputs_size),
+            SingleWithoutCorrespondingOutput { index, outputs_size } => write!(f, "SIGHASH_SINGLE for input ({}) haven't a corresponding output (#outputs:{})", index, outputs_size),
+            PrevoutsSize => write!(f, "Number of supplied prevouts differs from the number of inputs in transaction"),
+            PrevoutIndex => write!(f, "The index requested is greater than available prevouts or different from the provided [Provided::Anyone] index"),
+            PrevoutKind => write!(f, "A single prevout has been provided but all prevouts are needed without `ANYONECANPAY`"),
+            WrongAnnex => write!(f, "Annex must be at least one byte long and the first bytes must be `0x50`"),
+            InvalidSighashType(hash_ty) => write!(f, "Invalid taproot signature hash type : {} ", hash_ty),
         }
     }
 }
@@ -224,7 +262,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
 impl std::error::Error for Error {
     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
-        use self::Error::*;
+        use Error::*;
 
         match self {
             Io(_)
@@ -301,7 +339,7 @@ fn from(script_path: ScriptPath<'s>) -> TapLeafHash { script_path.leaf_hash() }
 /// Hashtype of an input's signature, encoded in the last byte of the signature.
 ///
 /// Fixed values so they can be cast as integer types for encoding (see also
-/// [`SchnorrSighashType`]).
+/// [`TapSighashType`]).
 #[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)]
 pub enum EcdsaSighashType {
     /// 0x1: Sign all outputs.
@@ -325,13 +363,15 @@ pub enum EcdsaSighashType {
 
 impl fmt::Display for EcdsaSighashType {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use EcdsaSighashType::*;
+
         let s = match self {
-            EcdsaSighashType::All => "SIGHASH_ALL",
-            EcdsaSighashType::None => "SIGHASH_NONE",
-            EcdsaSighashType::Single => "SIGHASH_SINGLE",
-            EcdsaSighashType::AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
-            EcdsaSighashType::NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
-            EcdsaSighashType::SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
+            All => "SIGHASH_ALL",
+            None => "SIGHASH_NONE",
+            Single => "SIGHASH_SINGLE",
+            AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY",
+            NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY",
+            SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY",
         };
         f.write_str(s)
     }
@@ -341,13 +381,15 @@ impl str::FromStr for EcdsaSighashType {
     type Err = SighashTypeParseError;
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
+        use EcdsaSighashType::*;
+
         match s {
-            "SIGHASH_ALL" => Ok(EcdsaSighashType::All),
-            "SIGHASH_NONE" => Ok(EcdsaSighashType::None),
-            "SIGHASH_SINGLE" => Ok(EcdsaSighashType::Single),
-            "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
-            "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
-            "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay),
+            "SIGHASH_ALL" => Ok(All),
+            "SIGHASH_NONE" => Ok(None),
+            "SIGHASH_SINGLE" => Ok(Single),
+            "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(AllPlusAnyoneCanPay),
+            "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(NonePlusAnyoneCanPay),
+            "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SinglePlusAnyoneCanPay),
             _ => Err(SighashTypeParseError { unrecognized: s.to_owned() }),
         }
     }
@@ -356,13 +398,15 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
 impl EcdsaSighashType {
     /// Splits the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean.
     pub(crate) fn split_anyonecanpay_flag(self) -> (EcdsaSighashType, bool) {
+        use EcdsaSighashType::*;
+
         match self {
-            EcdsaSighashType::All => (EcdsaSighashType::All, false),
-            EcdsaSighashType::None => (EcdsaSighashType::None, false),
-            EcdsaSighashType::Single => (EcdsaSighashType::Single, false),
-            EcdsaSighashType::AllPlusAnyoneCanPay => (EcdsaSighashType::All, true),
-            EcdsaSighashType::NonePlusAnyoneCanPay => (EcdsaSighashType::None, true),
-            EcdsaSighashType::SinglePlusAnyoneCanPay => (EcdsaSighashType::Single, true),
+            All => (All, false),
+            None => (None, false),
+            Single => (Single, false),
+            AllPlusAnyoneCanPay => (All, true),
+            NonePlusAnyoneCanPay => (None, true),
+            SinglePlusAnyoneCanPay => (Single, true),
         }
     }
 
@@ -376,6 +420,8 @@ pub(crate) fn split_anyonecanpay_flag(self) -> (EcdsaSighashType, bool) {
     /// verifying signatures, the user should retain the `n` and use it compute the signature hash
     /// message.
     pub fn from_consensus(n: u32) -> EcdsaSighashType {
+        use EcdsaSighashType::*;
+
         // In Bitcoin Core, the SignatureHash function will mask the (int32) value with
         // 0x1f to (apparently) deactivate ACP when checking for SINGLE and NONE bits.
         // We however want to be matching also against on ACP-masked ALL, SINGLE, and NONE.
@@ -383,15 +429,15 @@ pub fn from_consensus(n: u32) -> EcdsaSighashType {
         let mask = 0x1f | 0x80;
         match n & mask {
             // "real" sighashes
-            0x01 => EcdsaSighashType::All,
-            0x02 => EcdsaSighashType::None,
-            0x03 => EcdsaSighashType::Single,
-            0x81 => EcdsaSighashType::AllPlusAnyoneCanPay,
-            0x82 => EcdsaSighashType::NonePlusAnyoneCanPay,
-            0x83 => EcdsaSighashType::SinglePlusAnyoneCanPay,
+            0x01 => All,
+            0x02 => None,
+            0x03 => Single,
+            0x81 => AllPlusAnyoneCanPay,
+            0x82 => NonePlusAnyoneCanPay,
+            0x83 => SinglePlusAnyoneCanPay,
             // catchalls
-            x if x & 0x80 == 0x80 => EcdsaSighashType::AllPlusAnyoneCanPay,
-            _ => EcdsaSighashType::All,
+            x if x & 0x80 == 0x80 => AllPlusAnyoneCanPay,
+            _ => All,
         }
     }
 
@@ -401,14 +447,16 @@ pub fn from_consensus(n: u32) -> EcdsaSighashType {
     ///
     /// If `n` is a non-standard sighash value.
     pub fn from_standard(n: u32) -> Result<EcdsaSighashType, NonStandardSighashType> {
+        use EcdsaSighashType::*;
+
         match n {
             // Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198
-            0x01 => Ok(EcdsaSighashType::All),
-            0x02 => Ok(EcdsaSighashType::None),
-            0x03 => Ok(EcdsaSighashType::Single),
-            0x81 => Ok(EcdsaSighashType::AllPlusAnyoneCanPay),
-            0x82 => Ok(EcdsaSighashType::NonePlusAnyoneCanPay),
-            0x83 => Ok(EcdsaSighashType::SinglePlusAnyoneCanPay),
+            0x01 => Ok(All),
+            0x02 => Ok(None),
+            0x03 => Ok(Single),
+            0x81 => Ok(AllPlusAnyoneCanPay),
+            0x82 => Ok(NonePlusAnyoneCanPay),
+            0x83 => Ok(SinglePlusAnyoneCanPay),
             non_standard => Err(NonStandardSighashType(non_standard)),
         }
     }
@@ -419,36 +467,40 @@ pub fn from_standard(n: u32) -> Result<EcdsaSighashType, NonStandardSighashType>
     pub fn to_u32(self) -> u32 { self as u32 }
 }
 
-impl From<EcdsaSighashType> for SchnorrSighashType {
+impl From<EcdsaSighashType> for TapSighashType {
     fn from(s: EcdsaSighashType) -> Self {
+        use TapSighashType::*;
+
         match s {
-            EcdsaSighashType::All => SchnorrSighashType::All,
-            EcdsaSighashType::None => SchnorrSighashType::None,
-            EcdsaSighashType::Single => SchnorrSighashType::Single,
-            EcdsaSighashType::AllPlusAnyoneCanPay => SchnorrSighashType::AllPlusAnyoneCanPay,
-            EcdsaSighashType::NonePlusAnyoneCanPay => SchnorrSighashType::NonePlusAnyoneCanPay,
-            EcdsaSighashType::SinglePlusAnyoneCanPay => SchnorrSighashType::SinglePlusAnyoneCanPay,
+            EcdsaSighashType::All => All,
+            EcdsaSighashType::None => None,
+            EcdsaSighashType::Single => Single,
+            EcdsaSighashType::AllPlusAnyoneCanPay => AllPlusAnyoneCanPay,
+            EcdsaSighashType::NonePlusAnyoneCanPay => NonePlusAnyoneCanPay,
+            EcdsaSighashType::SinglePlusAnyoneCanPay => SinglePlusAnyoneCanPay,
         }
     }
 }
 
-impl SchnorrSighashType {
+impl TapSighashType {
     /// Breaks the sighash flag into the "real" sighash flag and the `SIGHASH_ANYONECANPAY` boolean.
-    pub(crate) fn split_anyonecanpay_flag(self) -> (SchnorrSighashType, bool) {
+    pub(crate) fn split_anyonecanpay_flag(self) -> (TapSighashType, bool) {
+        use TapSighashType::*;
+
         match self {
-            SchnorrSighashType::Default => (SchnorrSighashType::Default, false),
-            SchnorrSighashType::All => (SchnorrSighashType::All, false),
-            SchnorrSighashType::None => (SchnorrSighashType::None, false),
-            SchnorrSighashType::Single => (SchnorrSighashType::Single, false),
-            SchnorrSighashType::AllPlusAnyoneCanPay => (SchnorrSighashType::All, true),
-            SchnorrSighashType::NonePlusAnyoneCanPay => (SchnorrSighashType::None, true),
-            SchnorrSighashType::SinglePlusAnyoneCanPay => (SchnorrSighashType::Single, true),
+            Default => (Default, false),
+            All => (All, false),
+            None => (None, false),
+            Single => (Single, false),
+            AllPlusAnyoneCanPay => (All, true),
+            NonePlusAnyoneCanPay => (None, true),
+            SinglePlusAnyoneCanPay => (Single, true),
         }
     }
 
-    /// Constructs a [`SchnorrSighashType`] from a raw `u8`.
+    /// Constructs a [`TapSighashType`] from a raw `u8`.
     pub fn from_consensus_u8(hash_ty: u8) -> Result<Self, Error> {
-        use SchnorrSighashType::*;
+        use TapSighashType::*;
 
         Ok(match hash_ty {
             0x00 => Default,
@@ -522,7 +574,7 @@ pub fn taproot_encode_signing_data_to<Write: io::Write, T: Borrow<TxOut>>(
         prevouts: &Prevouts<T>,
         annex: Option<Annex>,
         leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
-        sighash_type: SchnorrSighashType,
+        sighash_type: TapSighashType,
     ) -> Result<(), Error> {
         prevouts.check_all(self.tx.borrow())?;
 
@@ -556,7 +608,7 @@ pub fn taproot_encode_signing_data_to<Write: io::Write, T: Borrow<TxOut>>(
 
         // If hash_type & 3 does not equal SIGHASH_NONE or SIGHASH_SINGLE:
         //     sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format.
-        if sighash != SchnorrSighashType::None && sighash != SchnorrSighashType::Single {
+        if sighash != TapSighashType::None && sighash != TapSighashType::Single {
             self.common_cache().outputs.consensus_encode(&mut writer)?;
         }
 
@@ -604,7 +656,7 @@ pub fn taproot_encode_signing_data_to<Write: io::Write, T: Borrow<TxOut>>(
         // * Data about this output:
         // If hash_type & 3 equals SIGHASH_SINGLE:
         //      sha_single_output (32): the SHA256 of the corresponding output in CTxOut format.
-        if sighash == SchnorrSighashType::Single {
+        if sighash == TapSighashType::Single {
             let mut enc = sha256::Hash::engine();
             self.tx
                 .borrow()
@@ -639,9 +691,9 @@ pub fn taproot_signature_hash<T: Borrow<TxOut>>(
         prevouts: &Prevouts<T>,
         annex: Option<Annex>,
         leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
-        sighash_type: SchnorrSighashType,
-    ) -> Result<TapSighashHash, Error> {
-        let mut enc = TapSighashHash::engine();
+        sighash_type: TapSighashType,
+    ) -> Result<TapSighash, Error> {
+        let mut enc = TapSighash::engine();
         self.taproot_encode_signing_data_to(
             &mut enc,
             input_index,
@@ -650,7 +702,7 @@ pub fn taproot_signature_hash<T: Borrow<TxOut>>(
             leaf_hash_code_separator,
             sighash_type,
         )?;
-        Ok(TapSighashHash::from_engine(enc))
+        Ok(TapSighash::from_engine(enc))
     }
 
     /// Computes the BIP341 sighash for a key spend.
@@ -658,9 +710,9 @@ pub fn taproot_key_spend_signature_hash<T: Borrow<TxOut>>(
         &mut self,
         input_index: usize,
         prevouts: &Prevouts<T>,
-        sighash_type: SchnorrSighashType,
-    ) -> Result<TapSighashHash, Error> {
-        let mut enc = TapSighashHash::engine();
+        sighash_type: TapSighashType,
+    ) -> Result<TapSighash, Error> {
+        let mut enc = TapSighash::engine();
         self.taproot_encode_signing_data_to(
             &mut enc,
             input_index,
@@ -669,7 +721,7 @@ pub fn taproot_key_spend_signature_hash<T: Borrow<TxOut>>(
             None,
             sighash_type,
         )?;
-        Ok(TapSighashHash::from_engine(enc))
+        Ok(TapSighash::from_engine(enc))
     }
 
     /// Computes the BIP341 sighash for a script spend.
@@ -681,9 +733,9 @@ pub fn taproot_script_spend_signature_hash<S: Into<TapLeafHash>, T: Borrow<TxOut
         input_index: usize,
         prevouts: &Prevouts<T>,
         leaf_hash: S,
-        sighash_type: SchnorrSighashType,
-    ) -> Result<TapSighashHash, Error> {
-        let mut enc = TapSighashHash::engine();
+        sighash_type: TapSighashType,
+    ) -> Result<TapSighash, Error> {
+        let mut enc = TapSighash::engine();
         self.taproot_encode_signing_data_to(
             &mut enc,
             input_index,
@@ -692,7 +744,7 @@ pub fn taproot_script_spend_signature_hash<S: Into<TapLeafHash>, T: Borrow<TxOut
             Some((leaf_hash.into(), 0xFFFFFFFF)),
             sighash_type,
         )?;
-        Ok(TapSighashHash::from_engine(enc))
+        Ok(TapSighash::from_engine(enc))
     }
 
     /// Encodes the BIP143 signing data for any flag type into a given object implementing a
@@ -741,9 +793,9 @@ pub fn segwit_encode_signing_data_to<Write: io::Write>(
         if sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None {
             self.segwit_cache().outputs.consensus_encode(&mut writer)?;
         } else if sighash == EcdsaSighashType::Single && input_index < self.tx.borrow().output.len() {
-            let mut single_enc = Sighash::engine();
+            let mut single_enc = LegacySighash::engine();
             self.tx.borrow().output[input_index].consensus_encode(&mut single_enc)?;
-            let hash = Sighash::from_engine(single_enc);
+            let hash = LegacySighash::from_engine(single_enc);
             writer.write_all(&hash[..])?;
         } else {
             writer.write_all(&zero_hash[..])?;
@@ -761,8 +813,8 @@ pub fn segwit_signature_hash(
         script_code: &Script,
         value: u64,
         sighash_type: EcdsaSighashType,
-    ) -> Result<Sighash, Error> {
-        let mut enc = Sighash::engine();
+    ) -> Result<SegwitV0Sighash, Error> {
+        let mut enc = SegwitV0Sighash::engine();
         self.segwit_encode_signing_data_to(
             &mut enc,
             input_index,
@@ -770,7 +822,7 @@ pub fn segwit_signature_hash(
             value,
             sighash_type,
         )?;
-        Ok(Sighash::from_engine(enc))
+        Ok(SegwitV0Sighash::from_engine(enc))
     }
 
     /// Encodes the legacy signing data from which a signature hash for a given input index with a
@@ -930,15 +982,15 @@ pub fn legacy_signature_hash(
         input_index: usize,
         script_pubkey: &Script,
         sighash_type: u32,
-    ) -> Result<Sighash, Error> {
-        let mut enc = Sighash::engine();
+    ) -> Result<LegacySighash, Error> {
+        let mut enc = LegacySighash::engine();
         if self
             .legacy_encode_signing_data_to(&mut enc, input_index, script_pubkey, sighash_type)
             .is_sighash_single_bug()?
         {
-            Ok(Sighash::from_inner(UINT256_ONE))
+            Ok(LegacySighash::from_inner(UINT256_ONE))
         } else {
-            Ok(Sighash::from_engine(enc))
+            Ok(LegacySighash::from_engine(enc))
         }
     }
 
@@ -1068,12 +1120,12 @@ mod tests {
     use crate::blockdata::locktime::absolute;
     use crate::consensus::deserialize;
     use crate::crypto::key::PublicKey;
-    use crate::hash_types::Sighash;
+    use crate::crypto::sighash::{LegacySighash, TapSighash};
     use crate::hashes::hex::FromHex;
-    use crate::hashes::{Hash, HashEngine};
+    use crate::hashes::HashEngine;
     use crate::internal_macros::hex;
     use crate::network::constants::Network;
-    use crate::taproot::{TapLeafHash, TapSighashHash};
+    use crate::taproot::TapLeafHash;
 
     extern crate serde_json;
 
@@ -1092,7 +1144,7 @@ fn sighash_single_bug() {
         let cache = SighashCache::new(&tx);
 
         let got = cache.legacy_signature_hash(1, &script, SIGHASH_SINGLE).expect("sighash");
-        let want = Sighash::from_slice(&UINT256_ONE).unwrap();
+        let want = LegacySighash::from_slice(&UINT256_ONE).unwrap();
 
         assert_eq!(got, want)
     }
@@ -1115,7 +1167,7 @@ fn run_test_sighash(
             let script = ScriptBuf::from(Vec::from_hex(script).unwrap());
             let mut raw_expected = Vec::from_hex(expected_result).unwrap();
             raw_expected.reverse();
-            let want = Sighash::from_slice(&raw_expected[..]).unwrap();
+            let want = LegacySighash::from_slice(&raw_expected[..]).unwrap();
 
             let cache = SighashCache::new(&tx);
             let got = cache.legacy_signature_hash(input_index, &script, hash_type as u32).unwrap();
@@ -1126,7 +1178,7 @@ fn run_test_sighash(
         // These test vectors were stolen from libbtc, which is Copyright 2014 Jonas Schnelli MIT
         // They were transformed by replacing {...} with run_test_sighash(...), then the ones containing
         // OP_CODESEPARATOR in their pubkeys were removed
-        let data = include_str!("../tests/data/legacy_sighash.json");
+        let data = include_str!("../../tests/data/legacy_sighash.json");
 
         let testdata = serde_json::from_str::<Value>(data).unwrap().as_array().unwrap().clone();
         for t in testdata.iter().skip(1) {
@@ -1144,9 +1196,9 @@ fn test_tap_sighash_hash() {
         let bytes = hex!("00011b96877db45ffa23b307e9f0ac87b80ef9a80b4c5f0db3fbe734422453e83cc5576f3d542c5d4898fb2b696c15d43332534a7c1d1255fda38993545882df92c3e353ff6d36fbfadc4d168452afd8467f02fe53d71714fcea5dfe2ea759bd00185c4cb02bc76d42620393ca358a1a713f4997f9fc222911890afb3fe56c6a19b202df7bffdcfad08003821294279043746631b00e2dc5e52a111e213bbfe6ef09a19428d418dab0d50000000000");
         let expected =
             hex!("04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0");
-        let mut enc = TapSighashHash::engine();
+        let mut enc = TapSighash::engine();
         enc.input(&bytes);
-        let hash = TapSighashHash::from_engine(enc);
+        let hash = TapSighash::from_engine(enc);
         assert_eq!(expected, hash.into_inner());
     }
 
@@ -1159,7 +1211,7 @@ fn test_sighashes_keyspending() {
             "01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500",
             0,
             "33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703",
-            SchnorrSighashType::Default, None, None, None
+            TapSighashType::Default, None, None, None
         );
 
         test_taproot_sighash(
@@ -1167,7 +1219,7 @@ fn test_sighashes_keyspending() {
             "02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece",
             1,
             "626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8",
-            SchnorrSighashType::All, None, None, None
+            TapSighashType::All, None, None, None
         );
 
         test_taproot_sighash(
@@ -1175,7 +1227,7 @@ fn test_sighashes_keyspending() {
             "01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c",
             0,
             "dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c",
-            SchnorrSighashType::AllPlusAnyoneCanPay, None, None, None
+            TapSighashType::AllPlusAnyoneCanPay, None, None, None
         );
 
         test_taproot_sighash(
@@ -1183,7 +1235,7 @@ fn test_sighashes_keyspending() {
             "0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621",
             0,
             "3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067",
-            SchnorrSighashType::None, None, None, None
+            TapSighashType::None, None, None, None
         );
 
         test_taproot_sighash(
@@ -1191,7 +1243,7 @@ fn test_sighashes_keyspending() {
             "013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55",
             0,
             "2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae",
-            SchnorrSighashType::NonePlusAnyoneCanPay, None, None, None
+            TapSighashType::NonePlusAnyoneCanPay, None, None, None
         );
 
         test_taproot_sighash(
@@ -1199,7 +1251,7 @@ fn test_sighashes_keyspending() {
             "01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80",
             0,
             "30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88",
-            SchnorrSighashType::Single, None, None, None
+            TapSighashType::Single, None, None, None
         );
 
         test_taproot_sighash(
@@ -1207,7 +1259,7 @@ fn test_sighashes_keyspending() {
             "0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69",
             0,
             "bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df",
-            SchnorrSighashType::SinglePlusAnyoneCanPay, None, None, None
+            TapSighashType::SinglePlusAnyoneCanPay, None, None, None
         );
     }
 
@@ -1218,7 +1270,7 @@ fn test_sighashes_with_annex() {
             "01ea49260000000000225120ab5e9800806bf18cb246edcf5fe63441208fe955a4b5a35bbff65f5db622a010",
             0,
             "3b003000add359a364a156e73e02846782a59d0d95ca8c4638aaad99f2ef915c",
-            SchnorrSighashType::SinglePlusAnyoneCanPay,
+            TapSighashType::SinglePlusAnyoneCanPay,
             Some("507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e"),
             None,
             None,
@@ -1232,7 +1284,7 @@ fn test_sighashes_with_script_path() {
             "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182",
             0,
             "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e",
-            SchnorrSighashType::All,
+            TapSighashType::All,
             None,
             Some("20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab"),
             None,
@@ -1246,7 +1298,7 @@ fn test_sighashes_with_script_path_raw_hash() {
             "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182",
             0,
             "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e",
-            SchnorrSighashType::All,
+            TapSighashType::All,
             None,
             None,
             Some("15a2530514e399f8b5cf0b3d3112cf5b289eaa3e308ba2071b58392fdc6da68a"),
@@ -1260,7 +1312,7 @@ fn test_sighashes_with_annex_and_script() {
             "011458360000000000225120a7baec3fb9f84614e3899fcc010c638f80f13539344120e1f4d8b68a9a011a13",
             0,
             "a0042aa434f9a75904b64043f2a283f8b4c143c7f4f7f49a6cbe5b9f745f4c15",
-            SchnorrSighashType::All,
+            TapSighashType::All,
             Some("50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1"),
             Some("7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac"),
             None,
@@ -1282,27 +1334,27 @@ fn test_sighash_errors() {
         let empty_vec = vec![];
         let empty_prevouts : Prevouts<TxOut> = Prevouts::All(&empty_vec);
         assert_eq!(
-            c.taproot_signature_hash(0, &empty_prevouts, None, None, SchnorrSighashType::All),
+            c.taproot_signature_hash(0, &empty_prevouts, None, None, TapSighashType::All),
             Err(Error::PrevoutsSize)
         );
         let two = vec![TxOut::default(), TxOut::default()];
         let too_many_prevouts = Prevouts::All(&two);
         assert_eq!(
-            c.taproot_signature_hash(0, &too_many_prevouts, None, None, SchnorrSighashType::All),
+            c.taproot_signature_hash(0, &too_many_prevouts, None, None, TapSighashType::All),
             Err(Error::PrevoutsSize)
         );
         let tx_out = TxOut::default();
         let prevout = Prevouts::One(1, &tx_out);
         assert_eq!(
-            c.taproot_signature_hash(0, &prevout, None, None, SchnorrSighashType::All),
+            c.taproot_signature_hash(0, &prevout, None, None, TapSighashType::All),
             Err(Error::PrevoutKind)
         );
         assert_eq!(
-            c.taproot_signature_hash(0, &prevout, None, None, SchnorrSighashType::AllPlusAnyoneCanPay),
+            c.taproot_signature_hash(0, &prevout, None, None, TapSighashType::AllPlusAnyoneCanPay),
             Err(Error::PrevoutIndex)
         );
         assert_eq!(
-            c.taproot_signature_hash(10, &prevout, None, None, SchnorrSighashType::AllPlusAnyoneCanPay),
+            c.taproot_signature_hash(10, &prevout, None, None, TapSighashType::AllPlusAnyoneCanPay),
             Err(Error::IndexOutOfInputsBounds {
                 index: 10,
                 inputs_size: 1
@@ -1310,7 +1362,7 @@ fn test_sighash_errors() {
         );
         let prevout = Prevouts::One(0, &tx_out);
         assert_eq!(
-            c.taproot_signature_hash(0, &prevout, None, None, SchnorrSighashType::SinglePlusAnyoneCanPay),
+            c.taproot_signature_hash(0, &prevout, None, None, TapSighashType::SinglePlusAnyoneCanPay),
             Err(Error::SingleWithoutCorrespondingOutput {
                 index: 0,
                 outputs_size: 0
@@ -1338,7 +1390,7 @@ fn test_taproot_sighash(
         prevout_hex: &str,
         input_index: usize,
         expected_hash: &str,
-        sighash_type: SchnorrSighashType,
+        sighash_type: TapSighashType,
         annex_hex: Option<&str>,
         script_hex: Option<&str>,
         script_leaf_hash: Option<&str>,
@@ -1387,14 +1439,14 @@ fn test_taproot_sighash(
     #[cfg(feature = "serde")]
     #[test]
     fn bip_341_sighash_tests() {
-        fn sighash_deser_numeric<'de, D>(deserializer: D) -> Result<SchnorrSighashType, D::Error>
+        fn sighash_deser_numeric<'de, D>(deserializer: D) -> Result<TapSighashType, D::Error>
         where
             D: actual_serde::Deserializer<'de>,
         {
             use actual_serde::de::{Deserialize, Error, Unexpected};
 
             let raw = u8::deserialize(deserializer)?;
-            SchnorrSighashType::from_consensus_u8(raw).map_err(|_| {
+            TapSighashType::from_consensus_u8(raw).map_err(|_| {
                 D::Error::invalid_value(
                     Unexpected::Unsigned(raw.into()),
                     &"number in range 0-3 or 0x81-0x83",
@@ -1444,7 +1496,7 @@ struct KpsInputSpendingGiven {
             internal_privkey: SecretKey,
             merkle_root: Option<TapNodeHash>,
             #[serde(deserialize_with = "sighash_deser_numeric")]
-            hash_type: SchnorrSighashType,
+            hash_type: TapSighashType,
         }
 
         #[derive(serde::Deserialize)]
@@ -1456,7 +1508,7 @@ struct KpsInputSpendingIntermediary {
             tweaked_privkey: SecretKey,
             sig_msg: String,
             //precomputed_used: Vec<String>, // unused
-            sig_hash: TapSighashHash,
+            sig_hash: TapSighash,
         }
 
         #[derive(serde::Deserialize)]
@@ -1494,7 +1546,7 @@ struct TestData {
             //script_pubkey: Vec<ScriptPubKey>, // unused
         }
 
-        let json_str = include_str!("../tests/data/bip341_tests.json");
+        let json_str = include_str!("../../tests/data/bip341_tests.json");
         let mut data =
             serde_json::from_str::<TestData>(json_str).expect("JSON was not well-formatted");
 
@@ -1532,11 +1584,11 @@ struct TestData {
             let (expected_key_spend_sig, expected_hash_ty) = if sig_str.len() == 128 {
                 (
                     secp256k1::schnorr::Signature::from_str(&sig_str).unwrap(),
-                    SchnorrSighashType::Default,
+                    TapSighashType::Default,
                 )
             } else {
                 let hash_ty = u8::from_str_radix(&sig_str[128..130], 16).unwrap();
-                let hash_ty = SchnorrSighashType::from_consensus_u8(hash_ty).unwrap();
+                let hash_ty = TapSighashType::from_consensus_u8(hash_ty).unwrap();
                 (secp256k1::schnorr::Signature::from_str(&sig_str[..128]).unwrap(), hash_ty)
             };
 
@@ -1578,17 +1630,17 @@ struct TestData {
     #[test]
     fn sighashtype_fromstr_display() {
         let sighashtypes = vec![
-            ("SIGHASH_DEFAULT", SchnorrSighashType::Default),
-            ("SIGHASH_ALL", SchnorrSighashType::All),
-            ("SIGHASH_NONE", SchnorrSighashType::None),
-            ("SIGHASH_SINGLE", SchnorrSighashType::Single),
-            ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", SchnorrSighashType::AllPlusAnyoneCanPay),
-            ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", SchnorrSighashType::NonePlusAnyoneCanPay),
-            ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", SchnorrSighashType::SinglePlusAnyoneCanPay),
+            ("SIGHASH_DEFAULT", TapSighashType::Default),
+            ("SIGHASH_ALL", TapSighashType::All),
+            ("SIGHASH_NONE", TapSighashType::None),
+            ("SIGHASH_SINGLE", TapSighashType::Single),
+            ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", TapSighashType::AllPlusAnyoneCanPay),
+            ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", TapSighashType::NonePlusAnyoneCanPay),
+            ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", TapSighashType::SinglePlusAnyoneCanPay),
         ];
         for (s, sht) in sighashtypes {
             assert_eq!(sht.to_string(), s);
-            assert_eq!(SchnorrSighashType::from_str(s).unwrap(), sht);
+            assert_eq!(TapSighashType::from_str(s).unwrap(), sht);
         }
         let sht_mistakes = vec![
             "SIGHASH_ALL | SIGHASH_ANYONECANPAY",
@@ -1606,7 +1658,7 @@ fn sighashtype_fromstr_display() {
         ];
         for s in sht_mistakes {
             assert_eq!(
-                SchnorrSighashType::from_str(s).unwrap_err().to_string(),
+                TapSighashType::from_str(s).unwrap_err().to_string(),
                 format!("Unrecognized SIGHASH string '{}'", s)
             );
         }
@@ -1635,7 +1687,7 @@ fn bip143_p2wpkh() {
         let mut cache = SighashCache::new(&tx);
         assert_eq!(
             cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(),
-            "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670".parse::<Sighash>().unwrap(),
+            "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670".parse::<SegwitV0Sighash>().unwrap(),
         );
 
         let cache = cache.segwit_cache();
@@ -1671,7 +1723,7 @@ fn bip143_p2wpkh_nested_in_p2sh() {
         let mut cache = SighashCache::new(&tx);
         assert_eq!(
             cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
-            "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6".parse::<Sighash>().unwrap(),
+            "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6".parse::<SegwitV0Sighash>().unwrap(),
         );
 
         let cache = cache.segwit_cache();
@@ -1712,7 +1764,7 @@ fn bip143_p2wsh_nested_in_p2sh() {
         let mut cache = SighashCache::new(&tx);
         assert_eq!(
             cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
-            "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c".parse::<Sighash>().unwrap(),
+            "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c".parse::<SegwitV0Sighash>().unwrap(),
         );
 
         let cache = cache.segwit_cache();
diff --git a/bitcoin/src/crypto/taproot.rs b/bitcoin/src/crypto/taproot.rs
new file mode 100644
index 00000000..93f62ef5
--- /dev/null
+++ b/bitcoin/src/crypto/taproot.rs
@@ -0,0 +1,112 @@
+// Written in 2014 by Andrew Poelstra <apoelstra@wpsoftware.net>
+// SPDX-License-Identifier: CC0-1.0
+
+//! Bitcoin taproot keys.
+//!
+//! This module provides taproot keys used in Bitcoin (including reexporting secp256k1 keys).
+//!
+
+use core::fmt;
+
+use bitcoin_internals::write_err;
+
+pub use secp256k1::{self, constants, Secp256k1, KeyPair, XOnlyPublicKey, Verification, Parity};
+
+use crate::prelude::*;
+
+use crate::sighash::TapSighashType;
+
+/// A BIP340-341 serialized taproot signature with the corresponding hash type.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
+pub struct Signature {
+    /// The underlying schnorr signature
+    pub sig: secp256k1::schnorr::Signature,
+    /// The corresponding hash type
+    pub hash_ty: TapSighashType,
+}
+
+impl Signature {
+    /// Deserialize from slice
+    pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
+        match sl.len() {
+            64 => {
+                // default type
+                let sig = secp256k1::schnorr::Signature::from_slice(sl)
+                    .map_err(Error::Secp256k1)?;
+                Ok(Signature { sig, hash_ty: TapSighashType::Default })
+            },
+            65 => {
+                let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65");
+                let hash_ty = TapSighashType::from_consensus_u8(*hash_ty)
+                    .map_err(|_| Error::InvalidSighashType(*hash_ty))?;
+                let sig = secp256k1::schnorr::Signature::from_slice(sig)
+                    .map_err(Error::Secp256k1)?;
+                Ok(Signature { sig, hash_ty })
+            }
+            len => {
+                Err(Error::InvalidSignatureSize(len))
+            }
+        }
+    }
+
+    /// Serialize Signature
+    pub fn to_vec(self) -> Vec<u8> {
+        // TODO: add support to serialize to a writer to SerializedSig
+        let mut ser_sig = self.sig.as_ref().to_vec();
+        if self.hash_ty == TapSighashType::Default {
+            // default sighash type, don't add extra sighash byte
+        } else {
+            ser_sig.push(self.hash_ty as u8);
+        }
+        ser_sig
+    }
+
+}
+
+/// A taproot sig related error.
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[non_exhaustive]
+pub enum Error {
+    /// Base58 encoding error
+    InvalidSighashType(u8),
+    /// Signature has valid size but does not parse correctly
+    Secp256k1(secp256k1::Error),
+    /// Invalid taproot signature size
+    InvalidSignatureSize(usize),
+}
+
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::InvalidSighashType(hash_ty) =>
+                write!(f, "invalid signature hash type {}", hash_ty),
+            Error::Secp256k1(ref e) =>
+                write_err!(f, "taproot signature has correct len but is malformed"; e),
+            Error::InvalidSignatureSize(sz) =>
+                write!(f, "invalid taproot signature size: {}", sz),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
+impl std::error::Error for Error {
+    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+        use self::Error::*;
+
+        match self {
+            Secp256k1(e) => Some(e),
+            InvalidSighashType(_) | InvalidSignatureSize(_) => None,
+        }
+    }
+}
+
+impl From<secp256k1::Error> for Error {
+
+    fn from(e: secp256k1::Error) -> Error {
+        Error::Secp256k1(e)
+    }
+}
diff --git a/bitcoin/src/hash_types.rs b/bitcoin/src/hash_types.rs
index 78c0342d..31b7cb84 100644
--- a/bitcoin/src/hash_types.rs
+++ b/bitcoin/src/hash_types.rs
@@ -66,13 +66,6 @@ mod newtypes {
 ");
     hash_newtype!(Wtxid, sha256d::Hash, 32, doc="A bitcoin witness transaction ID.");
     hash_newtype!(BlockHash, sha256d::Hash, 32, doc="A bitcoin block hash.");
-    hash_newtype!(Sighash, sha256d::Hash, 32, doc="Hash of the transaction according to the signature algorithm", false);
-    impl secp256k1::ThirtyTwoByteHash for Sighash {
-        fn into_32(self) -> [u8; 32] {
-            use hashes::Hash;
-            *self.as_inner()
-        }
-    }
 
     hash_newtype!(PubkeyHash, hash160::Hash, 20, doc="A hash of a public key.");
     hash_newtype!(ScriptHash, hash160::Hash, 20, doc="A hash of Bitcoin Script bytecode.");
diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs
index f94c0f15..309ae9e8 100644
--- a/bitcoin/src/lib.rs
+++ b/bitcoin/src/lib.rs
@@ -99,7 +99,6 @@
 pub mod policy;
 pub mod pow;
 pub mod psbt;
-pub mod sighash;
 pub mod sign_message;
 pub mod string;
 pub mod taproot;
@@ -128,7 +127,7 @@
 pub use crate::blockdata::{constants, opcodes};
 pub use crate::consensus::encode::VarInt;
 pub use crate::crypto::key::{self, PrivateKey, PublicKey};
-pub use crate::crypto::{ecdsa, schnorr};
+pub use crate::crypto::sighash;
 pub use crate::error::Error;
 pub use crate::hash_types::{Txid, Wtxid, BlockHash, PubkeyHash,  ScriptHash, WPubkeyHash, WScriptHash};
 pub use crate::merkle_tree::MerkleBlock;
diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs
index 47bd4df7..6968785e 100644
--- a/bitcoin/src/psbt/error.rs
+++ b/bitcoin/src/psbt/error.rs
@@ -87,13 +87,13 @@ pub enum Error {
     InvalidXOnlyPublicKey,
     /// Parsing error indicating invalid ECDSA signatures
     InvalidEcdsaSignature(crate::crypto::ecdsa::Error),
-    /// Parsing error indicating invalid Schnorr signatures
-    InvalidSchnorrSignature(crate::crypto::schnorr::Error),
+    /// Parsing error indicating invalid taproot signatures
+    InvalidTaprootSignature(crate::crypto::taproot::Error),
     /// Parsing error indicating invalid control block
     InvalidControlBlock,
     /// Parsing error indicating invalid leaf version
     InvalidLeafVersion,
-    /// Parsing error indicating a Taproot error
+    /// Parsing error indicating a taproot error
     Taproot(&'static str),
     /// Error related to an xpub key
     XPubKey(&'static str),
@@ -136,7 +136,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             Error::InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e),
             Error::InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"),
             Error::InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e),
-            Error::InvalidSchnorrSignature(ref e) => write_err!(f, "invalid Schnorr signature"; e),
+            Error::InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e),
             Error::InvalidControlBlock => f.write_str("invalid control block"),
             Error::InvalidLeafVersion => f.write_str("invalid leaf version"),
             Error::Taproot(s) => write!(f, "taproot error -  {}", s),
@@ -179,7 +179,7 @@ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
             | InvalidSecp256k1PublicKey(_)
             | InvalidXOnlyPublicKey
             | InvalidEcdsaSignature(_)
-            | InvalidSchnorrSignature(_)
+            | InvalidTaprootSignature(_)
             | InvalidControlBlock
             | InvalidLeafVersion
             | Taproot(_)
diff --git a/bitcoin/src/psbt/map/input.rs b/bitcoin/src/psbt/map/input.rs
index 8ae6e987..20882b07 100644
--- a/bitcoin/src/psbt/map/input.rs
+++ b/bitcoin/src/psbt/map/input.rs
@@ -11,14 +11,14 @@
 use crate::blockdata::script::ScriptBuf;
 use crate::blockdata::witness::Witness;
 use crate::blockdata::transaction::{Transaction, TxOut};
-use crate::crypto::{ecdsa, schnorr};
+use crate::crypto::{ecdsa, taproot};
 use crate::crypto::key::PublicKey;
 use crate::hashes::{self, hash160, ripemd160, sha256, sha256d};
 use crate::bip32::KeySource;
 use crate::psbt::map::Map;
 use crate::psbt::serialize::Deserialize;
 use crate::psbt::{self, error, raw, Error};
-use crate::sighash::{self, NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, SchnorrSighashType};
+use crate::sighash::{self, NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, TapSighashType};
 use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash};
 
 /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
@@ -47,9 +47,9 @@
 const PSBT_IN_HASH160: u8 = 0x0c;
 /// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d
 const PSBT_IN_HASH256: u8 = 0x0d;
-/// Type: Schnorr Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13
+/// Type: Taproot Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13
 const PSBT_IN_TAP_KEY_SIG: u8 = 0x13;
-/// Type: Schnorr Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14
+/// Type: Taproot Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14
 const PSBT_IN_TAP_SCRIPT_SIG: u8 = 0x14;
 /// Type: Taproot Leaf Script PSBT_IN_TAP_LEAF_SCRIPT = 0x14
 const PSBT_IN_TAP_LEAF_SCRIPT: u8 = 0x15;
@@ -109,11 +109,11 @@ pub struct Input {
     /// HAS256 hash to preimage map.
     #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))]
     pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
-    /// Serialized schnorr signature with sighash type for key spend.
-    pub tap_key_sig: Option<schnorr::Signature>,
+    /// Serialized taproot signature with sighash type for key spend.
+    pub tap_key_sig: Option<taproot::Signature>,
     /// Map of `<xonlypubkey>|<leafhash>` with signature.
     #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
-    pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), schnorr::Signature>,
+    pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), taproot::Signature>,
     /// Map of Control blocks to Script version pair.
     #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
     pub tap_scripts: BTreeMap<ControlBlock, (ScriptBuf, LeafVersion)>,
@@ -134,7 +134,7 @@ pub struct Input {
 
 
 /// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash
-/// type can be either [`EcdsaSighashType`] or [`SchnorrSighashType`] but it is not possible to know
+/// type can be either [`EcdsaSighashType`] or [`TapSighashType`] but it is not possible to know
 /// directly which signature hash type the user is dealing with. Therefore, the user is responsible
 /// for converting to/from [`PsbtSighashType`] from/to the desired signature hash type they need.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -146,9 +146,9 @@ pub struct PsbtSighashType {
 
 impl fmt::Display for PsbtSighashType {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.schnorr_hash_ty() {
+        match self.taproot_hash_ty() {
             Err(_) => write!(f, "{:#x}", self.inner),
-            Ok(schnorr_hash_ty) => fmt::Display::fmt(&schnorr_hash_ty, f),
+            Ok(taproot_hash_ty) => fmt::Display::fmt(&taproot_hash_ty, f),
         }
     }
 }
@@ -160,10 +160,10 @@ impl FromStr for PsbtSighashType {
     fn from_str(s: &str) -> Result<Self, Self::Err> {
         // We accept strings of form: "SIGHASH_ALL" etc.
         //
-        // NB: some of Schnorr sighash types are non-standard for pre-taproot
+        // NB: some of Taproot sighash types are non-standard for pre-taproot
         // inputs. We also do not support SIGHASH_RESERVED in verbatim form
         // ("0xFF" string should be used instead).
-        if let Ok(ty) = SchnorrSighashType::from_str(s) {
+        if let Ok(ty) = TapSighashType::from_str(s) {
             return Ok(ty.into());
         }
 
@@ -181,9 +181,9 @@ fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self {
     }
 }
 
-impl From<SchnorrSighashType> for PsbtSighashType {
-    fn from(schnorr_hash_ty: SchnorrSighashType) -> Self {
-        PsbtSighashType { inner: schnorr_hash_ty as u32 }
+impl From<TapSighashType> for PsbtSighashType {
+    fn from(taproot_hash_ty: TapSighashType) -> Self {
+        PsbtSighashType { inner: taproot_hash_ty as u32 }
     }
 }
 
@@ -194,20 +194,20 @@ pub fn ecdsa_hash_ty(self) -> Result<EcdsaSighashType, NonStandardSighashType> {
         EcdsaSighashType::from_standard(self.inner)
     }
 
-    /// Returns the [`SchnorrSighashType`] if the [`PsbtSighashType`] can be
+    /// Returns the [`TapSighashType`] if the [`PsbtSighashType`] can be
     /// converted to one.
-    pub fn schnorr_hash_ty(self) -> Result<SchnorrSighashType, sighash::Error> {
+    pub fn taproot_hash_ty(self) -> Result<TapSighashType, sighash::Error> {
         if self.inner > 0xffu32 {
             Err(sighash::Error::InvalidSighashType(self.inner))
         } else {
-            SchnorrSighashType::from_consensus_u8(self.inner as u8)
+            TapSighashType::from_consensus_u8(self.inner as u8)
         }
     }
 
     /// Creates a [`PsbtSighashType`] from a raw `u32`.
     ///
     /// Allows construction of a non-standard or non-valid sighash flag
-    /// ([`EcdsaSighashType`], [`SchnorrSighashType`] respectively).
+    /// ([`EcdsaSighashType`], [`TapSighashType`] respectively).
     pub fn from_u32(n: u32) -> PsbtSighashType {
         PsbtSighashType { inner: n }
     }
@@ -234,16 +234,16 @@ pub fn ecdsa_hash_ty(&self) -> Result<EcdsaSighashType, NonStandardSighashType>
             .unwrap_or(Ok(EcdsaSighashType::All))
     }
 
-    /// Obtains the [`SchnorrSighashType`] for this input if one is specified. If no sighash type is
-    /// specified, returns [`SchnorrSighashType::Default`].
+    /// Obtains the [`TapSighashType`] for this input if one is specified. If no sighash type is
+    /// specified, returns [`TapSighashType::Default`].
     ///
     /// # Errors
     ///
-    /// If the `sighash_type` field is set to a invalid Schnorr sighash value.
-    pub fn schnorr_hash_ty(&self) -> Result<SchnorrSighashType, sighash::Error> {
+    /// If the `sighash_type` field is set to a invalid Taproot sighash value.
+    pub fn taproot_hash_ty(&self) -> Result<TapSighashType, sighash::Error> {
         self.sighash_type
-            .map(|sighash_type| sighash_type.schnorr_hash_ty())
-            .unwrap_or(Ok(SchnorrSighashType::Default))
+            .map(|sighash_type| sighash_type.taproot_hash_ty())
+            .unwrap_or(Ok(TapSighashType::Default))
     }
 
     pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> {
@@ -312,12 +312,12 @@ pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> {
             }
             PSBT_IN_TAP_KEY_SIG => {
                 impl_psbt_insert_pair! {
-                    self.tap_key_sig <= <raw_key: _>|<raw_value: schnorr::Signature>
+                    self.tap_key_sig <= <raw_key: _>|<raw_value: taproot::Signature>
                 }
             }
             PSBT_IN_TAP_SCRIPT_SIG => {
                 impl_psbt_insert_pair! {
-                    self.tap_script_sigs <= <raw_key: (XOnlyPublicKey, TapLeafHash)>|<raw_value: schnorr::Signature>
+                    self.tap_script_sigs <= <raw_key: (XOnlyPublicKey, TapLeafHash)>|<raw_value: taproot::Signature>
                 }
             }
             PSBT_IN_TAP_LEAF_SCRIPT => {
@@ -543,21 +543,21 @@ fn psbt_sighash_type_ecdsa() {
     }
 
     #[test]
-    fn psbt_sighash_type_schnorr() {
-        for schnorr in &[
-            SchnorrSighashType::Default,
-            SchnorrSighashType::All,
-            SchnorrSighashType::None,
-            SchnorrSighashType::Single,
-            SchnorrSighashType::AllPlusAnyoneCanPay,
-            SchnorrSighashType::NonePlusAnyoneCanPay,
-            SchnorrSighashType::SinglePlusAnyoneCanPay,
+    fn psbt_sighash_type_taproot() {
+        for tap in &[
+            TapSighashType::Default,
+            TapSighashType::All,
+            TapSighashType::None,
+            TapSighashType::Single,
+            TapSighashType::AllPlusAnyoneCanPay,
+            TapSighashType::NonePlusAnyoneCanPay,
+            TapSighashType::SinglePlusAnyoneCanPay,
         ] {
-            let sighash = PsbtSighashType::from(*schnorr);
+            let sighash = PsbtSighashType::from(*tap);
             let s = format!("{}", sighash);
             let back = PsbtSighashType::from_str(&s).unwrap();
             assert_eq!(back, sighash);
-            assert_eq!(back.schnorr_hash_ty().unwrap(), *schnorr);
+            assert_eq!(back.taproot_hash_ty().unwrap(), *tap);
         }
     }
 
@@ -570,6 +570,6 @@ fn psbt_sighash_type_notstd() {
 
         assert_eq!(back, sighash);
         assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashType(nonstd)));
-        assert_eq!(back.schnorr_hash_ty(), Err(sighash::Error::InvalidSighashType(nonstd)));
+        assert_eq!(back.taproot_hash_ty(), Err(sighash::Error::InvalidSighashType(nonstd)));
     }
 }
diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs
index 73b6c541..d2fba494 100644
--- a/bitcoin/src/psbt/mod.rs
+++ b/bitcoin/src/psbt/mod.rs
@@ -326,34 +326,37 @@ pub fn sighash_ecdsa<T: Borrow<Transaction>>(
         let hash_ty = input.ecdsa_hash_ty()
             .map_err(|_| SignError::InvalidSighashType)?; // Only support standard sighash types.
 
-        let sighash = match self.output_type(input_index)? {
+        match self.output_type(input_index)? {
             Bare => {
-                cache.legacy_signature_hash(input_index, spk, hash_ty.to_u32())?
+                let sighash = cache.legacy_signature_hash(input_index, spk, hash_ty.to_u32())?;
+                Ok((Message::from(sighash), hash_ty))
             },
             Sh => {
                 let script_code = input.redeem_script.as_ref().ok_or(SignError::MissingRedeemScript)?;
-                cache.legacy_signature_hash(input_index, script_code, hash_ty.to_u32())?
+                let sighash = cache.legacy_signature_hash(input_index, script_code, hash_ty.to_u32())?;
+                Ok((Message::from(sighash), hash_ty))
             },
             Wpkh => {
                 let script_code = ScriptBuf::p2wpkh_script_code(spk).ok_or(SignError::NotWpkh)?;
-                cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?
-            }
+                let sighash = cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?;
+                Ok((Message::from(sighash), hash_ty))
+            },
             ShWpkh => {
                 let script_code = ScriptBuf::p2wpkh_script_code(input.redeem_script.as_ref().expect("checked above"))
                     .ok_or(SignError::NotWpkh)?;
-                cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?
+                let sighash = cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?;
+                Ok((Message::from(sighash), hash_ty))
             },
             Wsh | ShWsh => {
                 let script_code = input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?;
-                cache.segwit_signature_hash(input_index, script_code, utxo.value, hash_ty)?
+                let sighash = cache.segwit_signature_hash(input_index, script_code, utxo.value, hash_ty)?;
+                Ok((Message::from(sighash), hash_ty))
             },
             Tr => {
                 // This PSBT signing API is WIP, taproot to come shortly.
-                return Err(SignError::Unsupported);
+                Err(SignError::Unsupported)
             }
-        };
-
-        Ok((Message::from(sighash), hash_ty))
+        }
     }
 
     /// Returns the spending utxo for this PSBT's input at `input_index`.
@@ -1373,9 +1376,9 @@ fn invalid_vectors() {
             assert_eq!(err.to_string(), "invalid xonly public key");
             let err = hex_psbt!("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011342173bb3d36c074afb716fec6307a069a2e450b995f3c82785945ab8df0e24260dcd703b0cbf34de399184a9481ac2b3586db6601f026a77f7e4938481bc34751701aa000000").unwrap_err();
             #[cfg(feature = "std")]
-            assert_eq!(err.to_string(), "invalid Schnorr signature");
+            assert_eq!(err.to_string(), "invalid taproot signature");
             #[cfg(not(feature = "std"))]
-            assert_eq!(err.to_string(), "invalid Schnorr signature: Invalid Schnorr signature size: 66");
+            assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 66");
             let err = hex_psbt!("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757221602fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000000000").unwrap_err();
             assert_eq!(err.to_string(), "invalid xonly public key");
             let err = hex_psbt!("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000001052102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa23200").unwrap_err();
@@ -1389,14 +1392,14 @@ fn invalid_vectors() {
             assert_eq!(err.to_string(), "hash parse error: invalid slice length 33 (expected 32)");
             let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err();
             #[cfg(feature = "std")]
-            assert_eq!(err.to_string(), "invalid Schnorr signature");
+            assert_eq!(err.to_string(), "invalid taproot signature");
             #[cfg(not(feature = "std"))]
-            assert_eq!(err.to_string(), "invalid Schnorr signature: Invalid Schnorr signature size: 66");
+            assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 66");
             let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err();
             #[cfg(feature = "std")]
-            assert_eq!(err.to_string(), "invalid Schnorr signature");
+            assert_eq!(err.to_string(), "invalid taproot signature");
             #[cfg(not(feature = "std"))]
-            assert_eq!(err.to_string(), "invalid Schnorr signature: Invalid Schnorr signature size: 57");
+            assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 57");
             let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926315c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f80023202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err();
             assert_eq!(err.to_string(), "invalid control block");
             let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926115c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e123202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err();
diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs
index bcd9bebd..493e2c70 100644
--- a/bitcoin/src/psbt/serialize.rs
+++ b/bitcoin/src/psbt/serialize.rs
@@ -19,7 +19,7 @@
 use secp256k1::{self, XOnlyPublicKey};
 use crate::bip32::{ChildNumber, Fingerprint, KeySource};
 use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
-use crate::crypto::{ecdsa, schnorr};
+use crate::crypto::{ecdsa, taproot};
 use crate::psbt::{Error, PartiallySignedTransaction};
 use crate::taproot::{TapNodeHash, TapLeafHash, ControlBlock, LeafVersion};
 use crate::crypto::key::PublicKey;
@@ -283,24 +283,24 @@ fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
     }
 }
 
-impl Serialize for schnorr::Signature  {
+impl Serialize for taproot::Signature  {
     fn serialize(&self) -> Vec<u8> {
         self.to_vec()
     }
 }
 
-impl Deserialize for schnorr::Signature {
+impl Deserialize for taproot::Signature {
     fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
-        schnorr::Signature::from_slice(bytes)
+        taproot::Signature::from_slice(bytes)
             .map_err(|e| match e {
-                schnorr::Error::InvalidSighashType(flag) => {
+                taproot::Error::InvalidSighashType(flag) => {
                     Error::NonStandardSighashType(flag as u32)
                 }
-                schnorr::Error::InvalidSignatureSize(_) => {
-                    Error::InvalidSchnorrSignature(e)
+                taproot::Error::InvalidSignatureSize(_) => {
+                    Error::InvalidTaprootSignature(e)
                 }
-                schnorr::Error::Secp256k1(..) => {
-                    Error::InvalidSchnorrSignature(e)
+                taproot::Error::Secp256k1(..) => {
+                    Error::InvalidTaprootSignature(e)
                 }
             })
     }
diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs
index 825b4708..06bfe9e0 100644
--- a/bitcoin/src/taproot.rs
+++ b/bitcoin/src/taproot.rs
@@ -13,11 +13,13 @@
 use secp256k1::{self, Scalar, Secp256k1};
 
 use crate::consensus::Encodable;
-use crate::crypto::schnorr::{TapTweak, TweakedPublicKey, UntweakedPublicKey, XOnlyPublicKey};
+use crate::crypto::key::{TapTweak, TweakedPublicKey, UntweakedPublicKey, XOnlyPublicKey};
 use crate::hashes::{sha256t_hash_newtype, Hash, HashEngine};
 use crate::prelude::*;
 use crate::{io, Script, ScriptBuf};
 
+pub use crate::crypto::sighash::{TapSighash, TapSighashTag};
+
 /// The SHA-256 midstate value for the TapLeaf hash.
 const MIDSTATE_TAPLEAF: [u8; 32] = [
     156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, 108,
@@ -39,13 +41,6 @@
 ];
 // d129a2f3701c655d6583b6c3b941972795f4e23294fd54f4a2ae8d8547ca590b
 
-/// The SHA-256 midstate value for the [`TapSighashHash`].
-const MIDSTATE_TAPSIGHASH: [u8; 32] = [
-    245, 4, 164, 37, 215, 248, 120, 59, 19, 99, 134, 138, 227, 229, 86, 88, 110, 238, 148, 93, 188,
-    120, 136, 221, 2, 166, 226, 195, 24, 115, 254, 159,
-];
-// f504a425d7f8783b1363868ae3e556586eee945dbc7888dd02a6e2c31873fe9f
-
 // Taproot test vectors from BIP-341 state the hashes without any reversing
 #[rustfmt::skip]
 sha256t_hash_newtype!(TapLeafHash, TapLeafTag, MIDSTATE_TAPLEAF, 64,
@@ -62,16 +57,6 @@
     doc="Taproot-tagged hash with tag \"TapTweak\".
     This hash type is used while computing the tweaked public key", false
 );
-#[rustfmt::skip]
-sha256t_hash_newtype!(TapSighashHash, TapSighashTag, MIDSTATE_TAPSIGHASH, 64,
-    doc="Taproot-tagged hash with tag \"TapSighash\".
-
-This hash type is used for computing taproot signature hash.", false
-);
-
-impl secp256k1::ThirtyTwoByteHash for TapSighashHash {
-    fn into_32(self) -> [u8; 32] { self.into_inner() }
-}
 
 impl TapTweakHash {
     /// Creates a new BIP341 [`TapTweakHash`] from key and tweak. Produces `H_taptweak(P||R)` where
@@ -1145,7 +1130,6 @@ mod test {
     use secp256k1::{VerifyOnly, XOnlyPublicKey};
 
     use super::*;
-    use crate::crypto::schnorr::TapTweak;
     use crate::hashes::hex::FromHex;
     use crate::hashes::sha256t::Tag;
     use crate::hashes::{sha256, Hash, HashEngine};
@@ -1165,6 +1149,8 @@ fn tag_engine(tag_name: &str) -> sha256::HashEngine {
 
     #[test]
     fn test_midstates() {
+        use crate::crypto::sighash::MIDSTATE_TAPSIGHASH;
+
         // check midstate against hard-coded values
         assert_eq!(MIDSTATE_TAPLEAF, tag_engine("TapLeaf").midstate().into_inner());
         assert_eq!(MIDSTATE_TAPBRANCH, tag_engine("TapBranch").midstate().into_inner());
@@ -1186,7 +1172,7 @@ fn test_midstates() {
         assert_eq!(empty_hash("TapLeaf"), TapLeafHash::hash(&[]).into_inner());
         assert_eq!(empty_hash("TapBranch"), TapNodeHash::hash(&[]).into_inner());
         assert_eq!(empty_hash("TapTweak"), TapTweakHash::hash(&[]).into_inner());
-        assert_eq!(empty_hash("TapSighash"), TapSighashHash::hash(&[]).into_inner());
+        assert_eq!(empty_hash("TapSighash"), TapSighash::hash(&[]).into_inner());
     }
 
     #[test]
@@ -1209,7 +1195,7 @@ fn test_vectors_core() {
             "8aa4229474ab0100b2d6f0687f031d1fc9d8eef92a042ad97d279bff456b15e4"
         );
         assert_eq!(
-            TapSighashHash::from_engine(TapSighashTag::engine()).to_string(),
+            TapSighash::from_engine(TapSighashTag::engine()).to_string(),
             "dabc11914abcd8072900042a2681e52f8dba99ce82e224f97b5fdb7cd4b9c803"
         );
 
@@ -1231,7 +1217,7 @@ fn test_vectors_core() {
             "cd8737b5e6047fc3f16f03e8b9959e3440e1bdf6dd02f7bb899c352ad490ea1e"
         );
         assert_eq!(
-            TapSighashHash::hash(&[0]).to_string(),
+            TapSighash::hash(&[0]).to_string(),
             "c2fd0de003889a09c4afcf676656a0d8a1fb706313ff7d509afb00c323c010cd"
         );
     }


Test patch:
diff --git a/bitcoin/tests/data/serde/schnorr_sig_bincode b/bitcoin/tests/data/serde/taproot_sig_bincode
similarity index 100%
rename from bitcoin/tests/data/serde/schnorr_sig_bincode
rename to bitcoin/tests/data/serde/taproot_sig_bincode
diff --git a/bitcoin/tests/data/serde/schnorr_sig_hex b/bitcoin/tests/data/serde/taproot_sig_hex
similarity index 100%
rename from bitcoin/tests/data/serde/schnorr_sig_hex
rename to bitcoin/tests/data/serde/taproot_sig_hex
diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs
index 79088793..254a2016 100644
--- a/bitcoin/tests/serde.rs
+++ b/bitcoin/tests/serde.rs
@@ -30,15 +30,16 @@
 use bitcoin::blockdata::locktime::{absolute, relative};
 use bitcoin::blockdata::witness::Witness;
 use bitcoin::consensus::encode::deserialize;
+use bitcoin::crypto::key::UntweakedPublicKey;
+use bitcoin::crypto::{ecdsa, taproot};
 use bitcoin::hashes::hex::FromHex;
 use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
 use bitcoin::psbt::raw::{self, Key, Pair, ProprietaryKey};
 use bitcoin::psbt::{Input, Output, Psbt, PsbtSighashType};
-use bitcoin::schnorr::{self, UntweakedPublicKey};
-use bitcoin::sighash::{EcdsaSighashType, SchnorrSighashType};
+use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
 use bitcoin::taproot::{ControlBlock, LeafVersion, TaprootBuilder, TaprootSpendInfo};
 use bitcoin::{
-    ecdsa, Address, Block, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence, Target,
+    Address, Block, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence, Target,
     Transaction, TxIn, TxOut, Txid, Work,
 };
 use secp256k1::Secp256k1;
@@ -339,15 +340,15 @@ fn serde_regression_proprietary_key() {
 }
 
 #[test]
-fn serde_regression_schnorr_sig() {
-    let s = include_str!("data/serde/schnorr_sig_hex");
-    let sig = schnorr::Signature {
+fn serde_regression_taproot_sig() {
+    let s = include_str!("data/serde/taproot_sig_hex");
+    let sig = taproot::Signature {
         sig: secp256k1::schnorr::Signature::from_str(s.trim()).unwrap(),
-        hash_ty: SchnorrSighashType::All,
+        hash_ty: TapSighashType::All,
     };
 
     let got = serialize(&sig).unwrap();
-    let want = include_bytes!("data/serde/schnorr_sig_bincode") as &[_];
+    let want = include_bytes!("data/serde/taproot_sig_bincode") as &[_];
     assert_eq!(got, want)
 }