Skip to content
This repository was archived by the owner on Nov 30, 2022. It is now read-only.

Commit faa02e0

Browse files
committed
Add sha256::Midstate type
1 parent d2d83c8 commit faa02e0

File tree

1 file changed

+63
-6
lines changed

1 file changed

+63
-6
lines changed

src/sha256.rs

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
use byteorder::{ByteOrder, BigEndian};
1818

19+
use hex;
1920
use HashEngine as EngineTrait;
2021
use Hash as HashTrait;
2122
use Error;
@@ -42,13 +43,13 @@ impl Clone for HashEngine {
4243
}
4344

4445
impl EngineTrait for HashEngine {
45-
type MidState = [u8; 32];
46+
type MidState = Midstate;
4647

4748
#[cfg(not(feature = "fuzztarget"))]
48-
fn midstate(&self) -> [u8; 32] {
49+
fn midstate(&self) -> Midstate {
4950
let mut ret = [0; 32];
5051
BigEndian::write_u32_into(&self.h, &mut ret);
51-
ret
52+
Midstate::from_inner(ret)
5253
}
5354

5455
#[cfg(feature = "fuzztarget")]
@@ -108,7 +109,7 @@ impl HashTrait for Hash {
108109
e.write_u64::<BigEndian>(8 * data_len).unwrap();
109110
debug_assert_eq!(e.length % BLOCK_SIZE, 0);
110111

111-
Hash(e.midstate())
112+
Hash(e.midstate().into_inner())
112113
}
113114

114115
#[cfg(feature = "fuzztarget")]
@@ -133,6 +134,62 @@ impl HashTrait for Hash {
133134
}
134135
}
135136

137+
/// Output of the SHA256 hash function
138+
#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
139+
pub struct Midstate([u8; 32]);
140+
141+
hex_fmt_impl!(Debug, Midstate);
142+
hex_fmt_impl!(Display, Midstate);
143+
hex_fmt_impl!(LowerHex, Midstate);
144+
index_impl!(Midstate);
145+
serde_impl!(Midstate, 32);
146+
borrow_slice_impl!(Midstate);
147+
148+
impl Midstate {
149+
/// Length of the midstate, in bytes.
150+
const LEN: usize = 32;
151+
152+
/// Flag indicating whether user-visible serializations of this hash
153+
/// should be backward. For some reason Satoshi decided this should be
154+
/// true for `Sha256dHash`, so here we are.
155+
const DISPLAY_BACKWARD: bool = true;
156+
157+
/// Construct a new midstate from the inner value.
158+
pub fn from_inner(inner: [u8; 32]) -> Self {
159+
Midstate(inner)
160+
}
161+
162+
/// Copies a byte slice into the [Midstate] object.
163+
pub fn from_slice(sl: &[u8]) -> Result<Midstate, Error> {
164+
if sl.len() != Self::LEN {
165+
Err(Error::InvalidLength(Self::LEN, sl.len()))
166+
} else {
167+
let mut ret = [0; 32];
168+
ret.copy_from_slice(sl);
169+
Ok(Midstate(ret))
170+
}
171+
}
172+
173+
/// Unwraps the [Midstate] and returns the underlying byte array.
174+
pub fn into_inner(self) -> [u8; 32] {
175+
self.0
176+
}
177+
}
178+
179+
impl hex::FromHex for Midstate {
180+
/// Parses a hex string as a hash object
181+
fn from_hex(s: &str) -> Result<Self, Error> {
182+
if s.len() != 2 * Self::LEN {
183+
return Err(Error::InvalidLength(2 * Self::LEN, s.len()));
184+
}
185+
186+
// Self::DISPLAY_BACKWARD is true
187+
let mut vec = Vec::<u8>::from_hex(s)?;
188+
vec.reverse();
189+
Self::from_slice(&vec)
190+
}
191+
}
192+
136193
macro_rules! Ch( ($x:expr, $y:expr, $z:expr) => ($z ^ ($x & ($y ^ $z))) );
137194
macro_rules! Maj( ($x:expr, $y:expr, $z:expr) => (($x & $y) | ($z & ($x | $y))) );
138195
macro_rules! Sigma0( ($x:expr) => (circular_lshift32!(30, $x) ^ circular_lshift32!(19, $x) ^ circular_lshift32!(10, $x)) ); macro_rules! Sigma1( ($x:expr) => (circular_lshift32!(26, $x) ^ circular_lshift32!(21, $x) ^ circular_lshift32!(7, $x)) );
@@ -336,12 +393,12 @@ mod tests {
336393
assert_eq!(
337394
engine.midstate(),
338395
// RPC output
339-
[
396+
sha256::Midstate::from_inner([
340397
0x0b, 0xcf, 0xe0, 0xe5, 0x4e, 0x6c, 0xc7, 0xd3,
341398
0x4f, 0x4f, 0x7c, 0x1d, 0xf0, 0xb0, 0xf5, 0x03,
342399
0xf2, 0xf7, 0x12, 0x91, 0x2a, 0x06, 0x05, 0xb4,
343400
0x14, 0xed, 0x33, 0x7f, 0x7f, 0x03, 0x2e, 0x03,
344-
]
401+
])
345402
);
346403
}
347404

0 commit comments

Comments
 (0)