Move taproot back to bitcoin crate

I don't know what I was thinking when I move the taproot hash types to
`primitives`. As correctly pointed out by Kix we agreed to only have
blockdata in `primitives`.

Move the taproot hash types back to `bitcoin::taproot` and remove the
extension traits.
This commit is contained in:
Tobin C. Harding 2025-02-26 15:44:53 +11:00
parent aebda6e516
commit cf12ba262a
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
6 changed files with 96 additions and 126 deletions

View File

@ -14,7 +14,7 @@ use crate::opcodes::all::*;
use crate::opcodes::{self, Opcode}; use crate::opcodes::{self, Opcode};
use crate::policy::{DUST_RELAY_TX_FEE, MAX_OP_RETURN_RELAY}; use crate::policy::{DUST_RELAY_TX_FEE, MAX_OP_RETURN_RELAY};
use crate::prelude::{sink, DisplayHex, String, ToString}; use crate::prelude::{sink, DisplayHex, String, ToString};
use crate::taproot::{LeafVersion, TapLeafHash, TapLeafHashExt as _}; use crate::taproot::{LeafVersion, TapLeafHash};
use crate::{Amount, FeeRate}; use crate::{Amount, FeeRate};
#[rustfmt::skip] // Keep public re-exports separate. #[rustfmt::skip] // Keep public re-exports separate.

View File

@ -21,7 +21,7 @@ use crate::internal_macros::impl_asref_push_bytes;
use crate::network::NetworkKind; use crate::network::NetworkKind;
use crate::prelude::{DisplayHex, String, Vec}; use crate::prelude::{DisplayHex, String, Vec};
use crate::script::{self, ScriptBuf}; use crate::script::{self, ScriptBuf};
use crate::taproot::{TapNodeHash, TapTweakHash, TapTweakHashExt as _}; use crate::taproot::{TapNodeHash, TapTweakHash};
#[rustfmt::skip] // Keep public re-exports separate. #[rustfmt::skip] // Keep public re-exports separate.
pub use secp256k1::{constants, Keypair, Parity, Secp256k1, Verification, XOnlyPublicKey}; pub use secp256k1::{constants, Keypair, Parity, Secp256k1, Verification, XOnlyPublicKey};

View File

@ -1864,8 +1864,6 @@ mod tests {
fn bip_341_sighash_tests() { fn bip_341_sighash_tests() {
use hex::DisplayHex; use hex::DisplayHex;
use crate::taproot::TapTweakHashExt as _;
fn sighash_deser_numeric<'de, D>(deserializer: D) -> Result<TapSighashType, D::Error> fn sighash_deser_numeric<'de, D>(deserializer: D) -> Result<TapSighashType, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,

View File

@ -12,7 +12,7 @@ use core::convert::Infallible;
use core::fmt; use core::fmt;
use core::iter::FusedIterator; use core::iter::FusedIterator;
use hashes::{sha256t, HashEngine}; use hashes::{hash_newtype, sha256t, sha256t_tag, HashEngine};
use internals::{impl_to_hex_from_lower_hex, write_err}; use internals::{impl_to_hex_from_lower_hex, write_err};
use io::Write; use io::Write;
use secp256k1::{Scalar, Secp256k1}; use secp256k1::{Scalar, Secp256k1};
@ -28,16 +28,61 @@ use crate::{Script, ScriptBuf};
pub use crate::crypto::taproot::{SigFromSliceError, Signature}; pub use crate::crypto::taproot::{SigFromSliceError, Signature};
#[doc(inline)] #[doc(inline)]
pub use merkle_branch::TaprootMerkleBranch; pub use merkle_branch::TaprootMerkleBranch;
pub use primitives::taproot::{
TapBranchTag, TapLeafHash, TapLeafTag, TapNodeHash, TapTweakHash, TapTweakTag,
};
crate::internal_macros::define_extension_trait! { // Taproot test vectors from BIP-341 state the hashes without any reversing
/// Extension functionality for the [`TapTweakHash`] type. sha256t_tag! {
pub trait TapTweakHashExt impl for TapTweakHash { pub struct TapLeafTag = hash_str("TapLeaf");
}
hash_newtype! {
/// Taproot-tagged hash with tag \"TapLeaf\".
///
/// This is used for computing tapscript script spend hash.
pub struct TapLeafHash(sha256t::Hash<TapLeafTag>);
}
hashes::impl_hex_for_newtype!(TapLeafHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapLeafHash);
sha256t_tag! {
pub struct TapBranchTag = hash_str("TapBranch");
}
hash_newtype! {
/// Tagged hash used in Taproot trees.
///
/// See BIP-340 for tagging rules.
pub struct TapNodeHash(sha256t::Hash<TapBranchTag>);
}
hashes::impl_hex_for_newtype!(TapNodeHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapNodeHash);
sha256t_tag! {
pub struct TapTweakTag = hash_str("TapTweak");
}
hash_newtype! {
/// Taproot-tagged hash with tag \"TapTweak\".
///
/// This hash type is used while computing the tweaked public key.
pub struct TapTweakHash(sha256t::Hash<TapTweakTag>);
}
hashes::impl_hex_for_newtype!(TapTweakHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapTweakHash);
impl From<TapLeafHash> for TapNodeHash {
fn from(leaf: TapLeafHash) -> TapNodeHash { TapNodeHash::from_byte_array(leaf.to_byte_array()) }
}
impl TapTweakHash {
/// Constructs a new BIP341 [`TapTweakHash`] from key and tweak. Produces `H_taptweak(P||R)` where /// Constructs a new BIP341 [`TapTweakHash`] from key and tweak. Produces `H_taptweak(P||R)` where
/// `P` is the internal key and `R` is the Merkle root. /// `P` is the internal key and `R` is the Merkle root.
fn from_key_and_tweak( pub fn from_key_and_tweak(
internal_key: UntweakedPublicKey, internal_key: UntweakedPublicKey,
merkle_root: Option<TapNodeHash>, merkle_root: Option<TapNodeHash>,
) -> TapTweakHash { ) -> TapTweakHash {
@ -54,18 +99,15 @@ crate::internal_macros::define_extension_trait! {
} }
/// Converts a `TapTweakHash` into a `Scalar` ready for use with key tweaking API. /// Converts a `TapTweakHash` into a `Scalar` ready for use with key tweaking API.
fn to_scalar(self) -> Scalar { pub fn to_scalar(self) -> Scalar {
// This is statistically extremely unlikely to panic. // This is statistically extremely unlikely to panic.
Scalar::from_be_bytes(self.to_byte_array()).expect("hash value greater than curve order") Scalar::from_be_bytes(self.to_byte_array()).expect("hash value greater than curve order")
} }
} }
}
crate::internal_macros::define_extension_trait! { impl TapLeafHash {
/// Extension functionality for the [`TapLeafHash`] type.
pub trait TapLeafHashExt impl for TapLeafHash {
/// Computes the leaf hash from components. /// Computes the leaf hash from components.
fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash { pub fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
let mut eng = sha256t::Hash::<TapLeafTag>::engine(); let mut eng = sha256t::Hash::<TapLeafTag>::engine();
ver.to_consensus().consensus_encode(&mut eng).expect("engines don't error"); ver.to_consensus().consensus_encode(&mut eng).expect("engines don't error");
script.consensus_encode(&mut eng).expect("engines don't error"); script.consensus_encode(&mut eng).expect("engines don't error");
@ -73,7 +115,6 @@ crate::internal_macros::define_extension_trait! {
TapLeafHash::from_byte_array(inner.to_byte_array()) TapLeafHash::from_byte_array(inner.to_byte_array())
} }
} }
}
impl From<LeafNode> for TapNodeHash { impl From<LeafNode> for TapNodeHash {
fn from(leaf: LeafNode) -> TapNodeHash { leaf.node_hash() } fn from(leaf: LeafNode) -> TapNodeHash { leaf.node_hash() }
@ -83,11 +124,9 @@ impl From<&LeafNode> for TapNodeHash {
fn from(leaf: &LeafNode) -> TapNodeHash { leaf.node_hash() } fn from(leaf: &LeafNode) -> TapNodeHash { leaf.node_hash() }
} }
crate::internal_macros::define_extension_trait! { impl TapNodeHash {
/// Extension functionality for the [`TapNodeHash`] type.
pub trait TapNodeHashExt impl for TapNodeHash {
/// Computes branch hash given two hashes of the nodes underneath it. /// Computes branch hash given two hashes of the nodes underneath it.
fn from_node_hashes(a: TapNodeHash, b: TapNodeHash) -> TapNodeHash { pub fn from_node_hashes(a: TapNodeHash, b: TapNodeHash) -> TapNodeHash {
combine_node_hashes(a, b).0 combine_node_hashes(a, b).0
} }
@ -96,14 +135,13 @@ crate::internal_macros::define_extension_trait! {
/// Similar to [`TapLeafHash::from_byte_array`], but explicitly conveys that the /// Similar to [`TapLeafHash::from_byte_array`], but explicitly conveys that the
/// hash is constructed from a hidden node. This also has better ergonomics /// hash is constructed from a hidden node. This also has better ergonomics
/// because it does not require the caller to import the Hash trait. /// because it does not require the caller to import the Hash trait.
fn assume_hidden(hash: [u8; 32]) -> TapNodeHash { TapNodeHash::from_byte_array(hash) } pub fn assume_hidden(hash: [u8; 32]) -> TapNodeHash { TapNodeHash::from_byte_array(hash) }
/// Computes the [`TapNodeHash`] from a script and a leaf version. /// Computes the [`TapNodeHash`] from a script and a leaf version.
fn from_script(script: &Script, ver: LeafVersion) -> TapNodeHash { pub fn from_script(script: &Script, ver: LeafVersion) -> TapNodeHash {
TapNodeHash::from(TapLeafHash::from_script(script, ver)) TapNodeHash::from(TapLeafHash::from_script(script, ver))
} }
} }
}
/// Computes branch hash given two hashes of the nodes underneath it and returns /// Computes branch hash given two hashes of the nodes underneath it and returns
/// whether the left node was the one hashed first. /// whether the left node was the one hashed first.
@ -1554,13 +1592,6 @@ impl fmt::Display for InvalidControlBlockSizeError {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl std::error::Error for InvalidControlBlockSizeError {} impl std::error::Error for InvalidControlBlockSizeError {}
mod sealed {
pub trait Sealed {}
impl Sealed for super::TapTweakHash {}
impl Sealed for super::TapLeafHash {}
impl Sealed for super::TapNodeHash {}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use hashes::sha256; use hashes::sha256;

View File

@ -49,7 +49,6 @@ pub mod pow;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub mod script; pub mod script;
pub mod sequence; pub mod sequence;
pub mod taproot;
pub mod transaction; pub mod transaction;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub mod witness; pub mod witness;
@ -80,7 +79,6 @@ pub use self::{
opcodes::Opcode, opcodes::Opcode,
pow::CompactTarget, pow::CompactTarget,
sequence::Sequence, sequence::Sequence,
taproot::{TapBranchTag, TapLeafHash, TapLeafTag, TapNodeHash, TapTweakHash, TapTweakTag},
transaction::{OutPoint, Txid, Wtxid}, transaction::{OutPoint, Txid, Wtxid},
}; };

View File

@ -1,57 +0,0 @@
// SPDX-License-Identifier: CC0-1.0
//! Bitcoin Taproot.
//!
//! This module provides support for Taproot tagged hashes.
use hashes::{hash_newtype, sha256t, sha256t_tag};
// Taproot test vectors from BIP-341 state the hashes without any reversing
sha256t_tag! {
pub struct TapLeafTag = hash_str("TapLeaf");
}
hash_newtype! {
/// Taproot-tagged hash with tag \"TapLeaf\".
///
/// This is used for computing tapscript script spend hash.
pub struct TapLeafHash(sha256t::Hash<TapLeafTag>);
}
hashes::impl_hex_for_newtype!(TapLeafHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapLeafHash);
sha256t_tag! {
pub struct TapBranchTag = hash_str("TapBranch");
}
hash_newtype! {
/// Tagged hash used in Taproot trees.
///
/// See BIP-340 for tagging rules.
pub struct TapNodeHash(sha256t::Hash<TapBranchTag>);
}
hashes::impl_hex_for_newtype!(TapNodeHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapNodeHash);
sha256t_tag! {
pub struct TapTweakTag = hash_str("TapTweak");
}
hash_newtype! {
/// Taproot-tagged hash with tag \"TapTweak\".
///
/// This hash type is used while computing the tweaked public key.
pub struct TapTweakHash(sha256t::Hash<TapTweakTag>);
}
hashes::impl_hex_for_newtype!(TapTweakHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapTweakHash);
impl From<TapLeafHash> for TapNodeHash {
fn from(leaf: TapLeafHash) -> TapNodeHash { TapNodeHash::from_byte_array(leaf.to_byte_array()) }
}