1use {
2 crate::{
3 abi_example::{normalize_type_name, AbiEnumVisitor},
4 hash::{Hash, Hasher},
5 },
6 log::*,
7 serde::{
8 ser::{Error as SerdeError, *},
9 Serialize, Serializer,
10 },
11 std::{any::type_name, io::Write},
12 thiserror::Error,
13};
14
15#[derive(Debug)]
16pub struct AbiDigester {
17 data_types: std::rc::Rc<std::cell::RefCell<Vec<String>>>,
18 depth: usize,
19 for_enum: bool,
20 opaque_scope: Option<String>,
21}
22
23pub type DigestResult = Result<AbiDigester, DigestError>;
24type Sstr = &'static str;
25
26#[derive(Debug, Error)]
27pub enum DigestError {
28 #[error("Option::None is serialized; no ABI digest for Option::Some")]
29 NoneIsSerialized,
30 #[error("nested error")]
31 Node(Sstr, Box<DigestError>),
32 #[error("leaf error")]
33 Leaf(Sstr, Sstr, Box<DigestError>),
34 #[error("arithmetic overflow")]
35 ArithmeticOverflow,
36}
37
38impl SerdeError for DigestError {
39 fn custom<T: std::fmt::Display>(_msg: T) -> DigestError {
40 unreachable!("This error should never be used");
41 }
42}
43
44impl DigestError {
45 pub(crate) fn wrap_by_type<T: ?Sized>(e: DigestError) -> DigestError {
46 DigestError::Node(type_name::<T>(), Box::new(e))
47 }
48
49 pub(crate) fn wrap_by_str(e: DigestError, s: Sstr) -> DigestError {
50 DigestError::Node(s, Box::new(e))
51 }
52}
53
54const INDENT_WIDTH: usize = 4;
55
56pub(crate) fn shorten_serialize_with(type_name: &str) -> &str {
57 if type_name.ends_with("__SerializeWith") {
61 "__SerializeWith"
62 } else {
63 type_name
64 }
65}
66
67impl AbiDigester {
68 pub fn create() -> Self {
69 AbiDigester {
70 data_types: std::rc::Rc::new(std::cell::RefCell::new(vec![])),
71 for_enum: false,
72 depth: 0,
73 opaque_scope: None,
74 }
75 }
76
77 pub fn create_new(&self) -> Self {
80 Self {
81 data_types: self.data_types.clone(),
82 depth: self.depth,
83 for_enum: false,
84 opaque_scope: self.opaque_scope.clone(),
85 }
86 }
87
88 pub fn create_new_opaque(&self, top_scope: &str) -> Self {
89 Self {
90 data_types: self.data_types.clone(),
91 depth: self.depth,
92 for_enum: false,
93 opaque_scope: Some(top_scope.to_owned()),
94 }
95 }
96
97 pub fn create_child(&self) -> Result<Self, DigestError> {
98 let depth = self
99 .depth
100 .checked_add(1)
101 .ok_or(DigestError::ArithmeticOverflow)?;
102 Ok(Self {
103 data_types: self.data_types.clone(),
104 depth,
105 for_enum: false,
106 opaque_scope: self.opaque_scope.clone(),
107 })
108 }
109
110 pub fn create_enum_child(&self) -> Result<Self, DigestError> {
111 let depth = self
112 .depth
113 .checked_add(1)
114 .ok_or(DigestError::ArithmeticOverflow)?;
115 Ok(Self {
116 data_types: self.data_types.clone(),
117 depth,
118 for_enum: true,
119 opaque_scope: self.opaque_scope.clone(),
120 })
121 }
122
123 pub fn digest_data<T: ?Sized + Serialize>(&mut self, value: &T) -> DigestResult {
124 let type_name = normalize_type_name(type_name::<T>());
125 if type_name.ends_with("__SerializeWith")
126 || (self.opaque_scope.is_some()
127 && type_name.starts_with(self.opaque_scope.as_ref().unwrap()))
128 {
129 value.serialize(self.create_new())
131 } else {
132 <&T>::visit_for_abi(&value, &mut self.create_new())
135 }
136 }
137
138 pub fn update(&mut self, strs: &[&str]) {
139 let mut buf = strs
140 .iter()
141 .map(|s| {
142 normalize_type_name(s)
145 })
146 .collect::<Vec<_>>()
147 .join(" ");
148 buf = format!(
149 "{:0width$}{}\n",
150 "",
151 buf,
152 width = self.depth.saturating_mul(INDENT_WIDTH)
153 );
154 info!("updating with: {}", buf.trim_end());
155 (*self.data_types.borrow_mut()).push(buf);
156 }
157
158 pub fn update_with_type<T: ?Sized>(&mut self, label: &str) {
159 self.update(&[label, type_name::<T>()]);
160 }
161
162 pub fn update_with_string(&mut self, label: String) {
163 self.update(&[&label]);
164 }
165
166 #[allow(clippy::unnecessary_wraps)]
167 fn digest_primitive<T: Serialize>(mut self) -> Result<AbiDigester, DigestError> {
168 self.update_with_type::<T>("primitive");
169 Ok(self)
170 }
171
172 fn digest_element<T: ?Sized + Serialize>(&mut self, v: &T) -> Result<(), DigestError> {
173 self.update_with_type::<T>("element");
174 self.create_child()?.digest_data(v).map(|_| ())
175 }
176
177 fn digest_named_field<T: ?Sized + Serialize>(
178 &mut self,
179 key: Sstr,
180 v: &T,
181 ) -> Result<(), DigestError> {
182 let field_type_name = shorten_serialize_with(type_name::<T>());
183 self.update_with_string(format!("field {}: {}", key, field_type_name));
184 self.create_child()?
185 .digest_data(v)
186 .map(|_| ())
187 .map_err(|e| DigestError::wrap_by_str(e, key))
188 }
189
190 fn digest_unnamed_field<T: ?Sized + Serialize>(&mut self, v: &T) -> Result<(), DigestError> {
191 self.update_with_type::<T>("field");
192 self.create_child()?.digest_data(v).map(|_| ())
193 }
194
195 #[allow(clippy::unnecessary_wraps)]
196 fn check_for_enum(
197 &mut self,
198 label: &'static str,
199 variant: &'static str,
200 ) -> Result<(), DigestError> {
201 assert!(self.for_enum, "derive AbiEnumVisitor or implement it for the enum, which contains a variant ({}) named {}", label, variant);
202 Ok(())
203 }
204
205 pub fn finalize(self) -> Hash {
206 let mut hasher = Hasher::default();
207
208 for buf in (*self.data_types.borrow()).iter() {
209 hasher.hash(buf.as_bytes());
210 }
211
212 let hash = hasher.result();
213
214 if let Ok(dir) = std::env::var("SAFECOIN_ABI_DUMP_DIR") {
215 let thread_name = std::thread::current()
216 .name()
217 .unwrap_or("unknown-test-thread")
218 .replace(':', "_");
219 if thread_name == "main" {
220 error!("Bad thread name detected for dumping; Maybe, --test-threads=1? Sorry, SAFECOIN_ABI_DUMP_DIR doesn't work under 1; increase it");
221 }
222
223 let path = format!("{}/{}_{}", dir, thread_name, hash,);
224 let mut file = std::fs::File::create(path).unwrap();
225 for buf in (*self.data_types.borrow()).iter() {
226 file.write_all(buf.as_bytes()).unwrap();
227 }
228 file.sync_data().unwrap();
229 }
230
231 hash
232 }
233}
234
235impl Serializer for AbiDigester {
236 type Ok = Self;
237 type Error = DigestError;
238 type SerializeSeq = Self;
239 type SerializeTuple = Self;
240 type SerializeTupleStruct = Self;
241 type SerializeTupleVariant = Self;
242 type SerializeMap = Self;
243 type SerializeStruct = Self;
244 type SerializeStructVariant = Self;
245
246 fn serialize_bool(self, _data: bool) -> DigestResult {
247 self.digest_primitive::<bool>()
248 }
249
250 fn serialize_i8(self, _data: i8) -> DigestResult {
251 self.digest_primitive::<i8>()
252 }
253
254 fn serialize_i16(self, _data: i16) -> DigestResult {
255 self.digest_primitive::<i16>()
256 }
257
258 fn serialize_i32(self, _data: i32) -> DigestResult {
259 self.digest_primitive::<i32>()
260 }
261
262 fn serialize_i64(self, _data: i64) -> DigestResult {
263 self.digest_primitive::<i64>()
264 }
265
266 fn serialize_i128(self, _data: i128) -> DigestResult {
267 self.digest_primitive::<i128>()
268 }
269
270 fn serialize_u8(self, _data: u8) -> DigestResult {
271 self.digest_primitive::<u8>()
272 }
273
274 fn serialize_u16(self, _data: u16) -> DigestResult {
275 self.digest_primitive::<u16>()
276 }
277
278 fn serialize_u32(self, _data: u32) -> DigestResult {
279 self.digest_primitive::<u32>()
280 }
281
282 fn serialize_u64(self, _data: u64) -> DigestResult {
283 self.digest_primitive::<u64>()
284 }
285
286 fn serialize_u128(self, _data: u128) -> DigestResult {
287 self.digest_primitive::<u128>()
288 }
289
290 fn serialize_f32(self, _data: f32) -> DigestResult {
291 self.digest_primitive::<f32>()
292 }
293
294 fn serialize_f64(self, _data: f64) -> DigestResult {
295 self.digest_primitive::<f64>()
296 }
297
298 fn serialize_char(self, _data: char) -> DigestResult {
299 self.digest_primitive::<char>()
300 }
301
302 fn serialize_str(self, _data: &str) -> DigestResult {
303 self.digest_primitive::<&str>()
304 }
305
306 fn serialize_unit(self) -> DigestResult {
307 self.digest_primitive::<()>()
308 }
309
310 fn serialize_bytes(mut self, v: &[u8]) -> DigestResult {
311 self.update_with_string(format!("bytes [u8] (len = {})", v.len()));
312 Ok(self)
313 }
314
315 fn serialize_none(self) -> DigestResult {
316 Err(DigestError::NoneIsSerialized)
317 }
318
319 fn serialize_some<T>(mut self, v: &T) -> DigestResult
320 where
321 T: ?Sized + Serialize,
322 {
323 self.update(&["enum Option (variants = 2)"]);
325 let mut variant_digester = self.create_child()?;
326
327 variant_digester.update_with_string("variant(0) None (unit)".to_owned());
328 variant_digester
329 .update_with_string(format!("variant(1) Some({}) (newtype)", type_name::<T>()));
330 variant_digester.create_child()?.digest_data(v)
331 }
332
333 fn serialize_unit_struct(mut self, name: Sstr) -> DigestResult {
334 self.update(&["struct", name, "(unit)"]);
335 Ok(self)
336 }
337
338 fn serialize_unit_variant(mut self, _name: Sstr, index: u32, variant: Sstr) -> DigestResult {
339 self.check_for_enum("unit_variant", variant)?;
340 self.update_with_string(format!("variant({}) {} (unit)", index, variant));
341 Ok(self)
342 }
343
344 fn serialize_newtype_struct<T>(mut self, name: Sstr, v: &T) -> DigestResult
345 where
346 T: ?Sized + Serialize,
347 {
348 self.update_with_string(format!("struct {}({}) (newtype)", name, type_name::<T>()));
349 self.create_child()?
350 .digest_data(v)
351 .map_err(|e| DigestError::wrap_by_str(e, "newtype_struct"))
352 }
353
354 fn serialize_newtype_variant<T>(
355 mut self,
356 _name: Sstr,
357 i: u32,
358 variant: Sstr,
359 v: &T,
360 ) -> DigestResult
361 where
362 T: ?Sized + Serialize,
363 {
364 self.check_for_enum("newtype_variant", variant)?;
365 self.update_with_string(format!(
366 "variant({}) {}({}) (newtype)",
367 i,
368 variant,
369 type_name::<T>()
370 ));
371 self.create_child()?
372 .digest_data(v)
373 .map_err(|e| DigestError::wrap_by_str(e, "newtype_variant"))
374 }
375
376 fn serialize_seq(mut self, len: Option<usize>) -> DigestResult {
377 let len = len.unwrap();
378 assert_eq!(
379 len, 1,
380 "Exactly 1 seq element is needed to generate the ABI digest precisely"
381 );
382 self.update_with_string(format!("seq (elements = {})", len));
383 self.create_child()
384 }
385
386 fn serialize_tuple(mut self, len: usize) -> DigestResult {
387 self.update_with_string(format!("tuple (elements = {})", len));
388 self.create_child()
389 }
390
391 fn serialize_tuple_struct(mut self, name: Sstr, len: usize) -> DigestResult {
392 self.update_with_string(format!("struct {} (fields = {}) (tuple)", name, len));
393 self.create_child()
394 }
395
396 fn serialize_tuple_variant(
397 mut self,
398 _name: Sstr,
399 i: u32,
400 variant: Sstr,
401 len: usize,
402 ) -> DigestResult {
403 self.check_for_enum("tuple_variant", variant)?;
404 self.update_with_string(format!("variant({}) {} (fields = {})", i, variant, len));
405 self.create_child()
406 }
407
408 fn serialize_map(mut self, len: Option<usize>) -> DigestResult {
409 let len = len.unwrap();
410 assert_eq!(
411 len, 1,
412 "Exactly 1 map entry is needed to generate the ABI digest precisely"
413 );
414 self.update_with_string(format!("map (entries = {})", len));
415 self.create_child()
416 }
417
418 fn serialize_struct(mut self, name: Sstr, len: usize) -> DigestResult {
419 self.update_with_string(format!("struct {} (fields = {})", name, len));
420 self.create_child()
421 }
422
423 fn serialize_struct_variant(
424 mut self,
425 _name: Sstr,
426 i: u32,
427 variant: Sstr,
428 len: usize,
429 ) -> DigestResult {
430 self.check_for_enum("struct_variant", variant)?;
431 self.update_with_string(format!(
432 "variant({}) struct {} (fields = {})",
433 i, variant, len
434 ));
435 self.create_child()
436 }
437}
438
439impl SerializeSeq for AbiDigester {
440 type Ok = Self;
441 type Error = DigestError;
442
443 fn serialize_element<T: ?Sized + Serialize>(&mut self, data: &T) -> Result<(), DigestError> {
444 self.digest_element(data)
445 }
446
447 fn end(self) -> DigestResult {
448 Ok(self)
449 }
450}
451
452impl SerializeTuple for AbiDigester {
453 type Ok = Self;
454 type Error = DigestError;
455
456 fn serialize_element<T: ?Sized + Serialize>(&mut self, data: &T) -> Result<(), DigestError> {
457 self.digest_element(data)
458 }
459
460 fn end(self) -> DigestResult {
461 Ok(self)
462 }
463}
464impl SerializeTupleStruct for AbiDigester {
465 type Ok = Self;
466 type Error = DigestError;
467
468 fn serialize_field<T: ?Sized + Serialize>(&mut self, data: &T) -> Result<(), DigestError> {
469 self.digest_unnamed_field(data)
470 }
471
472 fn end(self) -> DigestResult {
473 Ok(self)
474 }
475}
476
477impl SerializeTupleVariant for AbiDigester {
478 type Ok = Self;
479 type Error = DigestError;
480
481 fn serialize_field<T: ?Sized + Serialize>(&mut self, data: &T) -> Result<(), DigestError> {
482 self.digest_unnamed_field(data)
483 }
484
485 fn end(self) -> DigestResult {
486 Ok(self)
487 }
488}
489
490impl SerializeMap for AbiDigester {
491 type Ok = Self;
492 type Error = DigestError;
493
494 fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), DigestError> {
495 self.update_with_type::<T>("key");
496 self.create_child()?.digest_data(key).map(|_| ())
497 }
498
499 fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), DigestError> {
500 self.update_with_type::<T>("value");
501 self.create_child()?.digest_data(value).map(|_| ())
502 }
503
504 fn end(self) -> DigestResult {
505 Ok(self)
506 }
507}
508
509impl SerializeStruct for AbiDigester {
510 type Ok = Self;
511 type Error = DigestError;
512
513 fn serialize_field<T: ?Sized + Serialize>(
514 &mut self,
515 key: Sstr,
516 data: &T,
517 ) -> Result<(), DigestError> {
518 self.digest_named_field(key, data)
519 }
520
521 fn end(self) -> DigestResult {
522 Ok(self)
523 }
524}
525
526impl SerializeStructVariant for AbiDigester {
527 type Ok = Self;
528 type Error = DigestError;
529
530 fn serialize_field<T: ?Sized + Serialize>(
531 &mut self,
532 key: Sstr,
533 data: &T,
534 ) -> Result<(), DigestError> {
535 self.digest_named_field(key, data)
536 }
537
538 fn end(self) -> DigestResult {
539 Ok(self)
540 }
541}
542
543#[cfg(test)]
544mod tests {
545 use std::{collections::HashMap, sync::atomic::AtomicIsize};
546
547 #[frozen_abi(digest = "CQiGCzsGquChkwffHjZKFqa3tCYtS3GWYRRYX7iDR38Q")]
548 type TestTypeAlias = i32;
549
550 #[frozen_abi(digest = "Apwkp9Ah9zKirzwuSzVoU9QRc43EghpkD1nGVakJLfUY")]
551 #[derive(Serialize, AbiExample)]
552 struct TestStruct {
553 test_field: i8,
554 test_field2: i8,
555 }
556
557 #[frozen_abi(digest = "4LbuvQLX78XPbm4hqqZcHFHpseDJcw4qZL9EUZXSi2Ss")]
558 #[derive(Serialize, AbiExample)]
559 struct TestTupleStruct(i8, i8);
560
561 #[frozen_abi(digest = "FNHa6mNYJZa59Fwbipep5dXRXcFreaDHn9jEUZEH1YLv")]
562 #[derive(Serialize, AbiExample)]
563 struct TestNewtypeStruct(i8);
564
565 #[frozen_abi(digest = "Hbs1X2X7TF2gFEfsspwfZ1JKr8ZGbLY3uidQBebqcMYt")]
566 #[derive(Serialize, AbiExample)]
567 struct Foo<'a> {
568 #[serde(with = "serde_bytes")]
569 data1: Vec<u8>,
570 #[serde(with = "serde_bytes")]
571 data2: &'a [u8],
572 #[serde(with = "serde_bytes")]
573 data3: &'a Vec<u8>,
574 }
575
576 #[frozen_abi(digest = "5qio5qYurHDv6fq5kcwP2ue2RBEazSZF8CPk2kUuwC2j")]
577 #[derive(Serialize, AbiExample)]
578 struct TestStructReversed {
579 test_field2: i8,
580 test_field: i8,
581 }
582
583 #[frozen_abi(digest = "DLLrTWprsMjdJGR447A4mui9HpqxbKdsFXBfaWPcwhny")]
584 #[derive(Serialize, AbiExample)]
585 struct TestStructAnotherType {
586 test_field: i16,
587 test_field2: i8,
588 }
589
590 #[frozen_abi(digest = "GMeECsxg37a5qznstWXeeX3d6HXs6j12oB4SKaZZuNJk")]
591 #[derive(Serialize, AbiExample)]
592 struct TestNest {
593 nested_field: [TestStruct; 5],
594 }
595
596 #[frozen_abi(digest = "GttWH8FAY3teUjTaSds9mL3YbiDQ7qWw7WAvDXKd4ZzX")]
597 type TestUnitStruct = std::marker::PhantomData<i8>;
598
599 #[frozen_abi(digest = "6kj3mPXbzWTwZho48kZWxZjuseLU2oiqhbpqca4DmcRq")]
600 #[derive(Serialize, AbiExample, AbiEnumVisitor)]
601 enum TestEnum {
602 Variant1,
603 Variant2,
604 }
605
606 #[frozen_abi(digest = "3WqYwnbQEdu6iPZi5LJa2b5kw55hxBtZdqFqiViFCKPo")]
607 #[derive(Serialize, AbiExample, AbiEnumVisitor)]
608 enum TestTupleVariant {
609 Variant1(u8, u16),
610 Variant2(u8, u16),
611 }
612
613 #[frozen_abi(digest = "4E9gJjvKiETBeZ8dybZPAQ7maaHTHFucmLqgX2m6yrBh")]
614 #[derive(Serialize, AbiExample)]
615 struct TestVecEnum {
616 enums: Vec<TestTupleVariant>,
617 }
618
619 #[derive(Serialize, AbiExample)]
620 struct TestGenericStruct<T: Ord> {
621 test_field: T,
622 }
623
624 #[frozen_abi(digest = "2Dr5k3Z513mV4KrGeUfcMwjsVHLmVyLiZarmfnXawEbf")]
625 type TestConcreteStruct = TestGenericStruct<i64>;
626
627 #[derive(Serialize, AbiExample, AbiEnumVisitor)]
628 enum TestGenericEnum<T: serde::Serialize + Sized + Ord> {
629 TestVariant(T),
630 }
631
632 #[frozen_abi(digest = "2B2HqxHaziSfW3kdxJqV9vEMpCpRaEipXL6Bskv1GV7J")]
633 type TestConcreteEnum = TestGenericEnum<u128>;
634
635 #[frozen_abi(digest = "GyExD8nkYb9e6tijFL5S1gFtdN9GfY6L2sUDjTLhVGn4")]
636 type TestMap = HashMap<char, i128>;
637
638 #[frozen_abi(digest = "AFLTVyVBkjc1SAPnzyuwTvmie994LMhJGN7PrP7hCVwL")]
639 type TestVec = Vec<f32>;
640
641 #[frozen_abi(digest = "F5RniBQtNMBiDnyLEf72aQKHskV1TuBrD4jrEH5odPAW")]
642 type TestArray = [f64; 10];
643
644 #[frozen_abi(digest = "8cgZGpckC4dFovh3QuZpgvcvK2125ig7P4HsK9KCw39N")]
645 type TestUnit = ();
646
647 #[frozen_abi(digest = "FgnBPy2T5iNNbykMteq1M4FRpNeSkzRoi9oXeCjEW6uq")]
648 type TestResult = Result<u8, u16>;
649
650 #[frozen_abi(digest = "F5s6YyJkfz7LM56q5j9RzTLa7QX4Utx1ecNkHX5UU9Fp")]
651 type TestAtomic = AtomicIsize;
652
653 #[frozen_abi(digest = "7rH7gnEhJ8YouzqPT6VPyUDELvL51DGednSPcoLXG2rg")]
654 type TestOptionWithIsize = Option<isize>;
655
656 #[derive(Serialize, AbiExample, AbiEnumVisitor)]
657 enum TestMyOption<T: serde::Serialize + Sized + Ord> {
658 None,
659 Some(T),
660 }
661 #[frozen_abi(digest = "BzXkoRacijFTCPW4PyyvhkqMVgcuhmvPXjZfMsHJCeet")]
662 type TestMyOptionWithIsize = TestMyOption<isize>;
663
664 #[frozen_abi(digest = "9PMdHRb49BpkywrmPoJyZWMsEmf5E1xgmsFGkGmea5RW")]
665 type TestBitVec = bv::BitVec<u64>;
666
667 mod skip_should_be_same {
668 #[frozen_abi(digest = "4LbuvQLX78XPbm4hqqZcHFHpseDJcw4qZL9EUZXSi2Ss")]
669 #[derive(Serialize, AbiExample)]
670 struct TestTupleStruct(i8, i8, #[serde(skip)] i8);
671
672 #[frozen_abi(digest = "Hk7BYjZ71upWQJAx2PqoNcapggobPmFbMJd34xVdvRso")]
673 #[derive(Serialize, AbiExample)]
674 struct TestStruct {
675 test_field: i8,
676 #[serde(skip)]
677 _skipped_test_field: i8,
678 }
679
680 #[frozen_abi(digest = "6kj3mPXbzWTwZho48kZWxZjuseLU2oiqhbpqca4DmcRq")]
681 #[derive(Serialize, AbiExample, AbiEnumVisitor)]
682 enum TestEnum {
683 Variant1,
684 Variant2,
685 #[serde(skip)]
686 #[allow(dead_code)]
687 Variant3,
688 }
689
690 #[frozen_abi(digest = "3WqYwnbQEdu6iPZi5LJa2b5kw55hxBtZdqFqiViFCKPo")]
691 #[derive(Serialize, AbiExample, AbiEnumVisitor)]
692 enum TestTupleVariant {
693 Variant1(u8, u16),
694 Variant2(u8, u16, #[serde(skip)] u32),
695 }
696 }
697}