1616
1717use byteorder:: { ByteOrder , BigEndian } ;
1818
19+ use hex;
1920use HashEngine as EngineTrait ;
2021use Hash as HashTrait ;
2122use Error ;
@@ -42,20 +43,20 @@ 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 ( ret)
5253 }
5354
5455 #[ cfg( feature = "fuzztarget" ) ]
55- fn midstate ( & self ) -> [ u8 ; 32 ] {
56+ fn midstate ( & self ) -> Midstate {
5657 let mut ret = [ 0 ; 32 ] ;
5758 ret. copy_from_slice ( & self . buffer [ ..32 ] ) ;
58- ret
59+ Midstate ( ret)
5960 }
6061
6162 const BLOCK_SIZE : usize = 64 ;
@@ -104,12 +105,12 @@ impl HashTrait for Hash {
104105 e. write_u64 :: < BigEndian > ( 8 * data_len) . unwrap ( ) ;
105106 debug_assert_eq ! ( e. length % BLOCK_SIZE , 0 ) ;
106107
107- Hash ( e. midstate ( ) )
108+ Hash ( e. midstate ( ) . into_inner ( ) )
108109 }
109110
110111 #[ cfg( feature = "fuzztarget" ) ]
111112 fn from_engine ( e : HashEngine ) -> Hash {
112- Hash ( e. midstate ( ) )
113+ Hash ( e. midstate ( ) . into_inner ( ) )
113114 }
114115
115116 const LEN : usize = 32 ;
@@ -133,6 +134,59 @@ 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+ fn from_byte_iter < I > ( iter : I ) -> Result < Self , Error >
181+ where I : Iterator < Item =Result < u8 , Error > > +
182+ ExactSizeIterator +
183+ DoubleEndedIterator ,
184+ {
185+ // DISPLAY_BACKWARD is true
186+ Ok ( Midstate :: from_inner ( hex:: FromHex :: from_byte_iter ( iter. rev ( ) ) ?) )
187+ }
188+ }
189+
136190macro_rules! Ch ( ( $x: expr, $y: expr, $z: expr) => ( $z ^ ( $x & ( $y ^ $z) ) ) ) ;
137191macro_rules! Maj ( ( $x: expr, $y: expr, $z: expr) => ( ( $x & $y) | ( $z & ( $x | $y) ) ) ) ;
138192macro_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) ) ) ;
@@ -155,6 +209,23 @@ macro_rules! round(
155209) ;
156210
157211impl HashEngine {
212+ /// Create a new [HashEngine] from a midstate.
213+ ///
214+ /// Be aware that this method panics when [length] is
215+ /// not a multiple of the block size.
216+ pub fn from_midstate ( midstate : Midstate , length : usize ) -> HashEngine {
217+ assert ! ( length % BLOCK_SIZE == 0 , "length is no multiple of the block size" ) ;
218+
219+ let mut ret = [ 0 ; 8 ] ;
220+ BigEndian :: read_u32_into ( & midstate[ ..] , & mut ret) ;
221+
222+ HashEngine {
223+ buffer : [ 0 ; BLOCK_SIZE ] ,
224+ h : ret,
225+ length : length,
226+ }
227+ }
228+
158229 // Algorithm copied from libsecp256k1
159230 fn process_block ( & mut self ) {
160231 debug_assert_eq ! ( self . buffer. len( ) , BLOCK_SIZE ) ;
@@ -336,15 +407,64 @@ mod tests {
336407 assert_eq ! (
337408 engine. midstate( ) ,
338409 // RPC output
339- [
410+ sha256 :: Midstate :: from_inner ( [
340411 0x0b , 0xcf , 0xe0 , 0xe5 , 0x4e , 0x6c , 0xc7 , 0xd3 ,
341412 0x4f , 0x4f , 0x7c , 0x1d , 0xf0 , 0xb0 , 0xf5 , 0x03 ,
342413 0xf2 , 0xf7 , 0x12 , 0x91 , 0x2a , 0x06 , 0x05 , 0xb4 ,
343414 0x14 , 0xed , 0x33 , 0x7f , 0x7f , 0x03 , 0x2e , 0x03 ,
344- ]
415+ ] )
345416 ) ;
346417 }
347418
419+ #[ test]
420+ fn engine_with_state ( ) {
421+ let mut engine = sha256:: Hash :: engine ( ) ;
422+ let midstate_engine = sha256:: HashEngine :: from_midstate ( engine. midstate ( ) , 0 ) ;
423+ // Fresh engine and engine initialized with fresh state should have same state
424+ assert_eq ! ( engine. h, midstate_engine. h) ;
425+
426+ // Midstate changes after writing 64 bytes
427+ engine. input ( & [ 1 ; 63 ] ) ;
428+ assert_eq ! ( engine. h, midstate_engine. h) ;
429+ engine. input ( & [ 2 ; 1 ] ) ;
430+ assert_ne ! ( engine. h, midstate_engine. h) ;
431+
432+ // Initializing an engine with midstate from another engine should result in
433+ // both engines producing the same hashes
434+ let data_vec = vec ! [ vec![ 3 ; 1 ] , vec![ 4 ; 63 ] , vec![ 5 ; 65 ] , vec![ 6 ; 66 ] ] ;
435+ for data in data_vec {
436+ let mut engine = engine. clone ( ) ;
437+ let mut midstate_engine =
438+ sha256:: HashEngine :: from_midstate ( engine. midstate ( ) , engine. length ) ;
439+ assert_eq ! ( engine. h, midstate_engine. h) ;
440+ assert_eq ! ( engine. length, midstate_engine. length) ;
441+ engine. input ( & data) ;
442+ midstate_engine. input ( & data) ;
443+ assert_eq ! ( engine. h, midstate_engine. h) ;
444+ let hash1 = sha256:: Hash :: from_engine ( engine) ;
445+ let hash2 = sha256:: Hash :: from_engine ( midstate_engine) ;
446+ assert_eq ! ( hash1, hash2) ;
447+ }
448+
449+ // Test that a specific midstate results in a specific hash. Midstate was
450+ // obtained by applying sha256 to sha256("MuSig coefficient")||sha256("MuSig
451+ // coefficient").
452+ static MIDSTATE : [ u8 ; 32 ] = [
453+ 0x0f , 0xd0 , 0x69 , 0x0c , 0xfe , 0xfe , 0xae , 0x97 , 0x99 , 0x6e , 0xac , 0x7f , 0x5c , 0x30 ,
454+ 0xd8 , 0x64 , 0x8c , 0x4a , 0x05 , 0x73 , 0xac , 0xa1 , 0xa2 , 0x2f , 0x6f , 0x43 , 0xb8 , 0x01 ,
455+ 0x85 , 0xce , 0x27 , 0xcd ,
456+ ] ;
457+ static HASH_EXPECTED : [ u8 ; 32 ] = [
458+ 0x18 , 0x84 , 0xe4 , 0x72 , 0x40 , 0x4e , 0xf4 , 0x5a , 0xb4 , 0x9c , 0x4e , 0xa4 , 0x9a , 0xe6 ,
459+ 0x23 , 0xa8 , 0x88 , 0x52 , 0x7f , 0x7d , 0x8a , 0x06 , 0x94 , 0x20 , 0x8f , 0xf1 , 0xf7 , 0xa9 ,
460+ 0xd5 , 0x69 , 0x09 , 0x59 ,
461+ ] ;
462+ let midstate_engine =
463+ sha256:: HashEngine :: from_midstate ( sha256:: Midstate :: from_inner ( MIDSTATE ) , 64 ) ;
464+ let hash = sha256:: Hash :: from_engine ( midstate_engine) ;
465+ assert_eq ! ( hash, sha256:: Hash ( HASH_EXPECTED ) ) ;
466+ }
467+
348468 #[ cfg( feature="serde" ) ]
349469 #[ test]
350470 fn sha256_serde ( ) {
0 commit comments