@@ -209,6 +209,18 @@ macro_rules! round(
209209) ;
210210
211211impl HashEngine {
212+ /// Create a new [HashEngine] from a midstate.
213+ pub fn from_midstate ( midstate : Midstate , length : usize ) -> HashEngine {
214+ let mut ret = [ 0 ; 8 ] ;
215+ BigEndian :: read_u32_into ( & midstate[ ..] , & mut ret) ;
216+
217+ HashEngine {
218+ buffer : [ 0 ; BLOCK_SIZE ] ,
219+ h : ret,
220+ length : length,
221+ }
222+ }
223+
212224 // Algorithm copied from libsecp256k1
213225 fn process_block ( & mut self ) {
214226 debug_assert_eq ! ( self . buffer. len( ) , BLOCK_SIZE ) ;
@@ -399,6 +411,55 @@ mod tests {
399411 ) ;
400412 }
401413
414+ #[ test]
415+ fn engine_with_state ( ) {
416+ let mut engine = sha256:: Hash :: engine ( ) ;
417+ let midstate_engine = sha256:: HashEngine :: from_midstate ( engine. midstate ( ) , 0 ) ;
418+ // Fresh engine and engine initialized with fresh state should have same state
419+ assert_eq ! ( engine. h, midstate_engine. h) ;
420+
421+ // Midstate changes after writing 64 bytes
422+ engine. input ( & [ 1 ; 63 ] ) ;
423+ assert_eq ! ( engine. h, midstate_engine. h) ;
424+ engine. input ( & [ 2 ; 1 ] ) ;
425+ assert_ne ! ( engine. h, midstate_engine. h) ;
426+
427+ // Initializing an engine with midstate from another engine should result in
428+ // both engines producing the same hashes
429+ let data_vec = vec ! [ vec![ 3 ; 1 ] , vec![ 4 ; 63 ] , vec![ 5 ; 65 ] , vec![ 6 ; 66 ] ] ;
430+ for data in data_vec {
431+ let mut engine = engine. clone ( ) ;
432+ let mut midstate_engine =
433+ sha256:: HashEngine :: from_midstate ( engine. midstate ( ) , engine. length ) ;
434+ assert_eq ! ( engine. h, midstate_engine. h) ;
435+ assert_eq ! ( engine. length, midstate_engine. length) ;
436+ engine. input ( & data) ;
437+ midstate_engine. input ( & data) ;
438+ assert_eq ! ( engine. h, midstate_engine. h) ;
439+ let hash1 = sha256:: Hash :: from_engine ( engine) ;
440+ let hash2 = sha256:: Hash :: from_engine ( midstate_engine) ;
441+ assert_eq ! ( hash1, hash2) ;
442+ }
443+
444+ // Test that a specific midstate results in a specific hash. Midstate was
445+ // obtained by applying sha256 to sha256("MuSig coefficient")||sha256("MuSig
446+ // coefficient").
447+ static MIDSTATE : [ u8 ; 32 ] = [
448+ 0x0f , 0xd0 , 0x69 , 0x0c , 0xfe , 0xfe , 0xae , 0x97 , 0x99 , 0x6e , 0xac , 0x7f , 0x5c , 0x30 ,
449+ 0xd8 , 0x64 , 0x8c , 0x4a , 0x05 , 0x73 , 0xac , 0xa1 , 0xa2 , 0x2f , 0x6f , 0x43 , 0xb8 , 0x01 ,
450+ 0x85 , 0xce , 0x27 , 0xcd ,
451+ ] ;
452+ static HASH_EXPECTED : [ u8 ; 32 ] = [
453+ 0x18 , 0x84 , 0xe4 , 0x72 , 0x40 , 0x4e , 0xf4 , 0x5a , 0xb4 , 0x9c , 0x4e , 0xa4 , 0x9a , 0xe6 ,
454+ 0x23 , 0xa8 , 0x88 , 0x52 , 0x7f , 0x7d , 0x8a , 0x06 , 0x94 , 0x20 , 0x8f , 0xf1 , 0xf7 , 0xa9 ,
455+ 0xd5 , 0x69 , 0x09 , 0x59 ,
456+ ] ;
457+ let midstate_engine =
458+ sha256:: HashEngine :: from_midstate ( sha256:: Midstate :: from_inner ( MIDSTATE ) , 64 ) ;
459+ let hash = sha256:: Hash :: from_engine ( midstate_engine) ;
460+ assert_eq ! ( hash, sha256:: Hash ( HASH_EXPECTED ) ) ;
461+ }
462+
402463 #[ cfg( feature="serde" ) ]
403464 #[ test]
404465 fn sha256_serde ( ) {
0 commit comments