Skip to main content

ark_serialize/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![warn(
3    unused,
4    future_incompatible,
5    nonstandard_style,
6    rust_2018_idioms,
7    rust_2021_compatibility
8)]
9#![deny(unsafe_code)]
10#![doc = include_str!("../README.md")]
11mod error;
12mod flags;
13mod impls;
14
15pub mod serde;
16
17pub use ark_std::io::{Read, Write};
18
19pub use error::*;
20pub use flags::*;
21pub use serde::{
22    CompressedChecked, CompressedUnchecked, UncompressedChecked, UncompressedUnchecked,
23};
24
25#[cfg(test)]
26mod test;
27
28#[cfg(feature = "derive")]
29#[doc(hidden)]
30pub use ark_serialize_derive::*;
31
32use digest::{Digest, Output};
33
34/// Serializes the given `CanonicalSerialize` items in sequence. `serialize_to_vec![a, b, c, d, e]`
35/// is identical to the value of `buf` after `(a, b, c, d, e).serialize_compressed(&mut buf)`.
36#[macro_export]
37macro_rules! serialize_to_vec {
38    ($($x:expr),*) => ({
39        let mut buf = ::ark_std::vec![];
40        {$crate::serialize_to_vec!(@inner buf, $($x),*)}.map(|_| buf)
41    });
42
43    (@inner $buf:expr, $y:expr, $($x:expr),*) => ({
44        {
45            $crate::CanonicalSerialize::serialize_uncompressed(&$y, &mut $buf)
46        }.and({$crate::serialize_to_vec!(@inner $buf, $($x),*)})
47    });
48
49    (@inner $buf:expr, $x:expr) => ({
50        $crate::CanonicalSerialize::serialize_uncompressed(&$x, &mut $buf)
51    });
52}
53
54/// Whether to use a compressed version of the serialization algorithm. Specific behavior depends
55/// on implementation. If no compressed version exists (e.g. on `Fp`), mode is ignored.
56#[derive(Copy, Clone, PartialEq, Eq)]
57pub enum Compress {
58    Yes,
59    No,
60}
61
62/// Whether to validate the element after deserializing it. Specific behavior depends on
63/// implementation. If no validation algorithm exists (e.g. on `Fp`), mode is ignored.
64#[derive(Copy, Clone, PartialEq, Eq)]
65pub enum Validate {
66    Yes,
67    No,
68}
69
70pub trait Valid: Sync {
71    /// Whether the `check` method is trivial (i.e. always returns `Ok(())`). If this is `true`,
72    /// the `batch_check` method will skip all checks and return `Ok(())`.
73    /// This should be set to `true` for types where `check` is trivial, e.g.
74    /// integers, field elements, etc.
75    /// This is `false` by default.
76    /// This is primarily an optimization to skip unnecessary checks in `batch_check`.
77    const TRIVIAL_CHECK: bool = false;
78
79    /// Checks whether `self` is valid. If `self` is valid, returns `Ok(())`. Otherwise, returns
80    /// an error describing the failure.
81    /// This method is called by `deserialize_with_mode` if `validate` is `Validate::Yes`.
82    fn check(&self) -> Result<(), SerializationError>;
83
84    /// Checks whether all items in `batch` are valid. If all items are valid, returns `Ok(())`.
85    /// Otherwise, returns an error describing the first failure.
86    #[inline]
87    fn batch_check<'a>(
88        batch: impl Iterator<Item = &'a Self> + Send,
89    ) -> Result<(), SerializationError>
90    where
91        Self: 'a,
92    {
93        if !Self::TRIVIAL_CHECK {
94            #[cfg(feature = "parallel")]
95            {
96                use rayon::{iter::ParallelBridge, prelude::ParallelIterator};
97                batch.par_bridge().try_for_each(|e| e.check())?;
98            }
99            #[cfg(not(feature = "parallel"))]
100            {
101                for item in batch {
102                    item.check()?;
103                }
104            }
105        }
106        Ok(())
107    }
108}
109
110/// Serializer in little endian format.
111/// This trait can be derived if all fields of a struct implement
112/// `CanonicalSerialize` and the `derive` feature is enabled.
113///
114/// # Example
115/// ```
116/// // The `derive` feature must be set for the derivation to work.
117/// use ark_serialize::*;
118///
119/// # #[cfg(feature = "derive")]
120/// #[derive(CanonicalSerialize)]
121/// struct TestStruct {
122///     a: u64,
123///     b: (u64, (u64, u64)),
124/// }
125/// ```
126pub trait CanonicalSerialize {
127    /// The general serialize method that takes in customization flags.
128    fn serialize_with_mode<W: Write>(
129        &self,
130        writer: W,
131        compress: Compress,
132    ) -> Result<(), SerializationError>;
133
134    /// Returns the size in bytes of the serialized version of `self` with the given compression mode.
135    fn serialized_size(&self, compress: Compress) -> usize;
136
137    /// Serializes `self` into `writer` using the compressed form if applicable.
138    fn serialize_compressed<W: Write>(&self, writer: W) -> Result<(), SerializationError> {
139        self.serialize_with_mode(writer, Compress::Yes)
140    }
141
142    /// Returns the size in bytes of the compressed serialized version of `self`.
143    fn compressed_size(&self) -> usize {
144        self.serialized_size(Compress::Yes)
145    }
146
147    /// Serializes `self` into `writer` using the uncompressed form.
148    fn serialize_uncompressed<W: Write>(&self, writer: W) -> Result<(), SerializationError> {
149        self.serialize_with_mode(writer, Compress::No)
150    }
151
152    /// Returns the size in bytes of the uncompressed serialized version of `self`.
153    fn uncompressed_size(&self) -> usize {
154        self.serialized_size(Compress::No)
155    }
156}
157
158/// Deserializer in little endian format.
159/// This trait can be derived if all fields of a struct implement
160/// `CanonicalDeserialize` and the `derive` feature is enabled.
161///
162/// # Example
163/// ```
164/// // The `derive` feature must be set for the derivation to work.
165/// use ark_serialize::*;
166///
167/// # #[cfg(feature = "derive")]
168/// #[derive(CanonicalDeserialize)]
169/// struct TestStruct {
170///     a: u64,
171///     b: (u64, (u64, u64)),
172/// }
173/// ```
174pub trait CanonicalDeserialize: Valid + Sized {
175    /// The general deserialize method that takes in customization flags.
176    fn deserialize_with_mode<R: Read>(
177        reader: R,
178        compress: Compress,
179        validate: Validate,
180    ) -> Result<Self, SerializationError>;
181
182    /// Reads `Self` from `reader` using the compressed form if applicable.
183    /// Performs validation if applicable.
184    fn deserialize_compressed<R: Read>(reader: R) -> Result<Self, SerializationError> {
185        Self::deserialize_with_mode(reader, Compress::Yes, Validate::Yes)
186    }
187
188    /// Reads `Self` from `reader` using the compressed form if applicable, without validating the
189    /// deserialized value.
190    ///
191    /// # Note
192    ///
193    /// This should be used with caution, as it may lead to invalid values being used in
194    /// subsequent computations, which may have security implications depending on the context.
195    ///
196    /// It should only be used when the caller can guarantee that the input is valid, e.g. if it was
197    /// generated by a trusted source.
198    fn deserialize_compressed_unchecked<R: Read>(reader: R) -> Result<Self, SerializationError> {
199        Self::deserialize_with_mode(reader, Compress::Yes, Validate::No)
200    }
201
202    /// Reads `Self` from `reader` using the uncompressed form. Performs validation if applicable.
203    fn deserialize_uncompressed<R: Read>(reader: R) -> Result<Self, SerializationError> {
204        Self::deserialize_with_mode(reader, Compress::No, Validate::Yes)
205    }
206
207    /// Reads `Self` from `reader` using the uncompressed form, without validating the deserialized
208    /// value.
209    ///
210    /// # Note
211    ///
212    /// This should be used with caution, as it may lead to invalid values being used in
213    /// subsequent computations, which may have security implications depending on the context.
214    ///
215    /// It should only be used when the caller can guarantee that the input is valid, e.g. if it was
216    /// generated by a trusted source.
217    fn deserialize_uncompressed_unchecked<R: Read>(reader: R) -> Result<Self, SerializationError> {
218        Self::deserialize_with_mode(reader, Compress::No, Validate::No)
219    }
220}
221
222/// Serializer in little endian format allowing to encode flags.
223pub trait CanonicalSerializeWithFlags: CanonicalSerialize {
224    /// Serializes `self` and `flags` into `writer`.
225    fn serialize_with_flags<W: Write, F: Flags>(
226        &self,
227        writer: W,
228        flags: F,
229    ) -> Result<(), SerializationError>;
230
231    /// Serializes `self` and `flags` into `writer`.
232    fn serialized_size_with_flags<F: Flags>(&self) -> usize;
233}
234
235/// Deserializer in little endian format allowing flags to be encoded.
236pub trait CanonicalDeserializeWithFlags: Sized {
237    /// Reads `Self` and `Flags` from `reader`.
238    /// Returns empty flags by default.
239    fn deserialize_with_flags<R: Read, F: Flags>(
240        reader: R,
241    ) -> Result<(Self, F), SerializationError>;
242}
243
244// This private struct works around Serialize taking the pre-existing
245// std::io::Write instance of most digest::Digest implementations by value
246struct HashMarshaller<'a, H: Digest>(&'a mut H);
247
248impl<H: Digest> ark_std::io::Write for HashMarshaller<'_, H> {
249    #[inline]
250    fn write(&mut self, buf: &[u8]) -> ark_std::io::Result<usize> {
251        Digest::update(self.0, buf);
252        Ok(buf.len())
253    }
254
255    #[inline]
256    fn flush(&mut self) -> ark_std::io::Result<()> {
257        Ok(())
258    }
259}
260
261/// [`CanonicalSerialize`] induces a natural way to hash a value:
262/// serialize it and hash the resulting byte string.
263///
264/// This is a convenience trait that combines the two steps.
265pub trait CanonicalSerializeHashExt: CanonicalSerialize {
266    fn hash<H: Digest>(&self) -> Output<H> {
267        let mut hasher = H::new();
268        self.serialize_compressed(HashMarshaller(&mut hasher))
269            .expect("HashMarshaller::flush should be infaillible!");
270        hasher.finalize()
271    }
272
273    fn hash_uncompressed<H: Digest>(&self) -> Output<H> {
274        let mut hasher = H::new();
275        self.serialize_uncompressed(HashMarshaller(&mut hasher))
276            .expect("HashMarshaller::flush should be infaillible!");
277        hasher.finalize()
278    }
279}
280
281/// [`CanonicalSerializeHashExt`] is a (blanket) extension trait of
282/// `CanonicalSerialize`: all types implementing the latter
283/// automatically implement the former.
284impl<T: CanonicalSerialize> CanonicalSerializeHashExt for T {}
285
286#[inline]
287pub const fn buffer_bit_byte_size(modulus_bits: usize) -> (usize, usize) {
288    let byte_size = buffer_byte_size(modulus_bits);
289    ((byte_size * 8), byte_size)
290}
291
292/// Converts the number of bits required to represent a number
293/// into the number of bytes required to represent it.
294#[inline]
295pub const fn buffer_byte_size(modulus_bits: usize) -> usize {
296    modulus_bits.div_ceil(8)
297}