hashes: stop exposing engine/from_engine and general hashing methods in hash_newtype
We manually implement these methods (and the GeneralHash trait) on newtypes around sha256t::Hash, because tagged hashes require a bit more work. In the next commit (API diff) you will see that this affects two hashes, which are the only things that appear green in the diff. Users who want to implement their own engine/from_engine types now need to do it on their own. We do this for the non-Taproot sighash types in `bitcoin` (though only privately) to demonstrate that it's possible.
This commit is contained in:
parent
8c4899f2cc
commit
91265977f8
|
@ -58,16 +58,13 @@ impl_message_from_hash!(SegwitV0Sighash);
|
|||
// Implement private engine/from_engine methods for use within this module;
|
||||
// but outside of it, it should not be possible to construct these hash
|
||||
// types from arbitrary data (except by casting via to/from_byte_array).
|
||||
//
|
||||
// These will be uncommented in the next commit; in this one they cause
|
||||
// "duplicate definition" errors against the `hash_newtype!` macro.
|
||||
impl LegacySighash {
|
||||
//fn engine() -> sha256::HashEngine { sha256d::Hash::engine() }
|
||||
//fn from_engine(e: sha256::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) }
|
||||
fn engine() -> sha256::HashEngine { sha256d::Hash::engine() }
|
||||
fn from_engine(e: sha256::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) }
|
||||
}
|
||||
impl SegwitV0Sighash {
|
||||
//fn engine() -> sha256::HashEngine { sha256d::Hash::engine() }
|
||||
//fn from_engine(e: sha256::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) }
|
||||
fn engine() -> sha256::HashEngine { sha256d::Hash::engine() }
|
||||
fn from_engine(e: sha256::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) }
|
||||
}
|
||||
|
||||
sha256t_hash_newtype! {
|
||||
|
|
|
@ -255,9 +255,17 @@ mod tests {
|
|||
struct TestNewtype2(sha256d::Hash);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
const DUMMY: TestNewtype = TestNewtype::from_byte_array([
|
||||
0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
|
||||
0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a,
|
||||
0x14, 0x25, 0x36, 0x47, 0x58, 0x69, 0x7a, 0x8b,
|
||||
0x15, 0x26, 0x37, 0x48, 0x59, 0x6a, 0x7b, 0x8c,
|
||||
]);
|
||||
|
||||
#[test]
|
||||
fn convert_newtypes() {
|
||||
let h1 = TestNewtype::hash(&[]);
|
||||
let h1 = DUMMY;
|
||||
let h2: TestNewtype2 = h1.to_raw_hash().into();
|
||||
assert_eq!(&h1[..], &h2[..]);
|
||||
|
||||
|
@ -268,7 +276,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn newtype_fmt_roundtrip() {
|
||||
let orig = TestNewtype::hash(&[]);
|
||||
let orig = DUMMY;
|
||||
let hex = format!("{}", orig);
|
||||
let rinsed = hex.parse::<TestNewtype>().expect("failed to parse hex");
|
||||
assert_eq!(rinsed, orig)
|
||||
|
|
|
@ -207,6 +207,58 @@ macro_rules! sha256t_hash_newtype {
|
|||
$(#[$($hash_attr)*])*
|
||||
$hash_vis struct $hash_name($(#[$($field_attr)*])* $crate::sha256t::Hash<$tag>);
|
||||
}
|
||||
|
||||
impl $hash_name {
|
||||
/// Constructs a new engine.
|
||||
#[allow(unused)] // the user of macro may not need this
|
||||
pub fn engine() -> <$hash_name as $crate::GeneralHash>::Engine {
|
||||
<$hash_name as $crate::GeneralHash>::engine()
|
||||
}
|
||||
|
||||
/// Produces a hash from the current state of a given engine.
|
||||
#[allow(unused)] // the user of macro may not need this
|
||||
pub fn from_engine(e: <$hash_name as $crate::GeneralHash>::Engine) -> Self {
|
||||
<$hash_name as $crate::GeneralHash>::from_engine(e)
|
||||
}
|
||||
|
||||
/// Hashes some bytes.
|
||||
#[allow(unused)] // the user of macro may not need this
|
||||
pub fn hash(data: &[u8]) -> Self {
|
||||
use $crate::HashEngine;
|
||||
|
||||
let mut engine = Self::engine();
|
||||
engine.input(data);
|
||||
Self::from_engine(engine)
|
||||
}
|
||||
|
||||
/// Hashes all the byte slices retrieved from the iterator together.
|
||||
#[allow(unused)] // the user of macro may not need this
|
||||
pub fn hash_byte_chunks<B, I>(byte_slices: I) -> Self
|
||||
where
|
||||
B: AsRef<[u8]>,
|
||||
I: IntoIterator<Item = B>,
|
||||
{
|
||||
use $crate::HashEngine;
|
||||
|
||||
let mut engine = Self::engine();
|
||||
for slice in byte_slices {
|
||||
engine.input(slice.as_ref());
|
||||
}
|
||||
Self::from_engine(engine)
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::GeneralHash for $hash_name {
|
||||
type Engine = <$crate::sha256t::Hash<$tag> as $crate::GeneralHash>::Engine;
|
||||
|
||||
fn engine() -> Self::Engine {
|
||||
<$crate::sha256t::Hash<$tag> as $crate::GeneralHash>::engine()
|
||||
}
|
||||
|
||||
fn from_engine(e: Self::Engine) -> $hash_name {
|
||||
Self::from(<$crate::sha256t::Hash<$tag> as $crate::GeneralHash>::from_engine(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -209,46 +209,11 @@ macro_rules! hash_newtype {
|
|||
&self.0
|
||||
}
|
||||
|
||||
/// Constructs a new engine.
|
||||
pub fn engine() -> <$hash as $crate::GeneralHash>::Engine {
|
||||
<$hash as $crate::GeneralHash>::engine()
|
||||
}
|
||||
|
||||
/// Produces a hash from the current state of a given engine.
|
||||
pub fn from_engine(e: <$hash as $crate::GeneralHash>::Engine) -> Self {
|
||||
Self::from(<$hash as $crate::GeneralHash>::from_engine(e))
|
||||
}
|
||||
|
||||
/// Copies a byte slice into a hash object.
|
||||
pub fn from_slice(sl: &[u8]) -> $crate::_export::_core::result::Result<$newtype, $crate::FromSliceError> {
|
||||
Ok($newtype(<$hash as $crate::Hash>::from_slice(sl)?))
|
||||
}
|
||||
|
||||
/// Hashes some bytes.
|
||||
#[allow(unused)] // the user of macro may not need this
|
||||
pub fn hash(data: &[u8]) -> Self {
|
||||
use $crate::HashEngine;
|
||||
|
||||
let mut engine = Self::engine();
|
||||
engine.input(data);
|
||||
Self::from_engine(engine)
|
||||
}
|
||||
|
||||
/// Hashes all the byte slices retrieved from the iterator together.
|
||||
pub fn hash_byte_chunks<B, I>(byte_slices: I) -> Self
|
||||
where
|
||||
B: AsRef<[u8]>,
|
||||
I: IntoIterator<Item = B>,
|
||||
{
|
||||
use $crate::HashEngine;
|
||||
|
||||
let mut engine = Self::engine();
|
||||
for slice in byte_slices {
|
||||
engine.input(slice.as_ref());
|
||||
}
|
||||
Self::from_engine(engine)
|
||||
}
|
||||
|
||||
/// Returns the underlying byte array.
|
||||
pub const fn to_byte_array(self) -> <$hash as $crate::Hash>::Bytes {
|
||||
self.0.to_byte_array()
|
||||
|
@ -296,19 +261,6 @@ macro_rules! hash_newtype {
|
|||
fn from_byte_array(bytes: Self::Bytes) -> Self { Self::from_byte_array(bytes) }
|
||||
}
|
||||
|
||||
// To be dropped in the next commit
|
||||
impl $crate::GeneralHash for $newtype {
|
||||
type Engine = <$hash as $crate::GeneralHash>::Engine;
|
||||
|
||||
fn engine() -> Self::Engine {
|
||||
<$hash as $crate::GeneralHash>::engine()
|
||||
}
|
||||
|
||||
fn from_engine(e: <$hash as $crate::GeneralHash>::Engine) -> $newtype {
|
||||
Self::from_engine(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::_export::_core::str::FromStr for $newtype {
|
||||
type Err = $crate::hex::HexToArrayError;
|
||||
fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> {
|
||||
|
|
Loading…
Reference in New Issue