thor_devkit/
utils.rs

1use blake2::{digest::consts::U32, Blake2b, Digest};
2use tiny_keccak::{Hasher, Keccak};
3
4type Blake2b256 = Blake2b<U32>;
5
6pub fn blake2_256<S: AsRef<[u8]>>(bytes: &[S]) -> [u8; 32] {
7    //! Compute blake2b hash with 32-byte digest.
8    //!
9    //! Builds a hash iteratively by updating with every element
10    //! of the input sequence.
11    let mut hasher = Blake2b256::new();
12    bytes.iter().for_each(|b| hasher.update(b));
13    hasher.finalize().into()
14}
15
16pub fn keccak<S: AsRef<[u8]>>(bytes: S) -> [u8; 32] {
17    //! Compute a keccak hash with 32-byte digest.
18    let mut hasher = Keccak::v256();
19    hasher.update(bytes.as_ref());
20    let mut hash = [0; 32];
21    hasher.finalize(&mut hash);
22    hash
23}
24
25#[cfg(feature = "serde")]
26pub(crate) mod unhex {
27    use crate::rlp::RLPError;
28    use crate::U256;
29    use rustc_hex::{FromHex, ToHex};
30    use serde::de::Error;
31    use serde::{Deserialize, Deserializer, Serializer};
32    use serde_with::de::DeserializeAs;
33    use serde_with::formats::{Format, Lowercase, Uppercase};
34    use serde_with::ser::SerializeAs;
35    use std::any::type_name;
36    use std::borrow::Cow;
37    use std::marker::PhantomData;
38
39    #[derive(Copy, Clone, Debug, Default)]
40    pub struct Hex<FORMAT: Format = Lowercase>(PhantomData<FORMAT>);
41
42    impl<T: AsRef<[u8]>> SerializeAs<T> for Hex<Lowercase> {
43        fn serialize_as<S: Serializer>(source: &T, serializer: S) -> Result<S::Ok, S::Error> {
44            serializer.serialize_str(&("0x".to_string() + &source.as_ref().to_hex::<String>()))
45        }
46    }
47
48    impl<T: AsRef<[u8]>> SerializeAs<T> for Hex<Uppercase> {
49        fn serialize_as<S: Serializer>(source: &T, serializer: S) -> Result<S::Ok, S::Error> {
50            serializer.serialize_str(
51                &("0x".to_string() + &source.as_ref().to_hex::<String>().to_uppercase()),
52            )
53        }
54    }
55
56    impl<'de, T, FORMAT> DeserializeAs<'de, T> for Hex<FORMAT>
57    where
58        T: TryFrom<Vec<u8>>,
59        FORMAT: Format,
60    {
61        fn deserialize_as<D: Deserializer<'de>>(deserializer: D) -> Result<T, D::Error> {
62            <Cow<'de, str> as Deserialize<'de>>::deserialize(deserializer)
63                .and_then(|s| {
64                    s.strip_prefix("0x")
65                        .unwrap_or(&s)
66                        .from_hex()
67                        .map_err(Error::custom)
68                })
69                .and_then(|vec: Vec<u8>| {
70                    let length = vec.len();
71                    vec.try_into().map_err(|_e: T::Error| {
72                        Error::custom(format!(
73                            "Can't convert a Byte Vector of length {} to {}",
74                            length,
75                            type_name::<T>(),
76                        ))
77                    })
78                })
79        }
80    }
81
82    pub trait BeBytesConvertible<const N: usize>
83    where
84        Self: Sized,
85    {
86        fn from_be_bytes(src: [u8; N]) -> Self;
87        fn to_be_bytes_(self) -> [u8; N];
88    }
89
90    macro_rules! impl_from_be_bytes {
91        ($t:ty) => {
92            impl BeBytesConvertible<{ <$t>::BITS as usize / 8 }> for $t {
93                fn from_be_bytes(src: [u8; <$t>::BITS as usize / 8]) -> Self {
94                    Self::from_be_bytes(src)
95                }
96                fn to_be_bytes_(self) -> [u8; <$t>::BITS as usize / 8] {
97                    self.to_be_bytes()
98                }
99            }
100        };
101    }
102    impl_from_be_bytes!(u64);
103    impl_from_be_bytes!(u32);
104    impl_from_be_bytes!(u16);
105    impl BeBytesConvertible<32> for U256 {
106        fn from_be_bytes(src: [u8; 32]) -> Self {
107            Self::from_big_endian(&src)
108        }
109        fn to_be_bytes_(self) -> [u8; 32] {
110            let mut buf = [0; 32];
111            self.to_big_endian(&mut buf);
112            buf
113        }
114    }
115
116    impl BeBytesConvertible<1> for u8 {
117        fn from_be_bytes(src: [u8; 1]) -> Self {
118            src[0]
119        }
120        fn to_be_bytes_(self) -> [u8; 1] {
121            [self]
122        }
123    }
124
125    #[derive(Copy, Clone, Debug, Default)]
126    pub struct HexNum<const N: usize, Type: BeBytesConvertible<N>, FORMAT: Format = Lowercase>(
127        PhantomData<Type>,
128        PhantomData<FORMAT>,
129    );
130
131    impl<const N: usize, T: Copy + BeBytesConvertible<N>> SerializeAs<T> for HexNum<N, T, Lowercase> {
132        fn serialize_as<S: Serializer>(source: &T, serializer: S) -> Result<S::Ok, S::Error> {
133            serializer
134                .serialize_str(&("0x".to_string() + &source.to_be_bytes_().to_hex::<String>()))
135        }
136    }
137
138    impl<const N: usize, T: Copy + BeBytesConvertible<N>> SerializeAs<T> for HexNum<N, T, Uppercase> {
139        fn serialize_as<S: Serializer>(source: &T, serializer: S) -> Result<S::Ok, S::Error> {
140            serializer.serialize_str(
141                &("0x".to_string() + &source.to_be_bytes_().to_hex::<String>().to_uppercase()),
142            )
143        }
144    }
145
146    impl<'de, const N: usize, Type: BeBytesConvertible<N>, T, FORMAT> DeserializeAs<'de, T>
147        for HexNum<N, Type, FORMAT>
148    where
149        T: From<Type>,
150        FORMAT: Format,
151    {
152        fn deserialize_as<D: Deserializer<'de>>(deserializer: D) -> Result<T, D::Error> {
153            <Cow<'de, str> as Deserialize<'de>>::deserialize(deserializer)
154                .and_then(|s| {
155                    let stripped = s.strip_prefix("0x").unwrap_or(&s);
156                    let padded = if stripped.len() % 2 == 0 {
157                        stripped.to_string()
158                    } else {
159                        "0".to_string() + stripped
160                    };
161                    padded.from_hex().map_err(Error::custom)
162                })
163                .and_then(|vec: Vec<u8>| {
164                    let length = vec.len();
165                    Ok(Type::from_be_bytes(static_left_pad::<N>(&vec).map_err(|_| {
166                        Error::custom(format!(
167                            "Can't convert a Byte Vector of length {} to {}",
168                            length,
169                            type_name::<Type>(),
170                        ))
171                    })?)
172                    .into())
173                })
174        }
175    }
176
177    #[inline]
178    #[cfg(not(tarpaulin_include))]
179    fn static_left_pad<const N: usize>(data: &[u8]) -> Result<[u8; N], RLPError> {
180        // Similar to RLP padding, but allows leading zero. Tested there.
181        if data.len() > N {
182            return Err(RLPError::Overflow);
183        }
184
185        let mut v = [0; N];
186
187        if data.is_empty() {
188            return Ok(v);
189        }
190
191        // SAFETY: length checked above
192        unsafe { v.get_unchecked_mut(N - data.len()..) }.copy_from_slice(data);
193        Ok(v)
194    }
195}
196
197#[cfg(feature = "serde")]
198#[cfg(test)]
199mod test {
200    use super::super::rlp::Bytes;
201    use super::super::U256;
202    use super::unhex::*;
203    use serde::{Deserialize, Serialize};
204    use serde_json::{from_str, json, to_value};
205    use serde_with::formats::{Lowercase, Uppercase};
206
207    #[test]
208    fn test_numbers() {
209        #[serde_with::serde_as]
210        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
211        struct Test {
212            #[serde_as(as = "HexNum<1, u8>")]
213            a: u8,
214            #[serde_as(as = "HexNum<2, u16>")]
215            b: u16,
216            #[serde_as(as = "HexNum<4, u32>")]
217            c: u32,
218            #[serde_as(as = "HexNum<8, u64>")]
219            d: u64,
220            #[serde_as(as = "HexNum<32, U256>")]
221            e: U256,
222        }
223        assert_eq!(
224            to_value(Test {
225                a: 0,
226                b: 0,
227                c: 0,
228                d: 0,
229                e: 0.into()
230            })
231            .expect("Works"),
232            json! {{
233                "a": "0x00",
234                "b": "0x0000",
235                "c": "0x00000000",
236                "d": "0x0000000000000000",
237                "e": "0x0000000000000000000000000000000000000000000000000000000000000000",
238            }}
239        );
240        assert_eq!(
241            from_str::<Test>(
242                r#"{
243                "a": "0x00",
244                "b": "0x0000",
245                "c": "0x00000000",
246                "d": "0x0000000000000000",
247                "e": "0x0000000000000000000000000000000000000000000000000000000000000000"
248            }"#
249            )
250            .expect("Must parse"),
251            Test {
252                a: 0,
253                b: 0,
254                c: 0,
255                d: 0,
256                e: 0.into()
257            },
258        );
259    }
260
261    #[test]
262    fn test_numbers_padding() {
263        #[serde_with::serde_as]
264        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
265        struct Test {
266            #[serde_as(as = "HexNum<2, u16>")]
267            a: u16,
268        }
269        assert_eq!(
270            from_str::<Test>(r#"{"a": "0x1"}"#).expect("Must parse"),
271            Test { a: 1_u16 },
272        );
273    }
274
275    #[test]
276    fn test_numbers_fail_too_long() {
277        #[serde_with::serde_as]
278        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
279        struct Test {
280            #[serde_as(as = "HexNum<2, u16>")]
281            a: u16,
282        }
283        assert_eq!(
284            from_str::<Test>(r#"{"a": "0x01010101"}"#)
285                .expect_err("Must not parse")
286                .to_string(),
287            "Can't convert a Byte Vector of length 4 to u16 at line 1 column 19"
288        );
289    }
290
291    #[test]
292    fn test_wrapped_numbers() {
293        #[serde_with::serde_as]
294        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
295        struct Test {
296            #[serde_as(as = "Option<HexNum<1, u8, Uppercase>>")]
297            a: Option<u8>,
298            #[serde_as(as = "Option<HexNum<1, u8>>")]
299            b: Option<u8>,
300            #[serde_as(as = "Vec<HexNum<2, u16, Lowercase>>")]
301            c: Vec<u16>,
302        }
303        assert_eq!(
304            to_value(Test {
305                a: Some(0x0F),
306                b: None,
307                c: vec![1, 0x0E],
308            })
309            .expect("Works"),
310            json! {{
311                "a": "0x0F",
312                "b": Option::<u8>::None,
313                "c": vec!["0x0001", "0x000e"],
314            }}
315        );
316        assert_eq!(
317            from_str::<Test>(
318                r#"{
319                "a": "0x0f",
320                "b": null,
321                "c": ["0x0001", "0x000E"]
322            }"#
323            )
324            .expect("Must parse"),
325            Test {
326                a: Some(0x0F),
327                b: None,
328                c: vec![1, 0x0E],
329            }
330        );
331    }
332
333    #[test]
334    fn test_hex_strings() {
335        #[serde_with::serde_as]
336        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
337        struct Test {
338            #[serde_as(as = "Option<Hex>")]
339            a: Option<Vec<u8>>,
340            #[serde_as(as = "Option<Hex<Lowercase>>")]
341            b: Option<Bytes>,
342            #[serde_as(as = "Option<Hex<Lowercase>>")]
343            c: Option<Bytes>,
344            #[serde_as(as = "Vec<Hex<Uppercase>>")]
345            d: Vec<Bytes>,
346            #[serde_as(as = "Vec<Hex<Uppercase>>")]
347            e: Vec<Bytes>,
348            #[serde_as(as = "Vec<Hex<Lowercase>>")]
349            f: Vec<Bytes>,
350        }
351        assert_eq!(
352            to_value(Test {
353                a: Some(vec![]),
354                b: None,
355                c: Some(Bytes::copy_from_slice(&b"\x01\x0F"[..])),
356                d: vec![Bytes::copy_from_slice(&b"\x01\x0F"[..])],
357                e: vec![],
358                f: vec![Bytes::copy_from_slice(&b"\x01\x0F"[..])],
359            })
360            .expect("Works"),
361            json! {{
362                "a": "0x",
363                "b": Option::<u8>::None,
364                "c": "0x010f",
365                "d": vec!["0x010F"],
366                "e": Vec::<u8>::new(),
367                "f": vec!["0x010f"]
368            }}
369        );
370        assert_eq!(
371            from_str::<Test>(
372                r#"{
373                "a": "0x",
374                "b": null,
375                "c": "0x010f",
376                "d": ["0x010F"],
377                "e": [],
378                "f": ["0x010f"]
379            }"#
380            )
381            .expect("Must parse"),
382            Test {
383                a: Some(vec![]),
384                b: None,
385                c: Some(Bytes::copy_from_slice(&b"\x01\x0F"[..])),
386                d: vec![Bytes::copy_from_slice(&b"\x01\x0F"[..])],
387                e: vec![],
388                f: vec![Bytes::copy_from_slice(&b"\x01\x0F"[..])],
389            }
390        );
391    }
392
393    #[test]
394    fn test_string_fail_too_long() {
395        #[serde_with::serde_as]
396        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
397        struct Test {
398            #[serde_as(as = "Hex")]
399            a: [u8; 3],
400        }
401        assert_eq!(
402            from_str::<Test>(r#"{"a": "0x01010101"}"#)
403                .expect_err("Must not parse")
404                .to_string(),
405            "Can't convert a Byte Vector of length 4 to [u8; 3] at line 1 column 19"
406        );
407    }
408
409    #[test]
410    fn test_string_fail_too_short() {
411        #[serde_with::serde_as]
412        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
413        struct Test {
414            #[serde_as(as = "Hex")]
415            a: [u8; 5],
416        }
417        assert_eq!(
418            from_str::<Test>(r#"{"a": "0x01010101"}"#)
419                .expect_err("Must not parse")
420                .to_string(),
421            "Can't convert a Byte Vector of length 4 to [u8; 5] at line 1 column 19"
422        );
423    }
424
425    #[test]
426    fn test_string_fail_bad_hex() {
427        #[serde_with::serde_as]
428        #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
429        struct Test {
430            #[serde_as(as = "Hex")]
431            a: [u8; 5],
432        }
433        assert_eq!(
434            from_str::<Test>(r#"{"a": "0x0101010G"}"#)
435                .expect_err("Must not parse")
436                .to_string(),
437            "Invalid character 'G' at position 7 at line 1 column 19"
438        );
439    }
440}