Introduce taproot hash type extension traits
Introduce three extension traits for the taproot hash types. All logic for the hash types is now within the extension traits.
This commit is contained in:
parent
c30ef617fb
commit
24e944ed82
|
@ -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;
|
use crate::policy::DUST_RELAY_TX_FEE;
|
||||||
use crate::prelude::{sink, DisplayHex, String, ToString};
|
use crate::prelude::{sink, DisplayHex, String, ToString};
|
||||||
use crate::taproot::{LeafVersion, TapLeafHash};
|
use crate::taproot::{LeafVersion, TapLeafHash, TapLeafHashExt as _};
|
||||||
use crate::FeeRate;
|
use crate::FeeRate;
|
||||||
|
|
||||||
#[rustfmt::skip] // Keep public re-exports separate.
|
#[rustfmt::skip] // Keep public re-exports separate.
|
||||||
|
|
|
@ -20,7 +20,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};
|
use crate::taproot::{TapNodeHash, TapTweakHash, TapTweakHashExt as _};
|
||||||
|
|
||||||
#[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};
|
||||||
|
|
|
@ -1509,6 +1509,7 @@ mod tests {
|
||||||
use crate::consensus::deserialize;
|
use crate::consensus::deserialize;
|
||||||
use crate::locktime::absolute;
|
use crate::locktime::absolute;
|
||||||
use crate::script::ScriptBufExt as _;
|
use crate::script::ScriptBufExt as _;
|
||||||
|
use crate::taproot::TapTweakHashExt as _;
|
||||||
|
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
|
|
|
@ -62,40 +62,46 @@ hash_newtype! {
|
||||||
pub struct TapTweakHash(sha256t::Hash<TapTweakTag>);
|
pub struct TapTweakHash(sha256t::Hash<TapTweakTag>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TapTweakHash {
|
crate::internal_macros::define_extension_trait! {
|
||||||
/// Creates a new BIP341 [`TapTweakHash`] from key and tweak. Produces `H_taptweak(P||R)` where
|
/// Extension functionality for the [`TapTweakHash`] type.
|
||||||
/// `P` is the internal key and `R` is the Merkle root.
|
pub trait TapTweakHashExt impl for TapTweakHash {
|
||||||
pub fn from_key_and_tweak(
|
/// Creates a new BIP341 [`TapTweakHash`] from key and tweak. Produces `H_taptweak(P||R)` where
|
||||||
internal_key: UntweakedPublicKey,
|
/// `P` is the internal key and `R` is the Merkle root.
|
||||||
merkle_root: Option<TapNodeHash>,
|
fn from_key_and_tweak(
|
||||||
) -> TapTweakHash {
|
internal_key: UntweakedPublicKey,
|
||||||
let mut eng = sha256t::Hash::<TapTweakTag>::engine();
|
merkle_root: Option<TapNodeHash>,
|
||||||
// always hash the key
|
) -> TapTweakHash {
|
||||||
eng.input(&internal_key.serialize());
|
let mut eng = sha256t::Hash::<TapTweakTag>::engine();
|
||||||
if let Some(h) = merkle_root {
|
// always hash the key
|
||||||
eng.input(h.as_ref());
|
eng.input(&internal_key.serialize());
|
||||||
} else {
|
if let Some(h) = merkle_root {
|
||||||
// nothing to hash
|
eng.input(h.as_ref());
|
||||||
|
} else {
|
||||||
|
// nothing to hash
|
||||||
|
}
|
||||||
|
let inner = sha256t::Hash::<TapTweakTag>::from_engine(eng);
|
||||||
|
TapTweakHash::from_byte_array(inner.to_byte_array())
|
||||||
}
|
}
|
||||||
let inner = sha256t::Hash::<TapTweakTag>::from_engine(eng);
|
|
||||||
TapTweakHash::from_byte_array(inner.to_byte_array())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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.
|
||||||
pub fn to_scalar(self) -> Scalar {
|
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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TapLeafHash {
|
crate::internal_macros::define_extension_trait! {
|
||||||
/// Computes the leaf hash from components.
|
/// Extension functionality for the [`TapLeafHash`] type.
|
||||||
pub fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
|
pub trait TapLeafHashExt impl for TapLeafHash {
|
||||||
let mut eng = sha256t::Hash::<TapLeafTag>::engine();
|
/// Computes the leaf hash from components.
|
||||||
ver.to_consensus().consensus_encode(&mut eng).expect("engines don't error");
|
fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
|
||||||
script.consensus_encode(&mut eng).expect("engines don't error");
|
let mut eng = sha256t::Hash::<TapLeafTag>::engine();
|
||||||
let inner = sha256t::Hash::<TapTweakTag>::from_engine(eng);
|
ver.to_consensus().consensus_encode(&mut eng).expect("engines don't error");
|
||||||
TapLeafHash::from_byte_array(inner.to_byte_array())
|
script.consensus_encode(&mut eng).expect("engines don't error");
|
||||||
|
let inner = sha256t::Hash::<TapTweakTag>::from_engine(eng);
|
||||||
|
TapLeafHash::from_byte_array(inner.to_byte_array())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,22 +113,25 @@ impl From<&LeafNode> for TapNodeHash {
|
||||||
fn from(leaf: &LeafNode) -> TapNodeHash { leaf.node_hash() }
|
fn from(leaf: &LeafNode) -> TapNodeHash { leaf.node_hash() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TapNodeHash {
|
crate::internal_macros::define_extension_trait! {
|
||||||
/// Computes branch hash given two hashes of the nodes underneath it.
|
/// Extension functionality for the [`TapNodeHash`] type.
|
||||||
pub fn from_node_hashes(a: TapNodeHash, b: TapNodeHash) -> TapNodeHash {
|
pub trait TapNodeHashExt impl for TapNodeHash {
|
||||||
combine_node_hashes(a, b).0
|
/// Computes branch hash given two hashes of the nodes underneath it.
|
||||||
}
|
fn from_node_hashes(a: TapNodeHash, b: TapNodeHash) -> TapNodeHash {
|
||||||
|
combine_node_hashes(a, b).0
|
||||||
|
}
|
||||||
|
|
||||||
/// Assumes the given 32 byte array as hidden [`TapNodeHash`].
|
/// Assumes the given 32 byte array as hidden [`TapNodeHash`].
|
||||||
///
|
///
|
||||||
/// 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.
|
||||||
pub fn assume_hidden(hash: [u8; 32]) -> TapNodeHash { TapNodeHash::from_byte_array(hash) }
|
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.
|
||||||
pub fn from_script(script: &Script, ver: LeafVersion) -> TapNodeHash {
|
fn from_script(script: &Script, ver: LeafVersion) -> TapNodeHash {
|
||||||
TapNodeHash::from(TapLeafHash::from_script(script, ver))
|
TapNodeHash::from(TapLeafHash::from_script(script, ver))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue