reweb3/eip/eip712/serde/
hashstruct.rs

1//! EIP712 `encodeData` implementation using the serde [`Serialize`] framework.
2
3use std::{collections::HashMap, str::FromStr};
4
5use crate::primitives::{Address, Bytes, Hex, H256, U256};
6use regex::Regex;
7use serde::{ser, Serialize, Serializer};
8use sha3::{Digest, Keccak256};
9
10use super::TypeDefinition;
11
12#[derive(Debug, thiserror::Error)]
13pub enum EncodeDataError {
14    #[error("{0}")]
15    Unknown(String),
16
17    #[error("Unsupport type for eip712, {0}")]
18    UnsupportType(String),
19
20    #[error("Type definition not found, {0}")]
21    TypeDefinitionNotFound(String),
22
23    #[error("Close tuple before calling start_tuple function")]
24    EndTuple,
25    #[error("Call start_tuple first, eip712 root type must be a structure")]
26    StartTuple,
27    #[error("start_tuple and end_tuple must be called in pairs")]
28    UnclosedTuple,
29    #[error("Encode data is empty")]
30    Empty,
31
32    #[error("Bytes32OutofRange: {0}")]
33    Bytes32OutofRange(String),
34
35    #[error("IntOutofRange: {0}")]
36    IntOutofRange(String),
37}
38
39impl ser::Error for EncodeDataError {
40    fn custom<T>(msg: T) -> Self
41    where
42        T: std::fmt::Display,
43    {
44        Self::Unknown(msg.to_string())
45    }
46}
47
48#[derive(Debug, Default)]
49struct TupleEncoder {
50    names: Vec<String>,
51    fields: Vec<[u8; 32]>,
52}
53
54impl TupleEncoder {
55    fn append_element(&mut self, data: [u8; 32]) {
56        self.fields.push(data);
57    }
58
59    fn last_name(&self) -> Option<&String> {
60        self.names.last()
61    }
62
63    fn append_element_name(&mut self, name: &str) {
64        log::debug!("append element {} index {}", name, self.names.len());
65        self.names.push(name.to_owned());
66    }
67
68    fn finalize(self, type_hash: [u8; 32], definition: TypeDefinition) -> [u8; 32] {
69        let mut hasher = Keccak256::new();
70
71        hasher.update(&type_hash);
72
73        for field in definition {
74            let index = self
75                .names
76                .iter()
77                .enumerate()
78                .find(|(_, n)| n.as_str() == field.name)
79                .map(|(index, _)| index)
80                .unwrap();
81
82            log::debug!(
83                "hash update element {} with index {}: {}",
84                field.name,
85                index,
86                Hex(&self.fields[index])
87            );
88
89            hasher.update(&self.fields[index])
90        }
91
92        hasher.finalize().into()
93    }
94}
95
96#[derive(Debug)]
97pub struct EIP712StructHasher<'a> {
98    hashed: Option<[u8; 32]>,
99    tuple_stack: Vec<TupleEncoder>,
100    types: &'a HashMap<String, TypeDefinition>,
101    primary_type: &'a str,
102    type_stack: Vec<(String, TypeDefinition)>,
103}
104
105fn extract_type_name(name: &str) -> String {
106    let regex = Regex::new(r#"^([^\[]+)\[\d*\]$"#).unwrap();
107
108    if let Some(caps) = regex.captures(name) {
109        caps[1].to_owned()
110    } else {
111        name.to_owned()
112    }
113}
114
115impl<'a> EIP712StructHasher<'a> {
116    /// Returns json string for types, and close serializer.
117    pub fn finalize(mut self) -> Result<[u8; 32], EncodeDataError> {
118        if !self.tuple_stack.is_empty() {
119            return Err(EncodeDataError::UnclosedTuple);
120        }
121
122        if let Some(hashed) = self.hashed.take() {
123            Ok(hashed)
124        } else {
125            return Err(EncodeDataError::Empty);
126        }
127    }
128
129    fn start_encode_type(&mut self, name: &str) -> Result<(), EncodeDataError> {
130        self.append_element_name(name)?;
131
132        if self.type_stack.is_empty() {
133            if let Some(definition) = self.types.get(self.primary_type) {
134                self.type_stack
135                    .push((self.primary_type.to_owned(), definition.to_owned()));
136            } else {
137                return Err(EncodeDataError::TypeDefinitionNotFound(
138                    self.primary_type.to_owned(),
139                ));
140            }
141        }
142
143        let parent_type = self.type_stack.last().unwrap();
144
145        if let Some(type_definition) = parent_type.1.iter().find(|d| d.name == name) {
146            log::debug!("start encode type {}", type_definition.r#type);
147
148            let type_name = extract_type_name(&type_definition.r#type);
149
150            if let Some(definition) = self.types.get(&type_name) {
151                self.type_stack.push((type_name, definition.to_owned()));
152
153                return Ok(());
154            } else {
155                // assume is builtin type
156                log::debug!("process builtin type {}", type_name);
157                return Ok(());
158            }
159        } else {
160            log::debug!("maybe none field {}", name);
161            return Ok(());
162            // return Err(EncodeDataError::TypeDefinitionNotFound(name.to_owned()));
163        }
164    }
165
166    // pub fn end_encode_type(&mut self) -> Result<(), EncodeDataError> {
167    //     self.type_stack.pop();
168
169    //     Ok(())
170    // }
171
172    fn type_hash(&mut self) -> Result<[u8; 32], EncodeDataError> {
173        if self.type_stack.is_empty() {
174            if let Some(definition) = self.types.get(self.primary_type) {
175                self.type_stack
176                    .push((self.primary_type.to_owned(), definition.to_owned()));
177            } else {
178                return Err(EncodeDataError::TypeDefinitionNotFound(
179                    self.primary_type.to_owned(),
180                ));
181            }
182        }
183
184        let primary_type = self.type_stack.last().unwrap();
185
186        let mut types = HashMap::<String, (String, TypeDefinition)>::new();
187
188        let mut stack = vec![primary_type];
189
190        while !stack.is_empty() {
191            let current = stack.pop().unwrap();
192            for field in &current.1 {
193                let type_name = extract_type_name(&field.r#type);
194
195                if !types.contains_key(&type_name) {
196                    if let Some(definition) = self.types.get(&type_name) {
197                        types.insert(type_name.clone(), (type_name, definition.to_owned()));
198                    }
199                }
200            }
201        }
202
203        let mut keys = types.keys().collect::<Vec<_>>();
204
205        keys.sort_by(|a, b| a.cmp(b));
206
207        let mut sorted = vec![primary_type];
208
209        for key in keys {
210            let value = types.get(key.as_str());
211            sorted.push(value.unwrap());
212        }
213
214        let encode_type = sorted
215            .iter()
216            .map(|(name, fields)| {
217                let fields = fields
218                    .iter()
219                    .map(|f| format!("{} {}", f.r#type, f.name))
220                    .collect::<Vec<_>>();
221                format!("{}({})", name, fields.join(","))
222            })
223            .collect::<Vec<_>>()
224            .join("");
225
226        log::debug!("encode type {}", encode_type);
227
228        Ok(Keccak256::new()
229            .chain_update(encode_type.as_bytes())
230            .finalize()
231            .into())
232    }
233
234    /// Start encode tuple(e.g, `<Type>[5]`, Structure)
235    pub fn start_tuple(&mut self) -> Result<(), EncodeDataError> {
236        self.tuple_stack.push(TupleEncoder {
237            ..Default::default()
238        });
239
240        Ok(())
241    }
242
243    pub fn end_tuple(&mut self) -> Result<(), EncodeDataError> {
244        if let Some(tuple) = self.tuple_stack.pop() {
245            let encode_data = tuple.finalize(self.type_hash()?, self.type_stack.pop().unwrap().1);
246
247            if let Some(tuple) = self.tuple_stack.last_mut() {
248                tuple.append_element(encode_data);
249            } else {
250                self.hashed = Some(encode_data);
251            }
252
253            Ok(())
254        } else {
255            Err(EncodeDataError::EndTuple)
256        }
257    }
258
259    pub fn append_element(&mut self, data: [u8; 32]) -> Result<(), EncodeDataError> {
260        if let Some(tuple) = self.tuple_stack.last_mut() {
261            tuple.append_element(data);
262            Ok(())
263        } else {
264            Err(EncodeDataError::EndTuple)
265        }
266    }
267
268    fn append_element_name(&mut self, name: &str) -> Result<(), EncodeDataError> {
269        if let Some(tuple) = self.tuple_stack.last_mut() {
270            tuple.append_element_name(name);
271            Ok(())
272        } else {
273            Err(EncodeDataError::EndTuple)
274        }
275    }
276
277    fn element_type_name(&self) -> Result<Option<String>, EncodeDataError> {
278        if let Some(tuple) = self.tuple_stack.last() {
279            if let Some(name) = tuple.last_name() {
280                let (_, fields) = self.type_stack.last().unwrap();
281
282                if let Some(field) = fields.iter().find(|f| f.name.as_str() == name) {
283                    return Ok(Some(field.r#type.clone()));
284                }
285            }
286
287            Ok(None)
288        } else {
289            Err(EncodeDataError::EndTuple)
290        }
291    }
292}
293
294impl<'a, 'b> Serializer for &'a mut EIP712StructHasher<'b> {
295    type Ok = ();
296    type Error = EncodeDataError;
297    type SerializeSeq = Self;
298    type SerializeTuple = Self;
299    type SerializeTupleStruct = Self;
300    type SerializeTupleVariant = Self;
301    type SerializeMap = Self;
302    type SerializeStruct = Self;
303    type SerializeStructVariant = Self;
304
305    fn is_human_readable(&self) -> bool {
306        false
307    }
308    fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
309        unimplemented!()
310    }
311
312    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
313        self.append_element(Keccak256::new().chain_update(v).finalize().into())
314    }
315
316    fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
317        unimplemented!("Contract abi don't support rust char")
318    }
319
320    fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
321        unimplemented!("EIP712 don't support f32")
322    }
323
324    fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
325        unimplemented!("EIP712 don't support f64")
326    }
327
328    fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
329        let mut buff = if v.is_negative() {
330            [0u8; 32]
331        } else {
332            [0xffu8; 32]
333        };
334
335        buff[16..].copy_from_slice(&v.to_be_bytes());
336
337        self.append_element(buff)
338    }
339
340    fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
341        self.serialize_i128(_v as i128)
342    }
343
344    fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
345        self.serialize_i128(_v as i128)
346    }
347
348    fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
349        self.serialize_i128(_v as i128)
350    }
351
352    fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
353        self.serialize_i128(_v as i128)
354    }
355
356    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
357        self.start_tuple()?;
358
359        Ok(self)
360    }
361
362    fn serialize_newtype_struct<T: ?Sized>(
363        self,
364        name: &'static str,
365        value: &T,
366    ) -> Result<Self::Ok, Self::Error>
367    where
368        T: serde::Serialize,
369    {
370        match name {
371            "bytes" | "bytesN" => {
372                let bytes = unsafe { (value as *const T).cast::<Vec<u8>>().as_ref().unwrap() };
373
374                return self.append_element(Keccak256::new().chain_update(bytes).finalize().into());
375            }
376            "address" => {
377                let bytes = unsafe { (value as *const T).cast::<Vec<u8>>().as_ref().unwrap() };
378
379                let mut buf = [0u8; 32];
380
381                buf[12..].copy_from_slice(bytes.as_ref());
382
383                return self.append_element(buf);
384            }
385            "uint256" | "int256" => {
386                let bytes = unsafe { (value as *const T).cast::<Vec<u8>>().as_ref().unwrap() };
387
388                let mut buf = [0u8; 32];
389
390                buf[(32 - bytes.len())..].copy_from_slice(bytes.as_ref());
391
392                return self.append_element(buf);
393            }
394            _ => {
395                return Err(EncodeDataError::UnsupportType(name.to_owned()));
396            }
397        }
398    }
399
400    fn serialize_newtype_variant<T: ?Sized>(
401        self,
402        name: &'static str,
403        _variant_index: u32,
404        variant: &'static str,
405        _value: &T,
406    ) -> Result<Self::Ok, Self::Error>
407    where
408        T: serde::Serialize,
409    {
410        return Err(EncodeDataError::UnsupportType(format!(
411            "enum {}::{}",
412            name, variant
413        )));
414    }
415
416    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
417        Ok(())
418    }
419
420    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
421        unimplemented!("EIP712 don't support rust enum")
422    }
423
424    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
425    where
426        T: serde::Serialize,
427    {
428        value.serialize(self)
429    }
430
431    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
432        if let Some(type_name) = self.element_type_name()? {
433            log::debug!("serialize_str {}, type_name {}", v, type_name);
434            match type_name.as_str() {
435                "bytes" | "bytesN" => {
436                    let bytes = Bytes::from_str(v).map_err(ser::Error::custom)?;
437
438                    return self
439                        .append_element(Keccak256::new().chain_update(bytes).finalize().into());
440                }
441                "address" => {
442                    let address = Address::try_from(v).map_err(ser::Error::custom)?;
443
444                    let mut bytes = [0u8; 32];
445
446                    bytes[12..].copy_from_slice(address.as_ref());
447
448                    return self.append_element(bytes);
449                }
450                "uint256" => {
451                    let value = if v.starts_with("0x") {
452                        U256::from_str_radix(&v[2..], 16).map_err(ser::Error::custom)?
453                    } else {
454                        U256::from_str_radix(v, 10).map_err(ser::Error::custom)?
455                    };
456
457                    let buf = value.to_be_bytes();
458
459                    return self.append_element(buf);
460                }
461                _ => {}
462            }
463        }
464
465        self.append_element(
466            Keccak256::new()
467                .chain_update(v.as_bytes())
468                .finalize()
469                .into(),
470        )
471    }
472
473    fn serialize_struct(
474        self,
475        _name: &'static str,
476        _len: usize,
477    ) -> Result<Self::SerializeStruct, Self::Error> {
478        self.start_tuple()?;
479
480        Ok(self)
481    }
482
483    fn serialize_struct_variant(
484        self,
485        _name: &'static str,
486        _variant_index: u32,
487        _variant: &'static str,
488        _len: usize,
489    ) -> Result<Self::SerializeStructVariant, Self::Error> {
490        unimplemented!("EIP712 don't support rust enum")
491    }
492
493    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
494        unimplemented!("EIP712 don't support serialize tuple")
495    }
496
497    fn serialize_tuple_struct(
498        self,
499        _name: &'static str,
500        _len: usize,
501    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
502        unimplemented!("EIP712 don't support serialize tuple_struct")
503    }
504
505    fn serialize_tuple_variant(
506        self,
507        _name: &'static str,
508        _variant_index: u32,
509        _variant: &'static str,
510        _len: usize,
511    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
512        unimplemented!("Contract abi don't support rust enum")
513    }
514
515    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
516        let mut buff = [0u8; 32];
517
518        buff[16..].copy_from_slice(&v.to_be_bytes());
519
520        self.append_element(buff)
521    }
522
523    fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
524        self.serialize_u128(_v as u128)
525    }
526
527    fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
528        self.serialize_u128(_v as u128)
529    }
530
531    fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
532        self.serialize_u128(_v as u128)
533    }
534
535    fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
536        self.serialize_u128(_v as u128)
537    }
538
539    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
540        Ok(())
541    }
542
543    fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
544        Ok(())
545    }
546
547    fn serialize_unit_variant(
548        self,
549        _name: &'static str,
550        _variant_index: u32,
551        _variant: &'static str,
552    ) -> Result<Self::Ok, Self::Error> {
553        unimplemented!("Contract abi don't support rust enum")
554    }
555}
556
557impl<'a, 'b> ser::SerializeStruct for &'a mut EIP712StructHasher<'b> {
558    type Error = EncodeDataError;
559
560    type Ok = ();
561    fn end(self) -> Result<Self::Ok, Self::Error> {
562        self.end_tuple()
563    }
564
565    fn serialize_field<T: ?Sized>(
566        &mut self,
567        key: &'static str,
568        value: &T,
569    ) -> Result<(), Self::Error>
570    where
571        T: serde::Serialize,
572    {
573        self.start_encode_type(key)?;
574        value.serialize(&mut **self)
575    }
576}
577
578impl<'a, 'b> ser::SerializeMap for &'a mut EIP712StructHasher<'b> {
579    type Error = EncodeDataError;
580
581    type Ok = ();
582    fn end(self) -> Result<Self::Ok, Self::Error> {
583        self.end_tuple()
584    }
585
586    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
587    where
588        T: serde::Serialize,
589    {
590        let name = serde_json::to_string(key).map_err(ser::Error::custom)?;
591
592        let reg = Regex::new(r#"^"[^"]*"$"#).unwrap();
593
594        if !reg.is_match(&name) {
595            return Err(EncodeDataError::Unknown(
596                "HashStruct only support map with string key".to_owned(),
597            ));
598        }
599
600        self.start_encode_type(&name.as_str()[1..(name.len() - 1)])
601    }
602
603    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
604    where
605        T: serde::Serialize,
606    {
607        value.serialize(&mut **self)
608    }
609}
610
611impl<'a, 'b> ser::SerializeSeq for &'a mut EIP712StructHasher<'b> {
612    type Error = EncodeDataError;
613
614    type Ok = ();
615    fn end(self) -> Result<Self::Ok, Self::Error> {
616        unimplemented!()
617    }
618
619    fn serialize_element<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
620    where
621        T: serde::Serialize,
622    {
623        unimplemented!()
624    }
625}
626
627impl<'a, 'b> ser::SerializeStructVariant for &'a mut EIP712StructHasher<'b> {
628    type Error = EncodeDataError;
629
630    type Ok = ();
631    fn end(self) -> Result<Self::Ok, Self::Error> {
632        unimplemented!()
633    }
634
635    fn serialize_field<T: ?Sized>(
636        &mut self,
637        _key: &'static str,
638        _value: &T,
639    ) -> Result<(), Self::Error>
640    where
641        T: serde::Serialize,
642    {
643        unimplemented!()
644    }
645}
646
647impl<'a, 'b> ser::SerializeTuple for &'a mut EIP712StructHasher<'b> {
648    type Error = EncodeDataError;
649
650    type Ok = ();
651    fn end(self) -> Result<Self::Ok, Self::Error> {
652        unimplemented!()
653    }
654
655    fn serialize_element<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
656    where
657        T: serde::Serialize,
658    {
659        unimplemented!()
660    }
661}
662
663impl<'a, 'b> ser::SerializeTupleVariant for &'a mut EIP712StructHasher<'b> {
664    type Error = EncodeDataError;
665
666    type Ok = ();
667    fn end(self) -> Result<Self::Ok, Self::Error> {
668        unimplemented!()
669    }
670
671    fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
672    where
673        T: serde::Serialize,
674    {
675        unimplemented!()
676    }
677}
678
679impl<'a, 'b> ser::SerializeTupleStruct for &'a mut EIP712StructHasher<'b> {
680    type Error = EncodeDataError;
681
682    type Ok = ();
683    fn end(self) -> Result<Self::Ok, Self::Error> {
684        unimplemented!()
685    }
686
687    fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
688    where
689        T: serde::Serialize,
690    {
691        unimplemented!()
692    }
693}
694
695/// Calculate struct hash,
696/// see [`Definition of hashStruct`](https://eips.ethereum.org/EIPS/eip-712) for more information
697pub fn eip712_hash_struct<S: Serialize>(
698    primary_type: &str,
699    types: &HashMap<String, TypeDefinition>,
700    value: &S,
701) -> Result<H256, EncodeDataError> {
702    let mut hasher = EIP712StructHasher {
703        type_stack: vec![],
704        types,
705        hashed: None,
706        tuple_stack: vec![],
707        primary_type,
708    };
709
710    value.serialize(&mut hasher)?;
711
712    Ok(hasher.finalize()?.into())
713}