serde_eip712/
hashstruct.rs

1//! EIP712 `encodeData` implementation using the serde [`Serialize`] framework.
2
3use std::collections::HashMap;
4
5use ethers_primitives::{Address, FromEtherHex, ToEtherHex};
6use regex::Regex;
7use serde::{ser, Serialize, Serializer};
8use sha3::{Digest, Keccak256};
9
10use crate::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 {}: {:x?}",
84                field.name,
85                index,
86                (&self.fields[index]).to_eth_hex()
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" => {
372                let bytes = unsafe { (value as *const T).cast::<Vec<u8>>().as_ref().unwrap() };
373
374                self.append_element(Keccak256::new().chain_update(bytes).finalize().into())
375            }
376            "address" => {
377                let bytes = unsafe { (value as *const T).cast::<[u8; 32]>().as_ref().unwrap() };
378
379                self.append_element(bytes.to_owned())
380            }
381            _ => {
382                let bytes_regex = Regex::new(r"^bytes(\d{1,2})$").unwrap();
383                let int_regex = Regex::new(r"^(u)?int(\d{1,3})$").unwrap();
384
385                if let Some(caps) = bytes_regex.captures(name) {
386                    let len: usize = caps[1].parse().unwrap();
387                    if len <= 32 {
388                        let bytes =
389                            unsafe { (value as *const T).cast::<[u8; 32]>().as_ref().unwrap() };
390
391                        return self.append_element(bytes.to_owned());
392                    }
393                }
394
395                if let Some(caps) = int_regex.captures(name) {
396                    let len: usize = caps[2].parse().unwrap();
397                    if len <= 256 {
398                        let bytes =
399                            unsafe { (value as *const T).cast::<[u8; 32]>().as_ref().unwrap() };
400
401                        return self.append_element(bytes.to_owned());
402                    }
403                }
404
405                return Err(EncodeDataError::UnsupportType(name.to_owned()));
406            }
407        }
408    }
409
410    fn serialize_newtype_variant<T: ?Sized>(
411        self,
412        name: &'static str,
413        _variant_index: u32,
414        variant: &'static str,
415        _value: &T,
416    ) -> Result<Self::Ok, Self::Error>
417    where
418        T: serde::Serialize,
419    {
420        return Err(EncodeDataError::UnsupportType(format!(
421            "enum {}::{}",
422            name, variant
423        )));
424    }
425
426    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
427        Ok(())
428    }
429
430    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
431        unimplemented!("EIP712 don't support rust enum")
432    }
433
434    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
435    where
436        T: serde::Serialize,
437    {
438        value.serialize(self)
439    }
440
441    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
442        log::debug!("serialize_str {}", v);
443
444        if let Some(type_name) = self.element_type_name()? {
445            match type_name.as_str() {
446                "bytes" => {
447                    let bytes = Vec::<u8>::from_eth_hex(v).map_err(ser::Error::custom)?;
448
449                    return self
450                        .append_element(Keccak256::new().chain_update(bytes).finalize().into());
451                }
452                "address" => {
453                    let address = Address::try_from(v).map_err(ser::Error::custom)?;
454
455                    let mut bytes = [0u8; 32];
456
457                    bytes[12..].copy_from_slice(&address.0);
458
459                    return self.append_element(bytes);
460                }
461                _ => {
462                    let bytes_regex = Regex::new(r"^bytes(\d{1,2})$").unwrap();
463                    let int_regex = Regex::new(r"^(u)?int(\d{1,3})$").unwrap();
464
465                    if let Some(caps) = bytes_regex.captures(&type_name) {
466                        let len: usize = caps[1].parse().unwrap();
467                        if len <= 32 {
468                            let buff = Vec::<u8>::from_eth_hex(v).map_err(ser::Error::custom)?;
469
470                            if len < buff.len() {
471                                return Err(EncodeDataError::Bytes32OutofRange(v.to_owned()));
472                            }
473
474                            let mut bytes = [0u8; 32];
475
476                            bytes.copy_from_slice(&buff);
477
478                            return self.append_element(bytes);
479                        }
480                    }
481
482                    if let Some(caps) = int_regex.captures(&type_name) {
483                        let len: usize = caps[2].parse().unwrap();
484                        if len <= 256 {
485                            let buff = Vec::<u8>::from_eth_hex(v).map_err(ser::Error::custom)?;
486
487                            if len < buff.len() * 8 {
488                                return Err(EncodeDataError::IntOutofRange(v.to_owned()));
489                            }
490
491                            let mut bytes = [0u8; 32];
492
493                            bytes[(32 - buff.len())..].copy_from_slice(&buff);
494
495                            return self.append_element(bytes.to_owned());
496                        }
497                    }
498                }
499            }
500        }
501
502        self.append_element(
503            Keccak256::new()
504                .chain_update(v.as_bytes())
505                .finalize()
506                .into(),
507        )
508    }
509
510    fn serialize_struct(
511        self,
512        _name: &'static str,
513        _len: usize,
514    ) -> Result<Self::SerializeStruct, Self::Error> {
515        self.start_tuple()?;
516
517        Ok(self)
518    }
519
520    fn serialize_struct_variant(
521        self,
522        _name: &'static str,
523        _variant_index: u32,
524        _variant: &'static str,
525        _len: usize,
526    ) -> Result<Self::SerializeStructVariant, Self::Error> {
527        unimplemented!("EIP712 don't support rust enum")
528    }
529
530    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
531        unimplemented!("EIP712 don't support serialize tuple")
532    }
533
534    fn serialize_tuple_struct(
535        self,
536        _name: &'static str,
537        _len: usize,
538    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
539        unimplemented!("EIP712 don't support serialize tuple_struct")
540    }
541
542    fn serialize_tuple_variant(
543        self,
544        _name: &'static str,
545        _variant_index: u32,
546        _variant: &'static str,
547        _len: usize,
548    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
549        unimplemented!("Contract abi don't support rust enum")
550    }
551
552    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
553        let mut buff = [0u8; 32];
554
555        buff[16..].copy_from_slice(&v.to_be_bytes());
556
557        self.append_element(buff)
558    }
559
560    fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
561        self.serialize_u128(_v as u128)
562    }
563
564    fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
565        self.serialize_u128(_v as u128)
566    }
567
568    fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
569        self.serialize_u128(_v as u128)
570    }
571
572    fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
573        self.serialize_u128(_v as u128)
574    }
575
576    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
577        Ok(())
578    }
579
580    fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
581        Ok(())
582    }
583
584    fn serialize_unit_variant(
585        self,
586        _name: &'static str,
587        _variant_index: u32,
588        _variant: &'static str,
589    ) -> Result<Self::Ok, Self::Error> {
590        unimplemented!("Contract abi don't support rust enum")
591    }
592}
593
594impl<'a, 'b> ser::SerializeStruct for &'a mut EIP712StructHasher<'b> {
595    type Error = EncodeDataError;
596
597    type Ok = ();
598    fn end(self) -> Result<Self::Ok, Self::Error> {
599        self.end_tuple()
600    }
601
602    fn serialize_field<T: ?Sized>(
603        &mut self,
604        key: &'static str,
605        value: &T,
606    ) -> Result<(), Self::Error>
607    where
608        T: serde::Serialize,
609    {
610        self.start_encode_type(key)?;
611        value.serialize(&mut **self)
612    }
613}
614
615impl<'a, 'b> ser::SerializeMap for &'a mut EIP712StructHasher<'b> {
616    type Error = EncodeDataError;
617
618    type Ok = ();
619    fn end(self) -> Result<Self::Ok, Self::Error> {
620        self.end_tuple()
621    }
622
623    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
624    where
625        T: serde::Serialize,
626    {
627        let name = serde_json::to_string(key).map_err(ser::Error::custom)?;
628
629        let reg = Regex::new(r#"^"[^"]*"$"#).unwrap();
630
631        if !reg.is_match(&name) {
632            return Err(EncodeDataError::Unknown(
633                "HashStruct only support map with string key".to_owned(),
634            ));
635        }
636
637        self.start_encode_type(&name.as_str()[1..(name.len() - 1)])
638    }
639
640    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
641    where
642        T: serde::Serialize,
643    {
644        value.serialize(&mut **self)
645    }
646}
647
648impl<'a, 'b> ser::SerializeSeq for &'a mut EIP712StructHasher<'b> {
649    type Error = EncodeDataError;
650
651    type Ok = ();
652    fn end(self) -> Result<Self::Ok, Self::Error> {
653        unimplemented!()
654    }
655
656    fn serialize_element<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
657    where
658        T: serde::Serialize,
659    {
660        unimplemented!()
661    }
662}
663
664impl<'a, 'b> ser::SerializeStructVariant for &'a mut EIP712StructHasher<'b> {
665    type Error = EncodeDataError;
666
667    type Ok = ();
668    fn end(self) -> Result<Self::Ok, Self::Error> {
669        unimplemented!()
670    }
671
672    fn serialize_field<T: ?Sized>(
673        &mut self,
674        _key: &'static str,
675        _value: &T,
676    ) -> Result<(), Self::Error>
677    where
678        T: serde::Serialize,
679    {
680        unimplemented!()
681    }
682}
683
684impl<'a, 'b> ser::SerializeTuple for &'a mut EIP712StructHasher<'b> {
685    type Error = EncodeDataError;
686
687    type Ok = ();
688    fn end(self) -> Result<Self::Ok, Self::Error> {
689        unimplemented!()
690    }
691
692    fn serialize_element<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
693    where
694        T: serde::Serialize,
695    {
696        unimplemented!()
697    }
698}
699
700impl<'a, 'b> ser::SerializeTupleVariant for &'a mut EIP712StructHasher<'b> {
701    type Error = EncodeDataError;
702
703    type Ok = ();
704    fn end(self) -> Result<Self::Ok, Self::Error> {
705        unimplemented!()
706    }
707
708    fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
709    where
710        T: serde::Serialize,
711    {
712        unimplemented!()
713    }
714}
715
716impl<'a, 'b> ser::SerializeTupleStruct for &'a mut EIP712StructHasher<'b> {
717    type Error = EncodeDataError;
718
719    type Ok = ();
720    fn end(self) -> Result<Self::Ok, Self::Error> {
721        unimplemented!()
722    }
723
724    fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
725    where
726        T: serde::Serialize,
727    {
728        unimplemented!()
729    }
730}
731
732/// Calculate struct hash,
733/// see [`Definition of hashStruct`](https://eips.ethereum.org/EIPS/eip-712) for more information
734pub fn eip712_hash_struct<S: Serialize>(
735    primary_type: &str,
736    types: &HashMap<String, TypeDefinition>,
737    value: &S,
738) -> Result<[u8; 32], EncodeDataError> {
739    let mut hasher = EIP712StructHasher {
740        type_stack: vec![],
741        types,
742        hashed: None,
743        tuple_stack: vec![],
744        primary_type,
745    };
746
747    value.serialize(&mut hasher)?;
748
749    hasher.finalize()
750}