jf_utils/
serialize.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the Jellyfish library.
3
4// You should have received a copy of the MIT License
5// along with the Jellyfish library. If not, see <https://mit-license.org/>.
6
7//! Various serialization functions.
8
9use ark_std::vec::Vec;
10use serde::{Deserialize, Serialize};
11
12/// A helper for converting ark_serialize::CanonicalSerialize bytes to standard
13/// Serde bytes. Use this struct as intermediate target instead of directly
14/// deriving serde::Serialize/Deserialize to avoid implementation of Visitors.
15#[derive(Serialize, Deserialize)]
16pub struct CanonicalBytes(pub Vec<u8>);
17
18impl<T: ark_serialize::CanonicalSerialize> From<T> for CanonicalBytes {
19    fn from(obj: T) -> CanonicalBytes {
20        let mut bytes = Vec::new();
21        obj.serialize_compressed(&mut bytes)
22            .expect("fail to serialize to canonical bytes");
23        CanonicalBytes(bytes)
24    }
25}
26
27#[macro_export]
28macro_rules! deserialize_canonical_bytes {
29    ($t:ident) => {
30        deserialize_canonical_bytes!($t<>);
31    };
32
33    // match MyStruct<'a, 'b, T: MyTrait, R: MyTrait2, ...> where any number of lifetime and generic parameters
34    ($t:ident < $( $lt:lifetime ),* $( $T:ident : $trait:ident ),* >) => {
35        impl<$($lt),* $( $T: $trait ),*> From<CanonicalBytes> for $t<$($lt),* $( $T ),*> {
36            fn from(bytes: CanonicalBytes) -> Self {
37                ark_serialize::CanonicalDeserialize::deserialize_compressed(bytes.0.as_slice())
38                    .expect("fail to deserialize canonical bytes")
39            }
40        }
41    };
42}
43
44/// Serializers for elements that are Ark-Works serializable but not serde
45/// serializable.
46///
47/// Many cryptographic objects (e.g. finite field elements) are foreign types
48/// that we cannot apply [tagged] or `#[derive(Deserialize, Serialize)]` to.
49/// Instead, use `#[serde(with = "canonical")]` at the point where the object is
50/// used inside a struct or enum definition.
51///
52/// [tagged]: tagged_base64::tagged
53pub mod canonical {
54    use super::*;
55    use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
56    use ark_std::format;
57    use serde::{
58        de::{Deserializer, Error as DeError},
59        ser::{Error as SerError, Serializer},
60    };
61    use tagged_base64::TaggedBase64;
62
63    pub fn serialize<S: Serializer, T: CanonicalSerialize>(
64        elem: &T,
65        serializer: S,
66    ) -> Result<S::Ok, S::Error> {
67        let mut bytes = Vec::new();
68        T::serialize_compressed(elem, &mut bytes)
69            .map_err(|e| S::Error::custom(format!("{e:?}")))?;
70        Serialize::serialize(&TaggedBase64::new("FIELD", &bytes).unwrap(), serializer)
71    }
72
73    pub fn deserialize<'de, D: Deserializer<'de>, T: CanonicalDeserialize>(
74        deserializer: D,
75    ) -> Result<T, D::Error> {
76        let tb64 = <TaggedBase64 as Deserialize>::deserialize(deserializer)?;
77        if tb64.tag() == "FIELD" {
78            T::deserialize_compressed_unchecked(tb64.as_ref())
79                .map_err(|e| D::Error::custom(format!("{e:?}")))
80        } else {
81            Err(D::Error::custom(format!(
82                "incorrect tag (expected FIELD, got {})",
83                tb64.tag()
84            )))
85        }
86    }
87}
88
89#[macro_export]
90macro_rules! test_serde_default {
91    ($struct:tt) => {
92        use ark_serialize::*;
93
94        let data = $struct::default();
95        let mut ser_bytes: $crate::Vec<u8> = $crate::Vec::new();
96        data.serialize(&mut ser_bytes).unwrap();
97        let de: $struct = $struct::deserialize_compressed(&ser_bytes[..]).unwrap();
98        assert_eq!(de, data);
99    };
100}