hashes: Implement AsRef for fixed size arrays

Implement `AsRef<[u8; X]>` for hash types including wrapped hash types.
Doing so means at times the compiler can no longer infer the type because we have
`AsRef<[u8]` implemented also but we can use `into_inner` and `as_inner`
to get the inner array if needed.
This commit is contained in:
Tobin C. Harding 2023-01-26 10:50:20 +11:00
parent 2a052acadf
commit a121e19e94
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
5 changed files with 43 additions and 9 deletions

View File

@ -481,7 +481,7 @@ impl Payload {
pub fn p2wpkh(pk: &PublicKey) -> Result<Payload, Error> {
let prog = WitnessProgram::new(
WitnessVersion::V0,
pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?.as_ref().to_vec()
pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?.into_inner().to_vec()
)?;
Ok(Payload::WitnessProgram(prog))
}
@ -499,7 +499,7 @@ impl Payload {
pub fn p2wsh(script: &script::Script) -> Payload {
let prog = WitnessProgram::new(
WitnessVersion::V0,
script.wscript_hash().as_ref().to_vec()
script.wscript_hash().as_inner().to_vec()
).expect("wscript_hash has len 32 compatible with segwitv0");
Payload::WitnessProgram(prog)
}
@ -937,9 +937,9 @@ impl Address {
let payload = self.payload.inner_prog_as_bytes();
let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner);
(*pubkey_hash.as_ref() == *payload)
(*pubkey_hash.as_inner() == *payload)
|| (xonly_pubkey.serialize() == *payload)
|| (*segwit_redeem_hash(&pubkey_hash).as_ref() == *payload)
|| (*segwit_redeem_hash(&pubkey_hash).as_inner() == *payload)
}
/// Returns true if the supplied xonly public key can be used to derive the address.

View File

@ -582,7 +582,7 @@ mod test {
flags: BloomFlags::All,
}),
NetworkMessage::FilterAdd(FilterAdd { data: script.as_bytes().to_vec() }),
NetworkMessage::FilterAdd(FilterAdd { data: hash([29u8; 32]).as_ref().to_vec() }),
NetworkMessage::FilterAdd(FilterAdd { data: hash([29u8; 32]).into_inner().to_vec() }),
NetworkMessage::FilterClear,
NetworkMessage::GetCFilters(GetCFilters {
filter_type: 2,

View File

@ -309,9 +309,9 @@ impl Deserialize for schnorr::Signature {
impl Serialize for (XOnlyPublicKey, TapLeafHash) {
fn serialize(&self) -> Vec<u8> {
let ser_pk = self.0.serialize();
let mut buf = Vec::with_capacity(ser_pk.len() + self.1.as_ref().len());
let mut buf = Vec::with_capacity(ser_pk.len() + self.1.as_inner().len());
buf.extend(&ser_pk);
buf.extend(self.1.as_ref());
buf.extend(self.1.as_inner());
buf
}
}

View File

@ -97,6 +97,12 @@ macro_rules! hash_trait_impls {
serde_impl!(Hash, $bits / 8 $(, $gen: $gent)*);
borrow_slice_impl!(Hash $(, $gen: $gent)*);
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8; $bits / 8]> for Hash<$($gen),*> {
fn as_ref(&self) -> &[u8; $bits / 8] {
&self.0
}
}
impl<I: SliceIndex<[u8]> $(, $gen: $gent)*> Index<I> for Hash<$($gen),*> {
type Output = I::Output;

View File

@ -200,6 +200,12 @@ macro_rules! hash_newtype {
}
}
impl $crate::_export::_core::convert::AsRef<[u8; $len]> for $newtype {
fn as_ref(&self) -> &[u8; $len] {
AsRef::<[u8; $len]>::as_ref(&self.0)
}
}
impl<I: $crate::_export::_core::slice::SliceIndex<[u8]>> $crate::_export::_core::ops::Index<I> for $newtype {
type Output = I::Output;
@ -240,9 +246,17 @@ mod test {
use crate::{Hash, sha256};
#[test]
fn hash_as_ref() {
fn hash_as_ref_array() {
let hash = sha256::Hash::hash(&[3, 50]);
assert_eq!(hash.as_ref(), hash.as_inner());
let r = AsRef::<[u8; 32]>::as_ref(&hash);
assert_eq!(r, hash.as_inner());
}
#[test]
fn hash_as_ref_slice() {
let hash = sha256::Hash::hash(&[3, 50]);
let r = AsRef::<[u8]>::as_ref(&hash);
assert_eq!(r, hash.as_inner());
}
#[test]
@ -283,4 +297,18 @@ mod test {
let got = format!("{:#x}", TestHash::all_zeros());
assert_eq!(got, want)
}
#[test]
fn inner_hash_as_ref_array() {
let hash = TestHash::all_zeros();
let r = AsRef::<[u8; 32]>::as_ref(&hash);
assert_eq!(r, hash.as_inner());
}
#[test]
fn inner_hash_as_ref_slice() {
let hash = TestHash::all_zeros();
let r = AsRef::<[u8]>::as_ref(&hash);
assert_eq!(r, hash.as_inner());
}
}