ark_sponge/
absorb.rs

1use ark_ec::models::short_weierstrass_jacobian::GroupAffine as SWAffine;
2use ark_ec::models::twisted_edwards_extended::GroupAffine as TEAffine;
3use ark_ec::models::{SWModelParameters, TEModelParameters};
4use ark_ff::models::{
5    Fp256, Fp256Parameters, Fp320, Fp320Parameters, Fp384, Fp384Parameters, Fp768, Fp768Parameters,
6    Fp832, Fp832Parameters,
7};
8use ark_ff::{PrimeField, ToConstraintField};
9use ark_serialize::CanonicalSerialize;
10use ark_std::vec::Vec;
11/// An interface for objects that can be absorbed by a `CryptographicSponge`.
12pub trait Absorb {
13    /// Converts the object into a list of bytes that can be absorbed by a `CryptographicSponge`.
14    /// Append the list to `dest`.
15    fn to_sponge_bytes(&self, dest: &mut Vec<u8>);
16
17    /// Converts the object into a list of bytes that can be absorbed by a `CryptographicSponge`.
18    /// Return the list as `Vec`.
19    fn to_sponge_bytes_as_vec(&self) -> Vec<u8> {
20        let mut result = Vec::new();
21        self.to_sponge_bytes(&mut result);
22        result
23    }
24
25    /// Converts the object into field elements that can be absorbed by a `CryptographicSponge`.
26    /// Append the list to `dest`
27    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>);
28
29    /// Converts the object into field elements that can be absorbed by a `CryptographicSponge`.
30    /// Return the list as `Vec`
31    fn to_sponge_field_elements_as_vec<F: PrimeField>(&self) -> Vec<F> {
32        let mut result = Vec::new();
33        self.to_sponge_field_elements(&mut result);
34        result
35    }
36
37    /// Specifies the conversion into a list of bytes for a batch. Append the list to `dest`.
38    fn batch_to_sponge_bytes(batch: &[Self], dest: &mut Vec<u8>)
39    where
40        Self: Sized,
41    {
42        for absorbable in batch {
43            absorbable.to_sponge_bytes(dest)
44        }
45    }
46
47    /// Specifies the conversion into a list of bytes for a batch. Return the list as `Vec`.
48    fn batch_to_sponge_bytes_as_vec(batch: &[Self]) -> Vec<u8>
49    where
50        Self: Sized,
51    {
52        let mut result = Vec::new();
53        Self::batch_to_sponge_bytes(batch, &mut result);
54        result
55    }
56
57    /// Specifies the conversion into a list of field elements for a batch. Append the list to `dest`.
58    fn batch_to_sponge_field_elements<F: PrimeField>(batch: &[Self], dest: &mut Vec<F>)
59    where
60        Self: Sized,
61    {
62        for absorbable in batch {
63            absorbable.to_sponge_field_elements(dest)
64        }
65    }
66
67    /// Specifies the conversion into a list of field elements for a batch. Append the list to `dest`.
68    fn batch_to_sponge_field_elements_as_vec<F: PrimeField>(batch: &[Self]) -> Vec<F>
69    where
70        Self: Sized,
71    {
72        let mut result = Vec::new();
73        for absorbable in batch {
74            absorbable.to_sponge_field_elements(&mut result)
75        }
76        result
77    }
78}
79
80/// An extension to `Absorb` that is specific to items with variable length, such as a list.
81pub trait AbsorbWithLength: Absorb {
82    /// The length of the `self` being absorbed.
83    fn absorb_length(&self) -> usize;
84
85    /// Converts the object into a list of bytes along with its length information
86    /// that can be absorbed by a `CryptographicSponge`.
87    /// Append the list to `dest`.
88    fn to_sponge_bytes_with_length(&self, dest: &mut Vec<u8>) {
89        self.absorb_length().to_sponge_bytes(dest);
90        self.to_sponge_bytes(dest)
91    }
92
93    /// Converts the object into field elements along with its length information
94    /// that can be absorbed by a `CryptographicSponge`.
95    /// Append the list to `dest`
96    fn to_sponge_field_elements_with_length<F: PrimeField>(&self, dest: &mut Vec<F>) {
97        self.absorb_length().to_sponge_field_elements(dest);
98        <Self as Absorb>::to_sponge_field_elements(&self, dest)
99    }
100}
101
102/// If `F1` and `F2` have the same prime modulus, this method returns `Some(input)`
103/// but cast to `F2`, and returns `None` otherwise.
104pub(crate) fn field_cast<F1: PrimeField, F2: PrimeField>(input: F1) -> Option<F2> {
105    if F1::characteristic() != F2::characteristic() {
106        // Trying to absorb non-native field elements.
107        None
108    } else {
109        let mut buf = Vec::new();
110        input.serialize(&mut buf).unwrap();
111        Some(F2::from_le_bytes_mod_order(&buf))
112    }
113}
114
115/// If `F1` equals to `F2`, add all elements of `x` as `F2` to `dest` and returns `dest` pointer.
116///
117/// This function will return None and no-op if `F1` is not equal to `F2`.
118pub(crate) fn batch_field_cast<'a, F1: PrimeField, F2: PrimeField>(
119    x: &[F1],
120    dest: &'a mut Vec<F2>,
121) -> Option<&'a mut Vec<F2>> {
122    if F1::characteristic() != F2::characteristic() {
123        // "Trying to absorb non-native field elements."
124        None
125    } else {
126        x.iter().for_each(|item| {
127            let mut buf = Vec::new();
128            item.serialize(&mut buf).unwrap();
129            dest.push(F2::from_le_bytes_mod_order(&buf))
130        });
131        Some(dest)
132    }
133}
134
135impl Absorb for u8 {
136    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
137        dest.push(*self)
138    }
139
140    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
141        dest.push(F::from(*self))
142    }
143
144    fn batch_to_sponge_bytes(batch: &[Self], dest: &mut Vec<u8>) {
145        dest.extend_from_slice(batch)
146    }
147
148    fn batch_to_sponge_field_elements<F: PrimeField>(batch: &[Self], dest: &mut Vec<F>) {
149        let mut bytes = (batch.len() as u64).to_le_bytes().to_vec();
150        bytes.extend_from_slice(batch);
151        dest.extend_from_slice(&bytes.to_field_elements().unwrap()[..])
152    }
153}
154
155impl Absorb for bool {
156    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
157        dest.push(*self as u8)
158    }
159
160    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
161        dest.push(F::from(*self))
162    }
163}
164
165macro_rules! impl_absorbable_field {
166    ($field:ident, $params:ident) => {
167        impl<P: $params> Absorb for $field<P> {
168            fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
169                self.serialize(dest).unwrap()
170            }
171
172            fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
173                dest.push(field_cast(*self).unwrap())
174            }
175
176            fn batch_to_sponge_field_elements<F: PrimeField>(batch: &[Self], dest: &mut Vec<F>)
177            where
178                Self: Sized,
179            {
180                batch_field_cast(batch, dest).unwrap();
181            }
182        }
183    };
184}
185
186impl_absorbable_field!(Fp256, Fp256Parameters);
187impl_absorbable_field!(Fp320, Fp320Parameters);
188impl_absorbable_field!(Fp384, Fp384Parameters);
189impl_absorbable_field!(Fp768, Fp768Parameters);
190impl_absorbable_field!(Fp832, Fp832Parameters);
191
192macro_rules! impl_absorbable_unsigned {
193    ($t:ident) => {
194        impl Absorb for $t {
195            fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
196                dest.extend_from_slice(&self.to_le_bytes()[..])
197            }
198
199            fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
200                dest.push(F::from(*self))
201            }
202        }
203    };
204}
205//
206impl_absorbable_unsigned!(u16);
207impl_absorbable_unsigned!(u32);
208impl_absorbable_unsigned!(u64);
209impl_absorbable_unsigned!(u128);
210
211macro_rules! impl_absorbable_signed {
212    ($signed:ident, $unsigned:ident) => {
213        impl Absorb for $signed {
214            fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
215                dest.extend_from_slice(&self.to_le_bytes()[..])
216            }
217
218            fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
219                let mut elem = F::from(self.abs() as $unsigned);
220                if *self < 0 {
221                    elem = -elem;
222                }
223                dest.push(elem)
224            }
225        }
226    };
227}
228
229impl_absorbable_signed!(i8, u8);
230impl_absorbable_signed!(i16, u16);
231impl_absorbable_signed!(i32, u32);
232impl_absorbable_signed!(i64, u64);
233impl_absorbable_signed!(i128, u128);
234
235impl Absorb for usize {
236    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
237        dest.extend_from_slice(&((*self as u64).to_le_bytes())[..])
238    }
239
240    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
241        (*self as u64).to_sponge_field_elements(dest)
242    }
243}
244
245impl Absorb for isize {
246    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
247        dest.extend_from_slice(&self.to_le_bytes()[..])
248    }
249
250    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
251        (*self as i64).to_sponge_field_elements(dest)
252    }
253}
254
255impl<CF: PrimeField, P: TEModelParameters<BaseField = CF>> Absorb for TEAffine<P> {
256    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
257        self.to_field_elements().unwrap().serialize(dest).unwrap()
258    }
259
260    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
261        batch_field_cast::<P::BaseField, _>(&self.to_field_elements().unwrap(), dest).unwrap();
262    }
263}
264
265impl<CF: PrimeField, P: SWModelParameters<BaseField = CF>> Absorb for SWAffine<P> {
266    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
267        self.to_field_elements().unwrap().serialize(dest).unwrap()
268    }
269
270    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
271        batch_field_cast::<P::BaseField, _>(&self.to_field_elements().unwrap(), dest).unwrap();
272    }
273}
274
275impl<A: Absorb> Absorb for &[A] {
276    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
277        A::batch_to_sponge_bytes(self, dest)
278    }
279
280    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
281        A::batch_to_sponge_field_elements(self, dest)
282    }
283}
284
285impl<A: Absorb> AbsorbWithLength for &[A] {
286    fn absorb_length(&self) -> usize {
287        self.len()
288    }
289}
290
291impl<A: Absorb> Absorb for Vec<A> {
292    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
293        self.as_slice().to_sponge_bytes(dest)
294    }
295
296    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
297        self.as_slice().to_sponge_field_elements(dest)
298    }
299}
300
301impl<A: Absorb> AbsorbWithLength for Vec<A> {
302    fn absorb_length(&self) -> usize {
303        self.as_slice().len()
304    }
305}
306
307impl<A: Absorb> Absorb for Option<A> {
308    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
309        self.is_some().to_sponge_bytes(dest);
310        if let Some(item) = self {
311            item.to_sponge_bytes(dest)
312        }
313    }
314
315    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
316        self.is_some().to_sponge_field_elements(dest);
317        if let Some(item) = self {
318            item.to_sponge_field_elements(dest)
319        }
320    }
321}
322
323// TODO: add more for common data structures, treemap?
324
325impl<A: Absorb> Absorb for &A {
326    fn to_sponge_bytes(&self, dest: &mut Vec<u8>) {
327        (*self).to_sponge_bytes(dest)
328    }
329
330    fn to_sponge_field_elements<F: PrimeField>(&self, dest: &mut Vec<F>) {
331        (*self).to_sponge_field_elements(dest)
332    }
333}
334
335/// Individually absorbs each element in a comma-separated list of absorbables into a sponge.
336/// Format is `absorb!(s, a_0, a_1, ..., a_n)`, where `s` is a mutable reference to a sponge
337/// and each `a_i` implements `Absorb`.
338#[macro_export]
339macro_rules! absorb {
340    ($sponge:expr, $($absorbable:expr),+ ) => {
341        $(
342            CryptographicSponge::absorb($sponge, &$absorbable);
343        )+
344    };
345}
346
347/// Quickly convert a list of different [`Absorb`]s into sponge bytes.
348#[macro_export]
349macro_rules! collect_sponge_bytes {
350    ($head:expr $(, $tail:expr)* ) => {
351        {
352            let mut output = Absorb::to_sponge_bytes_as_vec(&$head);
353            $(
354                Absorb::to_sponge_bytes(&$tail, &mut output);
355            )*
356            output
357        }
358    };
359}
360
361/// Quickly convert a list of different [`Absorb`]s into sponge field elements.
362#[macro_export]
363macro_rules! collect_sponge_field_elements {
364    ($head:expr $(, $tail:expr)* ) => {
365        {
366            let mut output = Absorb::to_sponge_field_elements_as_vec(&$head);
367            $(
368               Absorb::to_sponge_field_elements(&$tail, &mut output);
369            )*
370            output
371        }
372    };
373}
374
375#[cfg(test)]
376mod tests {
377    use crate::{batch_field_cast, field_cast};
378    use ark_ff::UniformRand;
379    use ark_std::test_rng;
380    use ark_test_curves::bls12_381::Fr;
381
382    #[test]
383    fn test_cast() {
384        let mut rng = test_rng();
385        let expected = Fr::rand(&mut rng);
386        let actual = field_cast::<_, Fr>(expected).unwrap();
387        assert_eq!(actual, expected);
388        let expected: Vec<_> = (0..10).map(|_| Fr::rand(&mut rng)).collect();
389        let mut actual = Vec::new();
390        batch_field_cast::<_, Fr>(&expected, &mut actual).unwrap();
391        assert_eq!(actual, expected);
392    }
393}