@@ -32,24 +32,24 @@ pub struct Entry {
3232#[ derive( Debug , PartialEq , Eq , Clone ) ]
3333pub enum Event {
3434 Tick ,
35- UserDataKey ( u64 ) ,
35+ UserDataKey ( Sha256Hash ) ,
3636}
3737
3838impl Entry {
3939 /// Creates a Entry from the number of hashes 'num_hashes' since the previous event
4040 /// and that resulting 'end_hash'.
4141 pub fn new_tick ( num_hashes : u64 , end_hash : & Sha256Hash ) -> Self {
42- let event = Event :: Tick ;
4342 Entry {
4443 num_hashes,
4544 end_hash : * end_hash,
46- event,
45+ event : Event :: Tick ,
4746 }
4847 }
4948
5049 /// Verifies self.end_hash is the result of hashing a 'start_hash' 'self.num_hashes' times.
50+ /// If the event is a UserDataKey, then hash that as well.
5151 pub fn verify ( self : & Self , start_hash : & Sha256Hash ) -> bool {
52- self . end_hash == next_tick ( start_hash, self . num_hashes ) . end_hash
52+ self . end_hash == next_hash ( start_hash, self . num_hashes , & self . event )
5353 }
5454}
5555
@@ -60,13 +60,36 @@ pub fn hash(val: &[u8]) -> Sha256Hash {
6060 hasher. result ( )
6161}
6262
63- /// Creates the next Tick Entry 'num_hashes' after 'start_hash'.
64- pub fn next_tick ( start_hash : & Sha256Hash , num_hashes : u64 ) -> Entry {
63+ /// Return the hash of the given hash extended with the given value.
64+ pub fn extend_and_hash ( end_hash : & Sha256Hash , val : & [ u8 ] ) -> Sha256Hash {
65+ let mut hash_data = end_hash. to_vec ( ) ;
66+ hash_data. extend_from_slice ( val) ;
67+ hash ( & hash_data)
68+ }
69+
70+ pub fn next_hash ( start_hash : & Sha256Hash , num_hashes : u64 , event : & Event ) -> Sha256Hash {
6571 let mut end_hash = * start_hash;
6672 for _ in 0 ..num_hashes {
6773 end_hash = hash ( & end_hash) ;
6874 }
69- Entry :: new_tick ( num_hashes, & end_hash)
75+ if let Event :: UserDataKey ( key) = * event {
76+ return extend_and_hash ( & end_hash, & key) ;
77+ }
78+ end_hash
79+ }
80+
81+ /// Creates the next Tick Entry 'num_hashes' after 'start_hash'.
82+ pub fn next_entry ( start_hash : & Sha256Hash , num_hashes : u64 , event : Event ) -> Entry {
83+ Entry {
84+ num_hashes,
85+ end_hash : next_hash ( start_hash, num_hashes, & event) ,
86+ event,
87+ }
88+ }
89+
90+ /// Creates the next Tick Entry 'num_hashes' after 'start_hash'.
91+ pub fn next_tick ( start_hash : & Sha256Hash , num_hashes : u64 ) -> Entry {
92+ next_entry ( start_hash, num_hashes, Event :: Tick )
7093}
7194
7295/// Verifies the hashes and counts of a slice of events are all consistent.
@@ -86,13 +109,16 @@ pub fn verify_slice_seq(events: &[Entry], start_hash: &Sha256Hash) -> bool {
86109
87110/// Create a vector of Ticks of length 'len' from 'start_hash' hash and 'num_hashes'.
88111pub fn create_ticks ( start_hash : & Sha256Hash , num_hashes : u64 , len : usize ) -> Vec < Entry > {
89- use itertools:: unfold;
90- let mut events = unfold ( * start_hash, |state| {
91- let event = next_tick ( state, num_hashes) ;
92- * state = event. end_hash ;
93- return Some ( event) ;
94- } ) ;
95- events. by_ref ( ) . take ( len) . collect ( )
112+ use std:: iter;
113+ let mut end_hash = * start_hash;
114+ iter:: repeat ( Event :: Tick )
115+ . take ( len)
116+ . map ( |event| {
117+ let entry = next_entry ( & end_hash, num_hashes, event) ;
118+ end_hash = entry. end_hash ;
119+ entry
120+ } )
121+ . collect ( )
96122}
97123
98124#[ cfg( test) ]
@@ -138,6 +164,32 @@ mod tests {
138164 verify_slice_generic ( verify_slice_seq) ;
139165 }
140166
167+ #[ test]
168+ fn test_reorder_attack ( ) {
169+ let zero = Sha256Hash :: default ( ) ;
170+ let one = hash ( & zero) ;
171+
172+ // First, verify UserData events
173+ let mut end_hash = zero;
174+ let events = [ Event :: UserDataKey ( zero) , Event :: UserDataKey ( one) ] ;
175+ let mut entries: Vec < Entry > = events
176+ . iter ( )
177+ . map ( |event| {
178+ let entry = next_entry ( & end_hash, 0 , event. clone ( ) ) ;
179+ end_hash = entry. end_hash ;
180+ entry
181+ } )
182+ . collect ( ) ;
183+ assert ! ( verify_slice( & entries, & zero) ) ; // inductive step
184+
185+ // Next, swap only two UserData events and ensure verification fails.
186+ let event0 = entries[ 0 ] . event . clone ( ) ;
187+ let event1 = entries[ 1 ] . event . clone ( ) ;
188+ entries[ 0 ] . event = event1;
189+ entries[ 1 ] . event = event0;
190+ assert ! ( !verify_slice( & entries, & zero) ) ; // inductive step
191+ }
192+
141193}
142194
143195#[ cfg( all( feature = "unstable" , test) ) ]
0 commit comments