1616
1717//! Hash utilities.
1818
19- use codec:: Codec ;
19+ use codec:: { Codec , Decode } ;
2020use sp_std:: prelude:: Vec ;
2121use sp_io:: hashing:: { blake2_128, blake2_256, twox_64, twox_128, twox_256} ;
2222
@@ -64,6 +64,20 @@ pub trait ReversibleStorageHasher: StorageHasher {
6464 fn reverse ( x : & [ u8 ] ) -> & [ u8 ] ;
6565}
6666
67+ /// Trait to retrieve some info from hash of type `Key` encoded.
68+ pub trait StorageHasherInfo < Key > {
69+ /// Some info contained in the hash of type `Key` encoded.
70+ type Info ;
71+
72+ /// Decode the hash and then decode the info from the decoded hash.
73+ ///
74+ /// # WARNING
75+ ///
76+ /// Even if info is (), input must be modified to have read the entire encoded hash.
77+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
78+ -> Result < Self :: Info , codec:: Error > ;
79+ }
80+
6781/// Store the key directly.
6882pub struct Identity ;
6983impl StorageHasher for Identity {
@@ -77,6 +91,14 @@ impl ReversibleStorageHasher for Identity {
7791 x
7892 }
7993}
94+ impl < Key : Decode > StorageHasherInfo < Key > for Identity {
95+ type Info = Key ;
96+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
97+ -> Result < Self :: Info , codec:: Error >
98+ {
99+ Key :: decode ( input)
100+ }
101+ }
80102
81103/// Hash storage keys with `concat(twox64(key), key)`
82104pub struct Twox64Concat ;
@@ -95,6 +117,15 @@ impl ReversibleStorageHasher for Twox64Concat {
95117 & x[ 8 ..]
96118 }
97119}
120+ impl < Key : Decode > StorageHasherInfo < Key > for Twox64Concat {
121+ type Info = Key ;
122+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
123+ -> Result < Self :: Info , codec:: Error >
124+ {
125+ input. read ( & mut [ 0u8 ; 8 ] ) ?;
126+ Key :: decode ( input)
127+ }
128+ }
98129
99130/// Hash storage keys with `concat(blake2_128(key), key)`
100131pub struct Blake2_128Concat ;
@@ -113,6 +144,15 @@ impl ReversibleStorageHasher for Blake2_128Concat {
113144 & x[ 16 ..]
114145 }
115146}
147+ impl < Key : Decode > StorageHasherInfo < Key > for Blake2_128Concat {
148+ type Info = Key ;
149+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
150+ -> Result < Self :: Info , codec:: Error >
151+ {
152+ input. read ( & mut [ 0u8 ; 16 ] ) ?;
153+ Key :: decode ( input)
154+ }
155+ }
116156
117157/// Hash storage keys with blake2 128
118158pub struct Blake2_128 ;
@@ -122,6 +162,15 @@ impl StorageHasher for Blake2_128 {
122162 blake2_128 ( x)
123163 }
124164}
165+ impl < Key > StorageHasherInfo < Key > for Blake2_128 {
166+ type Info = ( ) ;
167+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
168+ -> Result < Self :: Info , codec:: Error >
169+ {
170+ input. read ( & mut [ 0u8 ; 16 ] ) ?;
171+ Ok ( ( ) )
172+ }
173+ }
125174
126175/// Hash storage keys with blake2 256
127176pub struct Blake2_256 ;
@@ -131,6 +180,15 @@ impl StorageHasher for Blake2_256 {
131180 blake2_256 ( x)
132181 }
133182}
183+ impl < Key > StorageHasherInfo < Key > for Blake2_256 {
184+ type Info = ( ) ;
185+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
186+ -> Result < Self :: Info , codec:: Error >
187+ {
188+ input. read ( & mut [ 0u8 ; 32 ] ) ?;
189+ Ok ( ( ) )
190+ }
191+ }
134192
135193/// Hash storage keys with twox 128
136194pub struct Twox128 ;
@@ -140,6 +198,15 @@ impl StorageHasher for Twox128 {
140198 twox_128 ( x)
141199 }
142200}
201+ impl < Key > StorageHasherInfo < Key > for Twox128 {
202+ type Info = ( ) ;
203+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
204+ -> Result < Self :: Info , codec:: Error >
205+ {
206+ input. read ( & mut [ 0u8 ; 16 ] ) ?;
207+ Ok ( ( ) )
208+ }
209+ }
143210
144211/// Hash storage keys with twox 256
145212pub struct Twox256 ;
@@ -149,10 +216,20 @@ impl StorageHasher for Twox256 {
149216 twox_256 ( x)
150217 }
151218}
219+ impl < Key > StorageHasherInfo < Key > for Twox256 {
220+ type Info = ( ) ;
221+ fn decode_hash_and_then_info < I : codec:: Input > ( input : & mut I )
222+ -> Result < Self :: Info , codec:: Error >
223+ {
224+ input. read ( & mut [ 0u8 ; 32 ] ) ?;
225+ Ok ( ( ) )
226+ }
227+ }
152228
153229#[ cfg( test) ]
154230mod tests {
155231 use super :: * ;
232+ use codec:: Encode ;
156233
157234 #[ test]
158235 fn test_twox_64_concat ( ) {
@@ -165,4 +242,38 @@ mod tests {
165242 let r = Blake2_128Concat :: hash ( b"foo" ) ;
166243 assert_eq ! ( r. split_at( 16 ) , ( & blake2_128( b"foo" ) [ ..] , & b"foo" [ ..] ) )
167244 }
245+
246+ #[ test]
247+ fn test_storage_hasher_info ( ) {
248+ type KeyType = [ u8 ; 15 ] ;
249+ let key: KeyType = [ 3u8 ; 15 ] ;
250+
251+ let mut r = & Identity :: hash ( & ( & key) . encode ( ) [ ..] ) [ ..] ;
252+ assert_eq ! ( <Identity as StorageHasherInfo <KeyType >>:: decode_hash_and_then_info( & mut r) , Ok ( key) ) ;
253+ assert_eq ! ( r. len( ) , 0 ) ; // Assert input has indeed decoded the hash.
254+
255+ let mut r = & Twox64Concat :: hash ( & ( & key) . encode ( ) [ ..] ) [ ..] ;
256+ assert_eq ! ( <Twox64Concat as StorageHasherInfo <KeyType >>:: decode_hash_and_then_info( & mut r) , Ok ( key) ) ;
257+ assert_eq ! ( r. len( ) , 0 ) ; // Assert input has indeed decoded the hash.
258+
259+ let mut r = & Twox128 :: hash ( & ( & key) . encode ( ) [ ..] ) [ ..] ;
260+ assert_eq ! ( <Twox128 as StorageHasherInfo <KeyType >>:: decode_hash_and_then_info( & mut r) , Ok ( ( ) ) ) ;
261+ assert_eq ! ( r. len( ) , 0 ) ; // Assert input has indeed decoded the hash.
262+
263+ let mut r = & Twox256 :: hash ( & ( & key) . encode ( ) [ ..] ) [ ..] ;
264+ assert_eq ! ( <Twox256 as StorageHasherInfo <KeyType >>:: decode_hash_and_then_info( & mut r) , Ok ( ( ) ) ) ;
265+ assert_eq ! ( r. len( ) , 0 ) ; // Assert input has indeed decoded the hash.
266+
267+ let mut r = & Blake2_128Concat :: hash ( & ( & key) . encode ( ) [ ..] ) [ ..] ;
268+ assert_eq ! ( <Blake2_128Concat as StorageHasherInfo <KeyType >>:: decode_hash_and_then_info( & mut r) , Ok ( key) ) ;
269+ assert_eq ! ( r. len( ) , 0 ) ; // Assert input has indeed decoded the hash.
270+
271+ let mut r = & Blake2_128 :: hash ( & ( & key) . encode ( ) [ ..] ) [ ..] ;
272+ assert_eq ! ( <Blake2_128 as StorageHasherInfo <KeyType >>:: decode_hash_and_then_info( & mut r) , Ok ( ( ) ) ) ;
273+ assert_eq ! ( r. len( ) , 0 ) ; // Assert input has indeed decoded the hash.
274+
275+ let mut r = & Blake2_256 :: hash ( & ( & key) . encode ( ) [ ..] ) [ ..] ;
276+ assert_eq ! ( <Blake2_256 as StorageHasherInfo <KeyType >>:: decode_hash_and_then_info( & mut r) , Ok ( ( ) ) ) ;
277+ assert_eq ! ( r. len( ) , 0 ) ; // Assert input has indeed decoded the hash.
278+ }
168279}
0 commit comments