1616
1717use byteorder:: { ByteOrder , BigEndian } ;
1818
19+ use hex;
1920use HashEngine as EngineTrait ;
2021use Hash as HashTrait ;
2122use Error ;
@@ -42,13 +43,13 @@ impl Clone for HashEngine {
4243}
4344
4445impl 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+
136193macro_rules! Ch ( ( $x: expr, $y: expr, $z: expr) => ( $z ^ ( $x & ( $y ^ $z) ) ) ) ;
137194macro_rules! Maj ( ( $x: expr, $y: expr, $z: expr) => ( ( $x & $y) | ( $z & ( $x | $y) ) ) ) ;
138195macro_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