1use 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 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 log::debug!("process builtin type {}", type_name);
157 return Ok(());
158 }
159 } else {
160 log::debug!("maybe none field {}", name);
161 return Ok(());
162 }
164 }
165
166 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 ¤t.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 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
732pub 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}