primitives/sharing/authenticated/batched/
field_shares.rs

1use std::{
2    fmt::Debug,
3    iter::Sum as IterSum,
4    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5};
6
7use itertools::{enumerate, izip, Itertools};
8use rayon::prelude::IntoParallelIterator;
9use serde::{Deserialize, Serialize};
10use subtle::{Choice, ConstantTimeEq};
11use typenum::{PartialDiv, Prod, Sum, U1, U2, U3};
12
13use super::FieldShareKeys;
14use crate::{
15    algebra::{
16        field::{FieldExtension, SubfieldElement},
17        ops::transpose::transpose,
18    },
19    errors::PrimitiveError,
20    izip_eq,
21    random::{CryptoRngCore, Random, RandomWith},
22    sharing::{
23        authenticated::NParties,
24        unauthenticated::AdditiveShares,
25        FieldShare,
26        FieldShareKey,
27        GlobalFieldKey,
28        Reconstructible,
29        VerifiableWith,
30    },
31    types::{
32        heap_array::{FieldElements, SubfieldElements},
33        identifiers::PeerIndex,
34        ConditionallySelectable,
35        HeapArray,
36        Positive,
37    },
38    utils::IntoExactSizeIterator,
39};
40
41#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
42#[serde(bound = "F: FieldExtension, M: Positive")]
43pub struct OpenFieldShares<F: FieldExtension, M: Positive> {
44    pub(crate) value: SubfieldElements<F, M>,
45    pub(crate) mac: FieldElements<F, M>,
46}
47
48impl<F: FieldExtension, M: Positive> OpenFieldShares<F, M> {
49    pub fn new(value: SubfieldElements<F, M>, mac: FieldElements<F, M>) -> Self {
50        Self { value, mac }
51    }
52
53    pub fn get_value(&self) -> &SubfieldElements<F, M> {
54        &self.value
55    }
56
57    pub fn get_mac(&self) -> &FieldElements<F, M> {
58        &self.mac
59    }
60}
61
62impl<T: FieldExtension, M: Positive> Debug for OpenFieldShares<T, M> {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        f.debug_struct(format!("OpenFieldShares<{}>", M::USIZE).as_str())
65            .field("value", &self.value)
66            .field("mac", &self.mac)
67            .finish()
68    }
69}
70
71/// Authenticated share batch <x_i> of secret shared <x> held by `P_i` (this party).
72///
73/// They are composed of:
74/// - `x_i`, the unauthenticated share value (s.t. `x = Σ x_i`)
75/// - `{MAC(x_i)_j} ∀j∈[1..n]∖{i}`, the MACs of `x_i` for each of the other n-1 parties.
76/// - `{β_ij} ∀j∈[1..n]∖{i}` and `{α_ij} ∀j∈[1..n]∖{i}`, the (local and global) keys tied to the
77///   value&MACs of the other n-1 parties.
78///
79/// The authenticated shares fulfill this relation:
80///
81/// ```MAC(x_i)_j = α_ji · x_i + β_ji  ∀i∈[1..n]  ∀j∈[1..n]∖{i}```
82///     
83/// where `β_ji` and `α_ji` are the (local and global) keys of x_i held by P_j.
84#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
85#[serde(bound = "F: FieldExtension, M: Positive")]
86pub struct FieldShares<F, M>
87where
88    F: FieldExtension,
89    M: Positive, // # shares in the batch
90{
91    /// x_i
92    pub(crate) value: SubfieldElements<F, M>,
93    /// {MAC_1(x_i), ..., MAC_{i-1}(x_i), MAC_{i+1}(x_i), ..., MAC_n(x_i)}
94    pub(crate) macs: Box<[FieldElements<F, M>]>,
95    /// {(α_i1, β_i1), ..., (α_i{i-1}, β_i{i-1}), (α_i{i+1}, β_i{i+1}), ..., (α_in, β_in)}
96    pub(crate) keys: Box<[FieldShareKeys<F, M>]>,
97}
98
99impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
100    pub fn try_new(
101        value: SubfieldElements<F, M>,
102        macs: Box<[FieldElements<F, M>]>,
103        keys: Box<[FieldShareKeys<F, M>]>,
104    ) -> Result<Self, PrimitiveError> {
105        if macs.is_empty() {
106            return Err(PrimitiveError::InvalidParameters(
107                "n_parties < 2".to_string(),
108            ));
109        }
110        if macs.len() != keys.len() {
111            return Err(PrimitiveError::SizeError(macs.len(), keys.len()));
112        }
113        /* NOTE: We assume length equality for macs & keys from this point on */
114        Ok(Self { value, macs, keys })
115    }
116
117    fn new(
118        value: SubfieldElements<F, M>,
119        macs: Box<[FieldElements<F, M>]>,
120        keys: Box<[FieldShareKeys<F, M>]>,
121    ) -> Self {
122        Self { value, macs, keys }
123    }
124
125    pub fn get_value(&self) -> &SubfieldElements<F, M> {
126        &self.value
127    }
128
129    pub fn get_value_mut(&mut self) -> &mut SubfieldElements<F, M> {
130        &mut self.value
131    }
132
133    #[inline]
134    pub fn value(self) -> SubfieldElements<F, M> {
135        self.value
136    }
137
138    pub fn get_keys(&self) -> &[FieldShareKeys<F, M>] {
139        &self.keys
140    }
141
142    pub fn get_keys_mut(&mut self) -> &mut [FieldShareKeys<F, M>] {
143        &mut self.keys
144    }
145
146    pub fn get_key(&self, peer: PeerIndex) -> Option<&FieldShareKeys<F, M>> {
147        self.keys.get(peer)
148    }
149
150    pub fn get_macs(&self) -> &[FieldElements<F, M>] {
151        &self.macs
152    }
153
154    pub fn get_mac(&self, index: PeerIndex) -> Option<&FieldElements<F, M>> {
155        self.macs.get(index)
156    }
157
158    pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalFieldKey<F>> + '_ {
159        self.keys.iter().map(|key| key.get_alpha())
160    }
161
162    pub fn n_parties(&self) -> usize {
163        self.get_macs().len() + 1 // +1 for the local share
164    }
165
166    pub fn iter(&self) -> FieldSharesIterator<F, M> {
167        self.into_iter()
168    }
169
170    pub fn len(&self) -> usize {
171        self.value.len()
172    }
173
174    pub fn is_empty(&self) -> bool {
175        self.len() == 0
176    }
177}
178
179// --------------------
180// |   Verification   |
181// --------------------
182impl<F: FieldExtension, M: Positive> VerifiableWith for FieldShares<F, M> {
183    type VerificationData = ();
184    /// Check the MACs of the share received from another peer.
185    #[inline]
186    fn verify_from_peer_with(
187        &self,
188        open_share: &OpenFieldShares<F, M>,
189        peer: PeerIndex,
190        _verification_data: (),
191    ) -> Result<(), PrimitiveError> {
192        self.get_key(peer)
193            .ok_or(PrimitiveError::WrongPeerIndex(peer, self.keys.len()))?
194            .verify_mac(open_share)
195            .map_err(|e| e.blame(peer).add_state(self))
196    }
197
198    /// Check the MACs of each share received from all other peers.
199    #[inline]
200    fn verify_with(
201        &self,
202        open_shares: &[OpenFieldShares<F, M>],
203        _verification_data: (),
204    ) -> Result<(), PrimitiveError> {
205        izip_eq!(open_shares, &self.keys).enumerate().try_for_each(
206            |(from_peer, (open_share, key))| {
207                key.verify_mac(open_share)
208                    .map_err(|e| e.blame(from_peer).add_state(self))
209            },
210        )
211    }
212}
213
214// --------------------------------
215// |   Opening & Reconstruction   |
216// --------------------------------
217
218impl<F: FieldExtension, M: Positive> Reconstructible for FieldShares<F, M> {
219    type Opening = OpenFieldShares<F, M>;
220    type Secret = SubfieldElements<F, M>;
221
222    /// Open the share towards another peer.
223    fn open_to(&self, for_peer: PeerIndex) -> Result<OpenFieldShares<F, M>, PrimitiveError> {
224        let mac = self
225            .get_mac(for_peer)
226            .ok_or(PrimitiveError::WrongPeerIndex(for_peer, self.macs.len()))?
227            .to_owned();
228        Ok(OpenFieldShares::new(self.get_value().to_owned(), mac))
229    }
230
231    /// Open the share towards all other peers.
232    fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenFieldShares<F, M>> {
233        self.get_macs()
234            .iter()
235            .map(|mac| OpenFieldShares::new(self.get_value().to_owned(), mac.to_owned()))
236    }
237
238    /// Reconstruct a secret from openings coming from all other parties.
239    fn reconstruct(
240        &self,
241        openings: &[OpenFieldShares<F, M>],
242    ) -> Result<Self::Secret, PrimitiveError> {
243        if openings.len() != self.get_keys().len() {
244            return Err(PrimitiveError::SizeError(
245                openings.len(),
246                self.get_keys().len(),
247            ));
248        }
249
250        izip_eq!(openings, self.get_keys()).enumerate().try_fold(
251            self.get_value().to_owned(),
252            |acc, (i, (open_share, key))| {
253                key.verify_mac(open_share)
254                    .map_err(|e| e.blame(i).add_state(self))?;
255                Ok(acc + open_share.get_value())
256            },
257        )
258    }
259}
260
261// -------------------------
262// |   Random Generation   |
263// -------------------------
264
265fn compute_macs<F: FieldExtension, M: Positive>(
266    all_unauth_shares: &[SubfieldElements<F, M>],
267    all_keys: &[Box<[FieldShareKeys<F, M>]>],
268) -> Vec<Box<[FieldElements<F, M>]>> {
269    let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
270    enumerate(all_unauth_shares.iter())
271        .map(|(i, my_unauth_share)| {
272            enumerate(all_key_iters.iter_mut())
273                .filter(|(j, _)| *j != i)
274                .map(|(_, keys_iter)| keys_iter.next().unwrap().compute_mac(my_unauth_share))
275                .collect()
276        })
277        .collect()
278}
279
280impl<F: FieldExtension, M: Positive> Random for FieldShares<F, M> {
281    fn random(_rng: impl CryptoRngCore) -> Self {
282        unimplemented!(
283            "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
284            std::any::type_name::<Self>()
285        )
286    }
287
288    /// Generate a random field share, with Macs and keys for all the other parties.
289    fn random_n<Container: FromIterator<Self>>(
290        mut rng: impl CryptoRngCore,
291        n_parties: NParties,
292    ) -> Container {
293        let all_unauth_shares: Vec<_> = SubfieldElements::random_n(&mut rng, n_parties);
294        let all_keys = (0..n_parties)
295            .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
296            .collect::<Vec<_>>();
297        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
298        izip_eq!(all_unauth_shares, all_macs, all_keys)
299            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
300            .collect()
301    }
302}
303
304impl<F: FieldExtension, M: Positive> RandomWith<NParties> for FieldShares<F, M> {
305    /// Generate a random field share, with Macs and keys for all the other parties.
306    fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
307        FieldShares::new(
308            SubfieldElements::<F, M>::random(&mut rng),
309            FieldElements::<F, M>::random_n(&mut rng, n_parties - 1),
310            FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1),
311        )
312    }
313}
314
315impl<F: FieldExtension, M: Positive> RandomWith<(NParties, SubfieldElements<F, M>)>
316    for FieldShares<F, M>
317{
318    /// Generate a random field share with a specific secret share as value and random macs & keys.
319    fn random_with(
320        mut rng: impl CryptoRngCore,
321        n_parties_value: (NParties, SubfieldElements<F, M>),
322    ) -> Self {
323        let (n_parties, value) = n_parties_value;
324        FieldShares::new(
325            value,
326            FieldElements::<F, M>::random_n(&mut rng, n_parties - 1),
327            FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1),
328        )
329    }
330}
331
332impl<F: FieldExtension, M: Positive> RandomWith<SubfieldElements<F, M>> for FieldShares<F, M> {
333    fn random_with(_rng: impl CryptoRngCore, _data: SubfieldElements<F, M>) -> Self {
334        unimplemented!(
335            "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
336            std::any::type_name::<Self>()
337        )
338    }
339
340    /// Secret share a value among n parties, generating an authenticated share for each
341    /// peer with consistent MACs and keys across all peers.
342    fn random_n_with<Container: FromIterator<Self>>(
343        mut rng: impl CryptoRngCore,
344        n_parties: usize,
345        value: SubfieldElements<F, M>,
346    ) -> Container {
347        let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
348        let all_keys = (0..n_parties)
349            .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
350            .collect::<Vec<_>>();
351        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
352        izip_eq!(all_unauth_shares, all_macs, all_keys)
353            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
354            .collect()
355    }
356
357    /// Generate an authenticated share given for each peer given its additve share
358    ///  with consistent MACs and keys across all peers.
359    fn random_n_with_each<Container: FromIterator<Self>>(
360        mut rng: impl CryptoRngCore,
361        unauth_shares: impl IntoExactSizeIterator<Item = SubfieldElements<F, M>>,
362    ) -> Container {
363        let all_unauth_shares = unauth_shares.into_iter().collect::<Vec<_>>();
364        let n_parties = all_unauth_shares.len();
365        let all_keys = (0..n_parties)
366            .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
367            .collect::<Vec<_>>();
368        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
369        izip_eq!(all_unauth_shares, all_macs, all_keys)
370            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
371            .collect()
372    }
373}
374
375impl<F: FieldExtension, M: Positive> RandomWith<Vec<GlobalFieldKey<F>>> for FieldShares<F, M> {
376    /// Generate a random field share from its global keys (alphas).
377    fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalFieldKey<F>>) -> Self {
378        let n_other_parties = alphas.len();
379        FieldShares::new(
380            SubfieldElements::random(&mut rng),
381            FieldElements::<F, M>::random_n(&mut rng, n_other_parties),
382            FieldShareKeys::<F, M>::random_n_with_each(&mut rng, alphas),
383        )
384    }
385
386    /// Generate one random field share per peer from their global keys (alphas).
387    fn random_n_with_each<Container: FromIterator<Self>>(
388        mut rng: impl CryptoRngCore,
389        all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalFieldKey<F>>>,
390    ) -> Container {
391        let all_alphas = all_alphas.into_iter();
392        let all_unauth_shares: Vec<_> = SubfieldElements::random_n(&mut rng, all_alphas.len());
393        let all_keys = all_alphas
394            .into_iter()
395            .map(|my_alphas| FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas))
396            .collect::<Vec<_>>();
397        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
398        izip_eq!(all_unauth_shares, all_macs, all_keys)
399            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
400            .collect()
401    }
402}
403
404impl<F: FieldExtension, M: Positive> RandomWith<(SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>)>
405    for FieldShares<F, M>
406{
407    /// Generate a random field share from its global keys (alphas) and its share
408    fn random_with(
409        mut rng: impl CryptoRngCore,
410        value_alphas: (SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>),
411    ) -> Self {
412        let (value, alphas) = value_alphas;
413        let n_other_parties = alphas.len();
414        FieldShares::new(
415            value,
416            FieldElements::<F, M>::random_n(&mut rng, n_other_parties),
417            FieldShareKeys::<F, M>::random_n_with_each(&mut rng, alphas),
418        )
419    }
420
421    /// Generate one random field share per peer from their global keys (alphas).
422    fn random_n_with_each<Container: FromIterator<Self>>(
423        mut rng: impl CryptoRngCore,
424        unauth_shares_and_alphas: impl IntoIterator<
425            Item = (SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>),
426        >,
427    ) -> Container {
428        let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
429            .into_iter()
430            .map(|(value, my_alphas)| {
431                (
432                    value,
433                    FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas),
434                )
435            })
436            .unzip();
437        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
438        izip_eq!(all_unauth_shares, all_macs, all_keys)
439            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
440            .collect()
441    }
442}
443
444impl<F: FieldExtension, M: Positive>
445    RandomWith<(SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>)> for FieldShares<F, M>
446{
447    fn random_with(
448        _rng: impl CryptoRngCore,
449        _data: (SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>),
450    ) -> Self {
451        unimplemented!(
452            "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
453        );
454    }
455
456    /// Generate a random field share per peer from a value to secret share and global keys
457    /// (alphas).
458    fn random_n_with<Container: FromIterator<Self>>(
459        mut rng: impl CryptoRngCore,
460        n_parties: usize,
461        secret_value_and_alphas: (SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>),
462    ) -> Container {
463        let (secret_value, all_alphas) = secret_value_and_alphas;
464        assert_eq!(
465            all_alphas.len(),
466            n_parties,
467            "Number of alphas must match the number of parties"
468        );
469        let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
470        let all_keys = all_alphas
471            .into_iter()
472            .map(|my_alphas| FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas))
473            .collect::<Vec<_>>();
474        let all_macs = compute_macs(&all_unauth_shares, &all_keys);
475        izip_eq!(all_unauth_shares, all_macs, all_keys)
476            .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
477            .collect()
478    }
479}
480
481// --------------
482// | Arithmetic |
483// --------------
484
485// === Addition === //
486
487impl<F: FieldExtension, M: Positive> Add for FieldShares<F, M> {
488    type Output = FieldShares<F, M>;
489
490    #[inline]
491    fn add(mut self, other: FieldShares<F, M>) -> Self::Output {
492        self.value += other.value;
493        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
494        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
495        self
496    }
497}
498
499impl<F: FieldExtension, M: Positive> Add<FieldShares<F, M>> for &FieldShares<F, M> {
500    type Output = FieldShares<F, M>;
501
502    #[inline]
503    fn add(self, mut other: FieldShares<F, M>) -> Self::Output {
504        other.value += &self.value;
505        izip_eq!(&mut other.macs, &self.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
506        izip_eq!(&mut other.keys, &self.keys).for_each(|(key_i, key_j)| *key_i += key_j);
507        other
508    }
509}
510
511impl<'a, F: FieldExtension, M: Positive> Add<&'a FieldShares<F, M>> for FieldShares<F, M> {
512    type Output = FieldShares<F, M>;
513
514    #[inline]
515    fn add(mut self, other: &'a FieldShares<F, M>) -> Self::Output {
516        self.value += &other.value;
517        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
518        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
519        self
520    }
521}
522
523impl<'a, F: FieldExtension, M: Positive> Add<&'a FieldShares<F, M>> for &FieldShares<F, M> {
524    type Output = FieldShares<F, M>;
525
526    #[inline]
527    fn add(self, other: &'a FieldShares<F, M>) -> Self::Output {
528        let mut res = self.clone();
529        res.value += &other.value;
530        izip_eq!(&mut res.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
531        izip_eq!(&mut res.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
532        res
533    }
534}
535
536// === AddAssign === //
537
538impl<F: FieldExtension, M: Positive> AddAssign for FieldShares<F, M> {
539    #[inline]
540    fn add_assign(&mut self, other: Self) {
541        self.value += other.value;
542        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
543        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
544    }
545}
546
547impl<'a, F: FieldExtension, M: Positive> AddAssign<&'a FieldShares<F, M>> for FieldShares<F, M> {
548    #[inline]
549    fn add_assign(&mut self, other: &'a FieldShares<F, M>) {
550        self.value += &other.value;
551        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
552        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
553    }
554}
555
556// === Subtraction === //
557
558impl<F: FieldExtension, M: Positive> Sub for FieldShares<F, M> {
559    type Output = FieldShares<F, M>;
560
561    #[inline]
562    fn sub(mut self, other: FieldShares<F, M>) -> Self::Output {
563        self.value -= other.value;
564        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
565        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
566        self
567    }
568}
569
570impl<'a, F: FieldExtension, M: Positive> Sub<&'a FieldShares<F, M>> for FieldShares<F, M> {
571    type Output = FieldShares<F, M>;
572
573    #[inline]
574    fn sub(mut self, other: &'a FieldShares<F, M>) -> Self::Output {
575        self.value -= &other.value;
576        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
577        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
578        self
579    }
580}
581
582impl<'a, F: FieldExtension, M: Positive> Sub<&'a FieldShares<F, M>> for &FieldShares<F, M> {
583    type Output = FieldShares<F, M>;
584
585    #[inline]
586    fn sub(self, other: &'a FieldShares<F, M>) -> Self::Output {
587        FieldShares {
588            value: &self.value - &other.value,
589            macs: izip_eq!(&self.macs, &other.macs)
590                .map(|(mac_i, mac_j)| mac_i - mac_j)
591                .collect(),
592            keys: izip_eq!(&self.keys, &other.keys)
593                .map(|(key_i, key_j)| key_i - key_j)
594                .collect(),
595        }
596    }
597}
598
599impl<F: FieldExtension, M: Positive> Sub<FieldShares<F, M>> for &FieldShares<F, M> {
600    type Output = FieldShares<F, M>;
601
602    #[inline]
603    fn sub(self, other: FieldShares<F, M>) -> Self::Output {
604        FieldShares {
605            value: &self.value - &other.value,
606            macs: izip_eq!(&self.macs, &other.macs)
607                .map(|(mac_i, mac_j)| mac_i - mac_j)
608                .collect(),
609            keys: izip_eq!(&self.keys, &other.keys)
610                .map(|(key_i, key_j)| key_i - key_j)
611                .collect(),
612        }
613    }
614}
615
616// === SubAssign === //
617
618impl<F: FieldExtension, M: Positive> SubAssign for FieldShares<F, M> {
619    #[inline]
620    fn sub_assign(&mut self, other: Self) {
621        self.value -= other.value;
622        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
623        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
624    }
625}
626
627impl<'a, F: FieldExtension, M: Positive> SubAssign<&'a FieldShares<F, M>> for FieldShares<F, M> {
628    #[inline]
629    fn sub_assign(&mut self, other: &'a FieldShares<F, M>) {
630        self.value -= &other.value;
631        izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
632        izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
633    }
634}
635
636// === Value multiplication === //
637
638impl<F: FieldExtension, M: Positive> Mul<SubfieldElement<F>> for FieldShares<F, M> {
639    type Output = FieldShares<F, M>;
640
641    #[inline]
642    fn mul(mut self, other: SubfieldElement<F>) -> FieldShares<F, M> {
643        self.value *= other;
644        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
645        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
646        self
647    }
648}
649
650impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElement<F>> for FieldShares<F, M> {
651    type Output = FieldShares<F, M>;
652
653    #[inline]
654    fn mul(mut self, other: &'a SubfieldElement<F>) -> FieldShares<F, M> {
655        self.value *= other;
656        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
657        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
658        self
659    }
660}
661
662impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElements<F, M>> for FieldShares<F, M> {
663    type Output = FieldShares<F, M>;
664
665    #[inline]
666    fn mul(mut self, other: &'a SubfieldElements<F, M>) -> FieldShares<F, M> {
667        self.value *= other;
668        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
669        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
670        self
671    }
672}
673
674impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElements<F, M>> for &FieldShares<F, M> {
675    type Output = FieldShares<F, M>;
676
677    #[inline]
678    fn mul(self, other: &'a SubfieldElements<F, M>) -> FieldShares<F, M> {
679        self.clone() * other
680    }
681}
682
683impl<F: FieldExtension, M: Positive> Mul<SubfieldElements<F, M>> for &FieldShares<F, M> {
684    type Output = FieldShares<F, M>;
685
686    #[inline]
687    fn mul(self, other: SubfieldElements<F, M>) -> FieldShares<F, M> {
688        self.clone() * &other
689    }
690}
691
692// === MulAssign === //
693
694impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElement<F>> for FieldShares<F, M> {
695    #[inline]
696    fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
697        self.value *= other;
698        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
699        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
700    }
701}
702
703impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElements<F, M>>
704    for FieldShares<F, M>
705{
706    #[inline]
707    fn mul_assign(&mut self, other: &'a SubfieldElements<F, M>) {
708        self.value *= other;
709        izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
710        izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
711    }
712}
713
714// === Negation === //
715
716impl<F: FieldExtension, M: Positive> Neg for FieldShares<F, M> {
717    type Output = Self;
718
719    #[inline]
720    fn neg(self) -> Self::Output {
721        FieldShares {
722            value: -self.value,
723            macs: izip_eq!(&self.macs).map(|mac_i| -mac_i).collect(),
724            keys: izip_eq!(&self.keys).map(|key_i| -key_i).collect(),
725        }
726    }
727}
728
729impl<F: FieldExtension, M: Positive> Neg for &FieldShares<F, M> {
730    type Output = FieldShares<F, M>;
731
732    #[inline]
733    fn neg(self) -> Self::Output {
734        FieldShares {
735            value: -&self.value,
736            macs: izip_eq!(&self.macs).map(|mac_i| -mac_i).collect(),
737            keys: izip_eq!(&self.keys).map(|key_i| -key_i).collect(),
738        }
739    }
740}
741
742// === Sum === //
743
744impl<F: FieldExtension, M: Positive> IterSum for FieldShares<F, M> {
745    fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
746        let first = iter.next().unwrap_or_default();
747        iter.fold(first, |acc, x| acc + x)
748    }
749}
750
751// === Constant addition / subtraction === //
752
753impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
754    /// Adds a public constant to the secret shared value, updating the keys accordingly.
755    /// A designated peer (P_0) will modify its value, while the other peers will update their keys.
756    #[inline]
757    pub fn add_secret_owned(
758        mut self,
759        constant: &SubfieldElements<F, M>,
760        is_peer_zero: bool,
761    ) -> Self {
762        if is_peer_zero {
763            self.value += constant;
764        } else {
765            let key0 = self.keys.get_mut(0).expect("Missing key 0");
766            key0.betas -= constant.clone() * *key0.alpha;
767        }
768        self
769    }
770
771    /// Adds a public constant to the secret shared value, updating the keys accordingly.
772    /// A designated peer (P_0) will modify its value, while the other peers will update their keys.
773    #[inline]
774    pub fn add_secret(&self, constant: &SubfieldElements<F, M>, is_peer_zero: bool) -> Self {
775        let result = self.clone();
776        result.add_secret_owned(constant, is_peer_zero)
777    }
778
779    /// Subtracts a public constant batch from the secret shared batch, updating the keys
780    /// accordingly. A designated peer (P_0) will modify its value, while the other peers will
781    /// update their keys.
782    #[inline]
783    pub fn sub_constant_array_owned(
784        mut self,
785        arr: &SubfieldElements<F, M>,
786        is_peer_zero: bool,
787    ) -> Self {
788        if is_peer_zero {
789            self.value -= arr;
790        } else {
791            let key0 = self.keys.get_mut(0).expect("Missing key 0");
792            let alpha = *key0.alpha;
793            izip_eq!(&mut key0.betas, arr).for_each(|(beta, val)| *beta += alpha * val);
794        }
795        self
796    }
797}
798
799// === Constant Time Selection / Equality === //
800
801impl<F: FieldExtension, M: Positive> ConditionallySelectable for FieldShares<F, M> {
802    #[inline]
803    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
804        FieldShares {
805            value: HeapArray::conditional_select(&a.value, &b.value, choice),
806            macs: izip_eq!(&a.macs, &b.macs)
807                .map(|(a_mac, b_mac)| HeapArray::conditional_select(a_mac, b_mac, choice))
808                .collect::<Vec<_>>()
809                .into(),
810            keys: izip_eq!(&a.keys, &b.keys)
811                .map(|(a_key, b_key)| FieldShareKeys::conditional_select(a_key, b_key, choice))
812                .collect::<Vec<_>>()
813                .into(),
814        }
815    }
816}
817
818impl<F: FieldExtension, M: Positive> ConstantTimeEq for FieldShares<F, M> {
819    #[inline]
820    fn ct_eq(&self, other: &Self) -> Choice {
821        self.value.ct_eq(&other.value) & self.keys.ct_eq(&other.keys) & self.macs.ct_eq(&other.macs)
822    }
823}
824
825// === Other Ops === //
826
827impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
828    /// Compute the dot product of the share value with another share.
829    pub fn dot_product(&self, other: &SubfieldElements<F, M>) -> FieldShare<F> {
830        FieldShare {
831            value: izip_eq!(&self.value, other)
832                .map(|(value_i, other_i)| *value_i * other_i)
833                .sum(),
834            macs: izip_eq!(&self.macs)
835                .map(|mac_i| {
836                    izip_eq!(mac_i, other)
837                        .map(|(mac_ij, other_i)| *mac_ij * other_i)
838                        .sum()
839                })
840                .collect(),
841            keys: izip_eq!(&self.keys)
842                .map(|key_i| {
843                    let beta = izip_eq!(&key_i.betas, other)
844                        .map(|(key_ij, other_i)| key_ij * other_i)
845                        .sum();
846                    FieldShareKey {
847                        alpha: key_i.alpha.clone(),
848                        beta,
849                    }
850                })
851                .collect(),
852        }
853    }
854}
855
856// -----------------------
857// |   Split and Merge   |
858// -----------------------
859
860impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
861    // Split the shares into two sets of shares with M1 and M2 shares respectively.
862    pub fn split<M1, M2>(self) -> (FieldShares<F, M1>, FieldShares<F, M2>)
863    where
864        M1: Positive,
865        M2: Positive + Add<M1, Output = M>,
866    {
867        let FieldShares { value, macs, keys } = self;
868
869        let (value1, value2) = value.split::<M1, M2>();
870        let (macs1, macs2): (Vec<_>, Vec<_>) = macs
871            .into_vec()
872            .into_iter()
873            .map(|mac| mac.split::<M1, M2>())
874            .collect();
875
876        let (keys1, keys2): (Vec<_>, Vec<_>) = keys
877            .into_vec()
878            .into_iter()
879            .map(|key| key.split::<M1, M2>())
880            .collect();
881
882        (
883            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
884            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
885        )
886    }
887
888    // Split the shares into two sets of shares with M/2 shares each.
889    pub fn split_halves<MDiv2>(self) -> (FieldShares<F, MDiv2>, FieldShares<F, MDiv2>)
890    where
891        MDiv2: Positive + Mul<U2, Output = M>,
892    {
893        let FieldShares { value, macs, keys } = self;
894
895        let (value1, value2) = value.split_halves::<MDiv2>();
896        let (macs1, macs2): (Vec<_>, Vec<_>) = macs
897            .into_vec()
898            .into_iter()
899            .map(|mac| mac.split_halves::<MDiv2>())
900            .collect();
901
902        let (keys1, keys2): (Vec<_>, Vec<_>) = keys
903            .into_vec()
904            .into_iter()
905            .map(|key| key.split_halves::<MDiv2>())
906            .collect();
907
908        (
909            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
910            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
911        )
912    }
913
914    // Merge two sets of shares with M/2 shares each into a single set of shares with M shares.
915    pub fn merge_halves(this: Self, other: Self) -> FieldShares<F, Prod<M, U2>>
916    where
917        M: Positive + Mul<U2, Output: Positive>,
918    {
919        let FieldShares { value, macs, keys } = this;
920        let FieldShares {
921            value: other_value,
922            macs: other_macs,
923            keys: other_keys,
924        } = other;
925
926        let value = SubfieldElements::merge_halves(value, other_value);
927        let macs = izip_eq!(macs, other_macs)
928            .map(|(mac, other_mac)| FieldElements::merge_halves(mac, other_mac))
929            .collect::<Vec<_>>();
930        let keys = izip_eq!(keys, other_keys)
931            .map(|(key, other_key)| FieldShareKeys::merge_halves(key, other_key))
932            .collect::<Vec<_>>();
933
934        FieldShares::try_new(value, macs.into(), keys.into()).unwrap()
935    }
936
937    // Split the shares into three sets of shares with M1, M2 and M3 shares respectively.
938    pub fn split3<M1, M2, M3>(self) -> (FieldShares<F, M1>, FieldShares<F, M2>, FieldShares<F, M3>)
939    where
940        M1: Positive,
941        M2: Positive + Add<M1>,
942        M3: Positive + Add<Sum<M2, M1>, Output = M>,
943    {
944        let FieldShares { value, macs, keys } = self;
945
946        let (value1, value2, value3) = value.split3::<M1, M2, M3>();
947        let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
948            .into_vec()
949            .into_iter()
950            .map(|mac| mac.split3::<M1, M2, M3>())
951            .multiunzip();
952
953        let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
954            .into_vec()
955            .into_iter()
956            .map(|key| key.split3::<M1, M2, M3>())
957            .multiunzip();
958
959        (
960            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
961            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
962            FieldShares::try_new(value3, macs3.into(), keys3.into()).unwrap(),
963        )
964    }
965
966    // Split the shares into three sets of shares with M/3 shares each.
967    pub fn split_thirds<MDiv3>(
968        self,
969    ) -> (
970        FieldShares<F, MDiv3>,
971        FieldShares<F, MDiv3>,
972        FieldShares<F, MDiv3>,
973    )
974    where
975        MDiv3: Positive + Mul<U3, Output = M>,
976    {
977        let FieldShares { value, macs, keys } = self;
978
979        let (value1, value2, value3) = value.split_thirds::<MDiv3>();
980        let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
981            .into_vec()
982            .into_iter()
983            .map(|mac| mac.split_thirds::<MDiv3>())
984            .multiunzip();
985
986        let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
987            .into_vec()
988            .into_iter()
989            .map(|key| key.split_thirds::<MDiv3>())
990            .multiunzip();
991
992        (
993            FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
994            FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
995            FieldShares::try_new(value3, macs3.into(), keys3.into()).unwrap(),
996        )
997    }
998
999    // Merge three sets of shares with M/3 shares each into a single set of shares with M shares.
1000    pub fn merge_thirds(this: Self, other1: Self, other2: Self) -> FieldShares<F, Prod<M, U3>>
1001    where
1002        M: Positive + Mul<U3, Output: Positive>,
1003    {
1004        let FieldShares {
1005            value: v1,
1006            macs: m1,
1007            keys: k1,
1008        } = this;
1009        let FieldShares {
1010            value: v2,
1011            macs: m2,
1012            keys: k2,
1013        } = other1;
1014        let FieldShares {
1015            value: v3,
1016            macs: m3,
1017            keys: k3,
1018        } = other2;
1019
1020        let value = SubfieldElements::merge_thirds(v1, v2, v3);
1021        let macs = izip_eq!(m1, m2, m3)
1022            .map(|(mac1, mac2, mac3)| FieldElements::merge_thirds(mac1, mac2, mac3))
1023            .collect::<Vec<_>>();
1024        let keys = izip_eq!(k1, k2, k3)
1025            .map(|(key1, key2, key3)| FieldShareKeys::merge_thirds(key1, key2, key3))
1026            .collect::<Vec<_>>();
1027
1028        FieldShares::try_new(value, macs.into(), keys.into()).unwrap()
1029    }
1030}
1031
1032// ------------------------
1033// |   Iterate and Cast   |
1034// ------------------------
1035
1036// === Single Element === //
1037
1038impl<F: FieldExtension> From<FieldShare<F>> for FieldShares<F, U1> {
1039    fn from(share: FieldShare<F>) -> Self {
1040        FieldShares {
1041            value: HeapArray::from(share.value),
1042            macs: share
1043                .macs
1044                .into_vec()
1045                .into_iter()
1046                .map(HeapArray::from)
1047                .collect(),
1048            keys: share
1049                .keys
1050                .into_vec()
1051                .into_iter()
1052                .map(FieldShareKeys::from)
1053                .collect(),
1054        }
1055    }
1056}
1057
1058// === Multiple elements === //
1059
1060impl<F: FieldExtension, M: Positive> From<HeapArray<FieldShare<F>, M>> for FieldShares<F, M> {
1061    fn from(shares: HeapArray<FieldShare<F>, M>) -> Self {
1062        let (values, macs, keys): (Vec<_>, Vec<_>, Vec<_>) = shares
1063            .into_iter()
1064            .map(|share| (share.value, share.macs, share.keys))
1065            .multiunzip();
1066        let macs = transpose(macs)
1067            .into_iter()
1068            .map(HeapArray::from_iter)
1069            .collect::<Box<[_]>>();
1070        let keys = transpose(keys)
1071            .into_iter()
1072            .map(|peer_keys| {
1073                let alpha = peer_keys[0].get_alpha();
1074                let betas = peer_keys
1075                    .into_iter()
1076                    .map(|key| {
1077                        let FieldShareKey { alpha: _, beta } = key;
1078                        beta
1079                    })
1080                    .collect::<HeapArray<_, M>>();
1081                FieldShareKeys::new(alpha, betas)
1082            })
1083            .collect::<Box<[_]>>();
1084
1085        FieldShares {
1086            value: HeapArray::from_iter(values),
1087            macs,
1088            keys,
1089        }
1090    }
1091}
1092
1093// === Iterators === //
1094
1095type SubfieldElementsIterator<F, M> = <SubfieldElements<F, M> as IntoIterator>::IntoIter;
1096type FieldElementsIterator<F, M> = <FieldElements<F, M> as IntoIterator>::IntoIter;
1097
1098#[derive(Default, Clone, Debug)]
1099pub struct FieldSharesIterator<F: FieldExtension, M: Positive> {
1100    index: usize,
1101
1102    value: SubfieldElementsIterator<F, M>,
1103    macs: Vec<FieldElementsIterator<F, M>>,
1104    betas: Vec<FieldElementsIterator<F, M>>,
1105    alphas: Vec<GlobalFieldKey<F>>,
1106}
1107
1108impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldSharesIterator<F, M> {
1109    fn len(&self) -> usize {
1110        M::to_usize() - self.index
1111    }
1112}
1113
1114impl<F: FieldExtension, M: Positive> Iterator for FieldSharesIterator<F, M> {
1115    type Item = FieldShare<F>;
1116
1117    fn next(&mut self) -> Option<Self::Item> {
1118        if self.index < M::to_usize() {
1119            let value = self.value.next()?;
1120            let macs = self
1121                .macs
1122                .iter_mut()
1123                .map(|mac| mac.next())
1124                .collect::<Option<_>>()?;
1125            let keys = izip!(&mut self.betas, &self.alphas)
1126                .map(|(beta, alpha)| {
1127                    beta.next().map(|beta| FieldShareKey {
1128                        alpha: alpha.clone(),
1129                        beta,
1130                    })
1131                })
1132                .collect::<Option<_>>()?;
1133            self.index += 1;
1134            Some(FieldShare::new(value, macs, keys))
1135        } else {
1136            None
1137        }
1138    }
1139}
1140
1141impl<F: FieldExtension, M: Positive> IntoIterator for FieldShares<F, M> {
1142    type Item = FieldShare<F>;
1143    type IntoIter = FieldSharesIterator<F, M>;
1144
1145    fn into_iter(self) -> Self::IntoIter {
1146        let FieldShares { value, macs, keys } = self;
1147        let value = value.into_iter();
1148        let macs = macs
1149            .into_vec()
1150            .into_iter()
1151            .map(|mac| mac.into_iter())
1152            .collect();
1153        let (betas, alphas): (Vec<_>, Vec<_>) = keys
1154            .into_vec()
1155            .into_iter()
1156            .map(|key| (key.betas.into_iter(), key.alpha))
1157            .unzip();
1158
1159        FieldSharesIterator {
1160            index: 0,
1161            value,
1162            macs,
1163            betas,
1164            alphas,
1165        }
1166    }
1167}
1168
1169impl<F: FieldExtension, M: Positive> IntoIterator for &FieldShares<F, M> {
1170    type Item = FieldShare<F>;
1171    type IntoIter = FieldSharesIterator<F, M>;
1172
1173    fn into_iter(self) -> Self::IntoIter {
1174        let value = self.value.clone().into_iter();
1175        let macs = self
1176            .macs
1177            .iter()
1178            .map(|mac| mac.clone().into_iter())
1179            .collect();
1180        let (betas, alphas): (Vec<_>, Vec<_>) = self
1181            .keys
1182            .iter()
1183            .map(|key| (key.betas.clone().into_iter(), key.alpha.clone()))
1184            .unzip();
1185
1186        FieldSharesIterator {
1187            index: 0,
1188            value,
1189            macs,
1190            betas,
1191            alphas,
1192        }
1193    }
1194}
1195
1196impl<F: FieldExtension, N: Positive> FromIterator<FieldShare<F>> for FieldShares<F, N> {
1197    fn from_iter<T: IntoIterator<Item = FieldShare<F>>>(iter: T) -> Self {
1198        let (values, macs, keys): (Vec<_>, Vec<_>, Vec<_>) = iter
1199            .into_iter()
1200            .map(|share| (share.value, share.macs, share.keys))
1201            .multiunzip();
1202        let macs = transpose(macs)
1203            .into_iter()
1204            .map(HeapArray::from_iter)
1205            .collect::<Box<[_]>>();
1206        let keys = transpose(keys)
1207            .into_iter()
1208            .map(|peer_keys| {
1209                let alpha = peer_keys[0].get_alpha();
1210                let betas = peer_keys
1211                    .into_iter()
1212                    .map(|key| {
1213                        let FieldShareKey { alpha: _, beta } = key;
1214                        beta
1215                    })
1216                    .collect::<HeapArray<_, N>>();
1217                FieldShareKeys::new(alpha, betas)
1218            })
1219            .collect::<Box<[_]>>();
1220
1221        FieldShares {
1222            value: HeapArray::from_iter(values),
1223            macs,
1224            keys,
1225        }
1226    }
1227}
1228
1229impl<F: FieldExtension, N: Positive> IntoParallelIterator for FieldShares<F, N> {
1230    type Item = FieldShare<F>;
1231    type Iter = rayon::vec::IntoIter<FieldShare<F>>;
1232
1233    fn into_par_iter(self) -> Self::Iter {
1234        self.into_iter().collect::<Vec<_>>().into_par_iter()
1235    }
1236}
1237
1238// === Chunking === //
1239pub struct FieldSharesChunks<F: FieldExtension, M: Positive + PartialDiv<CS>, CS: Positive> {
1240    field_shares: FieldSharesIterator<F, M>,
1241    current_chunk: usize,
1242    _chunk_size: std::marker::PhantomData<CS>,
1243}
1244
1245impl<F: FieldExtension, M: Positive + PartialDiv<CS>, CS: Positive> FieldSharesChunks<F, M, CS> {
1246    #[allow(clippy::len_without_is_empty)]
1247    pub fn len(&self) -> usize {
1248        // The size is always a multiple of the number of chunks because of the `PartialDiv<CS>`
1249        // bound
1250        M::USIZE / CS::USIZE - self.current_chunk
1251    }
1252}
1253
1254impl<F: FieldExtension, M: Positive + PartialDiv<CS>, CS: Positive> Iterator
1255    for FieldSharesChunks<F, M, CS>
1256{
1257    type Item = FieldShares<F, CS>;
1258
1259    fn next(&mut self) -> Option<Self::Item> {
1260        if self.current_chunk * CS::to_usize() >= M::to_usize() {
1261            return None;
1262        }
1263
1264        let chunk_shares = self
1265            .field_shares
1266            .by_ref()
1267            .take(CS::to_usize())
1268            .collect::<Vec<_>>();
1269
1270        self.current_chunk += 1;
1271
1272        Some(chunk_shares.into_iter().collect())
1273    }
1274}
1275
1276impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
1277    /// Creates an iterator that yields chunks of the specified size. Each chunk is a
1278    /// `FieldShares<F, CS>`.
1279    pub fn chunks<CS: Positive>(&self) -> FieldSharesChunks<F, M, CS>
1280    where
1281        M: PartialDiv<CS>,
1282    {
1283        FieldSharesChunks {
1284            field_shares: self.into_iter(),
1285            current_chunk: 0,
1286            _chunk_size: std::marker::PhantomData,
1287        }
1288    }
1289}
1290
1291#[cfg(test)]
1292mod tests {
1293    use std::ops::Div;
1294
1295    use itertools::enumerate;
1296    use typenum::{Unsigned, U12};
1297
1298    use super::*;
1299    use crate::{
1300        algebra::elliptic_curve::Curve25519Ristretto as C,
1301        random::{self},
1302        sharing::{GlobalScalarKey, ScalarShares, Verifiable},
1303        types::heap_array::curve_arrays::Scalars,
1304    };
1305
1306    // TODO: Generalize once PairwiseAuthenticatedShare trait is implemented.
1307
1308    //////////////////////////////////////////////////
1309    // CHANGE ONLY THESE TO TEST ANOTHER SHARE TYPE //
1310    pub type M = U12;
1311    pub type Value = Scalars<C, M>;
1312    pub type Constant = Scalars<C, M>;
1313    pub type Share = ScalarShares<C, M>;
1314    pub type GlobalKey = GlobalScalarKey<C>;
1315
1316    // Batching
1317    pub type Mdiv2 = <M as Div<U2>>::Output;
1318    pub type ShareMdiv2 = ScalarShares<C, Mdiv2>;
1319    pub type Mdiv3 = <M as Div<U3>>::Output;
1320    pub type ShareMdiv3 = ScalarShares<C, Mdiv3>;
1321    //////////////////////////////////////////////////
1322
1323    pub const N_PARTIES: usize = 3;
1324
1325    #[test]
1326    fn test_open_to() {
1327        let mut rng = random::test_rng();
1328        let local_share = Share::random_with(&mut rng, N_PARTIES);
1329
1330        for i in 0..N_PARTIES - 1 {
1331            let open_share = local_share.open_to(i).unwrap();
1332            assert_eq!(open_share.get_value(), &local_share.value);
1333            assert_eq!(open_share.get_mac(), &local_share.macs[i]);
1334        }
1335    }
1336
1337    #[test]
1338    fn test_random() {
1339        let mut rng = random::test_rng();
1340
1341        // Generate a completely random share
1342        let share = Share::random_with(&mut rng, N_PARTIES);
1343        assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1344        assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1345
1346        // Generate a share with a specific value
1347        let value = &Value::random(&mut rng);
1348        let share_with_value = Share::random_with(&mut rng, (N_PARTIES, value.to_owned()));
1349        assert_eq!(share_with_value.get_value(), value);
1350        assert_eq!(share_with_value.get_macs().len(), N_PARTIES - 1);
1351        assert_eq!(share_with_value.get_keys().len(), N_PARTIES - 1);
1352    }
1353
1354    #[test]
1355    fn test_random_vec_and_reconstruct() {
1356        let mut rng = random::test_rng();
1357
1358        // Generate a vector of random shares, one per party
1359        let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
1360        assert_eq!(shares.len(), N_PARTIES);
1361        for share in &shares {
1362            assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1363            assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1364        }
1365        let unauthenticated_shares = shares
1366            .iter()
1367            .map(|s| s.get_value().to_owned())
1368            .collect::<Vec<_>>();
1369        let expected = Value::from_additive_shares(&unauthenticated_shares);
1370        let reconstructed = Share::reconstruct_all(&shares).unwrap();
1371        assert_eq!(reconstructed, expected);
1372
1373        // Secret share a value among n parties
1374        let value = &Value::random(&mut rng);
1375        let shares: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, value.to_owned());
1376        assert_eq!(shares.len(), N_PARTIES);
1377        for share in &shares {
1378            assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1379            assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1380        }
1381        let reconstructed = Share::reconstruct_all(&shares).unwrap();
1382        assert_eq!(reconstructed, value.to_owned());
1383    }
1384
1385    #[test]
1386    fn test_random_vec_with_global_key_and_reconstruct() {
1387        let mut rng = random::test_rng();
1388
1389        // Generate n authenticated shares from n global keys (alphas)
1390        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1391        let shares_from_alphas: Vec<_> = Share::random_n_with_each(&mut rng, alphas.clone());
1392        assert_eq!(shares_from_alphas.len(), N_PARTIES);
1393        for (share_a, my_alphas) in izip_eq!(&shares_from_alphas, alphas) {
1394            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1395            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1396            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1397        }
1398        let _ = Share::reconstruct_all(&shares_from_alphas).unwrap(); // Verify all MACs
1399
1400        // Generate n authenticated shares from a value and n global keys (alphas)
1401        let value = &Value::random(&mut rng);
1402        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1403        let shares_from_value_and_alphas: Vec<_> =
1404            Share::random_n_with(&mut rng, N_PARTIES, (value.to_owned(), alphas.clone()));
1405        assert_eq!(shares_from_value_and_alphas.len(), N_PARTIES);
1406        for (share_a, my_alphas) in izip_eq!(&shares_from_value_and_alphas, alphas) {
1407            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1408            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1409            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1410        }
1411        let reconstructed = Share::reconstruct_all(&shares_from_value_and_alphas).unwrap();
1412        assert_eq!(&reconstructed, value);
1413
1414        // Generate n authenticated shares from n unauthenticated shares and n global keys (alphas)
1415        let value = Value::random(&mut rng);
1416        let unauth_shares = value.to_additive_shares(N_PARTIES, &mut rng);
1417        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1418        let shares_from_unauth_and_alphas: Vec<_> =
1419            Share::random_n_with_each(&mut rng, izip_eq!(unauth_shares.clone(), alphas.clone()));
1420        assert_eq!(shares_from_unauth_and_alphas.len(), N_PARTIES);
1421        for (share_a, my_alphas) in izip_eq!(&shares_from_unauth_and_alphas, alphas) {
1422            assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1423            assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1424            assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1425        }
1426        let reconstructed = Share::reconstruct_all(&shares_from_unauth_and_alphas).unwrap();
1427        assert_eq!(reconstructed, value);
1428    }
1429
1430    #[test]
1431    fn test_verify_mac() {
1432        let mut rng = random::test_rng();
1433
1434        let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
1435
1436        // Verify each open separately
1437        enumerate(shares.iter()).for_each(|(i, s_i)| {
1438            enumerate(shares.iter())
1439                .filter(|(j, _)| i != *j)
1440                .for_each(|(j, s_j)| {
1441                    let open_share = s_j.open_to(i - (i > j) as usize).unwrap();
1442                    s_i.verify_from(&open_share, j - (j > i) as usize).unwrap();
1443                });
1444        });
1445
1446        // Verify all openings at once
1447        Share::verify_all(&shares).unwrap();
1448    }
1449
1450    #[test]
1451    fn test_add() {
1452        let mut rng = random::test_rng();
1453
1454        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1455        let a = &Value::random(&mut rng);
1456        let b = &Value::random(&mut rng);
1457
1458        let shares_a: Vec<_> =
1459            Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
1460        let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
1461
1462        // &a + &b
1463        let shares_a_ref_plus_b_ref = izip_eq!(&shares_a, &shares_b)
1464            .map(|(share_a, share_b)| share_a + share_b)
1465            .collect::<Vec<_>>();
1466        let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b_ref).unwrap();
1467        assert_eq!(reconstructed, a + b);
1468
1469        // &a + b
1470        let shares_a_ref_plus_b = izip_eq!(&shares_a, shares_b.clone())
1471            .map(|(share_a, share_b)| share_a + share_b)
1472            .collect::<Vec<_>>();
1473        let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b).unwrap();
1474        assert_eq!(reconstructed, a + b);
1475
1476        // a + &b
1477        let shares_a_plus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
1478            .map(|(share_a, share_b)| share_a + share_b)
1479            .collect::<Vec<_>>();
1480        let reconstructed = Share::reconstruct_all(&shares_a_plus_b_ref).unwrap();
1481        assert_eq!(reconstructed, a + b);
1482
1483        // a + b
1484        let shares_a_plus_b = izip_eq!(shares_a.clone(), shares_b.clone())
1485            .map(|(share_a, share_b)| share_a + share_b)
1486            .collect::<Vec<_>>();
1487        let reconstructed = Share::reconstruct_all(&shares_a_plus_b).unwrap();
1488        assert_eq!(reconstructed, a + b);
1489
1490        // a += &b
1491        let mut shares_a_add_assign_b_ref = shares_a.clone();
1492        izip_eq!(&mut shares_a_add_assign_b_ref, &shares_b)
1493            .for_each(|(share_a, share_b)| *share_a += share_b);
1494        let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b_ref).unwrap();
1495        assert_eq!(reconstructed, a + b);
1496
1497        // a += b
1498        let mut shares_a_add_assign_b = shares_a.clone();
1499        izip_eq!(&mut shares_a_add_assign_b, shares_b)
1500            .for_each(|(share_a, share_b)| *share_a += share_b);
1501        let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b).unwrap();
1502        assert_eq!(reconstructed, a + b);
1503    }
1504
1505    #[test]
1506    fn test_add_secret() {
1507        let mut rng = random::test_rng();
1508
1509        let a = &Value::random(&mut rng);
1510        let k = &Value::random(&mut rng);
1511
1512        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1513
1514        // &a + k
1515        let shares_a_plus_k_ref = enumerate(shares_a.iter())
1516            .map(|(i, share_a)| share_a.add_secret(k, i == 0))
1517            .collect::<Vec<_>>();
1518        let reconstructed = Share::reconstruct_all(&shares_a_plus_k_ref).unwrap();
1519        assert_eq!(reconstructed, a + k);
1520
1521        // a + k
1522        let shares_a_plus_k = enumerate(shares_a)
1523            .map(|(i, share_a)| share_a.add_secret_owned(k, i == 0))
1524            .collect::<Vec<_>>();
1525        let reconstructed = Share::reconstruct_all(&shares_a_plus_k).unwrap();
1526        assert_eq!(reconstructed, a + k);
1527    }
1528
1529    #[test]
1530    fn test_mul_constant() {
1531        let mut rng = random::test_rng();
1532
1533        let a = &Value::random(&mut rng);
1534        let k = &Constant::random(&mut rng);
1535
1536        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1537
1538        // &a * k
1539        let shares_a_times_k_ref = izip_eq!(&shares_a)
1540            .map(|share_a| share_a * k.to_owned())
1541            .collect::<Vec<_>>();
1542        let reconstructed = Share::reconstruct_all(&shares_a_times_k_ref).unwrap();
1543        assert_eq!(reconstructed, a.to_owned() * k);
1544
1545        // a * k
1546        let shares_a_times_k = izip_eq!(shares_a.clone())
1547            .map(|share_a| share_a * k)
1548            .collect::<Vec<_>>();
1549        let reconstructed = Share::reconstruct_all(&shares_a_times_k).unwrap();
1550        assert_eq!(reconstructed, a * k);
1551
1552        // a *= k
1553        let mut shares_a_times_k_assign = shares_a.clone();
1554        izip_eq!(&mut shares_a_times_k_assign).for_each(|share_a| *share_a *= k);
1555        let reconstructed = Share::reconstruct_all(&shares_a_times_k_assign).unwrap();
1556        assert_eq!(reconstructed, a * k);
1557    }
1558
1559    #[test]
1560    fn test_sub() {
1561        let mut rng = random::test_rng();
1562        let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1563
1564        let a = &Value::random(&mut rng);
1565        let b = &Value::random(&mut rng);
1566
1567        let shares_a: Vec<_> =
1568            Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
1569        let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
1570
1571        // &a - &b
1572        let shares_a_ref_minus_b_ref = izip_eq!(&shares_a, &shares_b)
1573            .map(|(share_a, share_b)| share_a - share_b)
1574            .collect::<Vec<_>>();
1575
1576        let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b_ref).unwrap();
1577        assert_eq!(reconstructed, a - b);
1578
1579        // &a - b
1580        let shares_a_ref_minus_b = izip_eq!(&shares_a, shares_b.clone())
1581            .map(|(share_a, share_b)| share_a - share_b)
1582            .collect::<Vec<_>>();
1583        let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b).unwrap();
1584        assert_eq!(reconstructed, a - b);
1585
1586        // a - &b
1587        let shares_a_minus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
1588            .map(|(share_a, share_b)| share_a - share_b)
1589            .collect::<Vec<_>>();
1590        let reconstructed = Share::reconstruct_all(&shares_a_minus_b_ref).unwrap();
1591        assert_eq!(reconstructed, a - b);
1592
1593        // a - b
1594        let shares_a_minus_b = izip_eq!(shares_a.clone(), shares_b.clone())
1595            .map(|(share_a, share_b)| share_a - share_b)
1596            .collect::<Vec<_>>();
1597        let reconstructed = Share::reconstruct_all(&shares_a_minus_b).unwrap();
1598        assert_eq!(reconstructed, a - b);
1599
1600        // a -= &b
1601        let mut shares_a_sub_assign_b_ref = shares_a.clone();
1602        izip_eq!(&mut shares_a_sub_assign_b_ref, &shares_b)
1603            .for_each(|(share_a, share_b)| *share_a -= share_b);
1604        let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b_ref).unwrap();
1605        assert_eq!(reconstructed, a - b);
1606
1607        // a -= b
1608        let mut shares_a_sub_assign_b = shares_a.clone();
1609        izip_eq!(&mut shares_a_sub_assign_b, shares_b)
1610            .for_each(|(share_a, share_b)| *share_a -= share_b);
1611        let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b).unwrap();
1612        assert_eq!(reconstructed, a - b);
1613    }
1614
1615    #[test]
1616    fn test_neg() {
1617        let mut rng = random::test_rng();
1618
1619        let a = Value::random(&mut rng);
1620
1621        let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1622
1623        // - &a
1624        let shares_a_neg_ref = shares_a.iter().map(|share_a| -share_a).collect::<Vec<_>>();
1625        let reconstructed = Share::reconstruct_all(&shares_a_neg_ref).unwrap();
1626        assert_eq!(reconstructed, -a.to_owned());
1627
1628        // - a
1629        let shares_a_neg = shares_a
1630            .into_iter()
1631            .map(|share_a| -share_a)
1632            .collect::<Vec<_>>();
1633        let reconstructed = Share::reconstruct_all(&shares_a_neg).unwrap();
1634        assert_eq!(reconstructed, -a.to_owned());
1635    }
1636
1637    #[test]
1638    fn test_conditional_select() {
1639        let mut rng = random::test_rng();
1640
1641        let shares_a = Share::random_with(&mut rng, N_PARTIES);
1642        let shares_b = Share::random_with(&mut rng, N_PARTIES);
1643
1644        // Select shares_a
1645        let choice = Choice::from(0u8);
1646        let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1647        assert_eq!(selected, shares_a);
1648
1649        // Select shares_b
1650        let choice = Choice::from(1u8);
1651        let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1652        assert_eq!(selected, shares_b);
1653    }
1654
1655    #[test]
1656    fn test_ct_eq() {
1657        let mut rng = random::test_rng();
1658
1659        let shares_a = Share::random_with(&mut rng, N_PARTIES);
1660        let shares_b = Share::random_with(&mut rng, N_PARTIES);
1661
1662        // Check equality
1663        assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
1664        assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
1665        assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
1666        assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
1667    }
1668
1669    #[test]
1670    fn test_split_halves() {
1671        let m_div2 = Mdiv2::to_usize();
1672
1673        let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1674
1675        let (shares1, shares2) = shares.clone().split_halves::<Mdiv2>();
1676
1677        // Check that the shares are split correctly
1678        assert_eq!(shares1.get_value().len(), m_div2);
1679        assert_eq!(shares2.get_value().len(), m_div2);
1680
1681        assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div2]);
1682        assert_eq!(shares2.get_value().as_ref(), &shares.get_value()[m_div2..]);
1683
1684        izip_eq!(&shares1.macs, &shares2.macs, &shares.macs).for_each(|(mac1, mac2, mac)| {
1685            assert_eq!(mac1.as_ref(), &mac[..m_div2]);
1686            assert_eq!(mac2.as_ref(), &mac[m_div2..]);
1687        });
1688        izip_eq!(&shares1.keys, &shares2.keys, &shares.keys).for_each(|(key1, key2, key)| {
1689            assert_eq!(key1.alpha, key.alpha);
1690            assert_eq!(key2.alpha, key.alpha);
1691            assert_eq!(key1.betas.as_ref(), &key.betas[..m_div2]);
1692            assert_eq!(key2.betas.as_ref(), &key.betas[m_div2..]);
1693        });
1694
1695        // Check that the shares can be merged back
1696        let merged_shares = ShareMdiv2::merge_halves(shares1, shares2);
1697        assert_eq!(merged_shares, shares);
1698    }
1699
1700    #[test]
1701    fn test_split_thirds() {
1702        let m_div3 = Mdiv3::to_usize();
1703
1704        let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1705
1706        let (shares1, shares2, shares3) = shares.clone().split_thirds::<Mdiv3>();
1707
1708        // Check that the shares are split correctly
1709        assert_eq!(shares1.get_value().len(), m_div3);
1710        assert_eq!(shares2.get_value().len(), m_div3);
1711        assert_eq!(shares3.get_value().len(), m_div3);
1712
1713        assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div3]);
1714        assert_eq!(
1715            shares2.get_value().as_ref(),
1716            &shares.get_value()[m_div3..(2 * m_div3)]
1717        );
1718        assert_eq!(
1719            shares3.get_value().as_ref(),
1720            &shares.get_value()[(2 * m_div3)..]
1721        );
1722
1723        izip_eq!(&shares1.macs, &shares2.macs, &shares3.macs, &shares.macs).for_each(
1724            |(mac1, mac2, mac3, mac)| {
1725                assert_eq!(mac1.as_ref(), &mac[..m_div3]);
1726                assert_eq!(mac2.as_ref(), &mac[m_div3..(2 * m_div3)]);
1727                assert_eq!(mac3.as_ref(), &mac[(2 * m_div3)..(3 * m_div3)]);
1728            },
1729        );
1730
1731        izip_eq!(&shares1.keys, &shares2.keys, &shares3.keys, &shares.keys).for_each(
1732            |(key1, key2, key3, key)| {
1733                assert_eq!(key1.alpha, key.alpha);
1734                assert_eq!(key2.alpha, key.alpha);
1735                assert_eq!(key3.alpha, key.alpha);
1736
1737                assert_eq!(key1.betas.as_ref(), &key.betas[..m_div3]);
1738                assert_eq!(key2.betas.as_ref(), &key.betas[m_div3..(2 * m_div3)]);
1739                assert_eq!(key3.betas.as_ref(), &key.betas[(2 * m_div3)..(3 * m_div3)]);
1740            },
1741        );
1742
1743        // Check that the shares can be merged back
1744        let merged_shares = ShareMdiv3::merge_thirds(shares1, shares2, shares3);
1745        assert_eq!(merged_shares, shares);
1746    }
1747
1748    #[test]
1749    fn test_into_iter() {
1750        let m = M::to_usize();
1751
1752        let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1753
1754        let mut iter = shares.clone().into_iter();
1755        assert_eq!(iter.len(), m);
1756
1757        for i in 0..m {
1758            assert_eq!(iter.len(), m - i);
1759            let share = iter.next().unwrap();
1760            assert_eq!(share.value, shares.get_value()[i]);
1761
1762            for j in 0..N_PARTIES - 1 {
1763                assert_eq!(share.macs[j], shares.macs[j][i]);
1764                assert_eq!(share.keys[j].alpha, shares.keys[j].alpha);
1765                assert_eq!(share.keys[j].beta, shares.keys[j].betas[i]);
1766            }
1767        }
1768    }
1769
1770    #[test]
1771    fn test_from_iterator() {
1772        let mut rng = random::test_rng();
1773        let shares = Share::random_with(&mut rng, N_PARTIES);
1774
1775        let collected: Vec<_> = shares.clone().into_iter().collect();
1776        let from_iterator: Share = collected.into_iter().collect();
1777
1778        assert_eq!(shares, from_iterator);
1779    }
1780
1781    #[test]
1782    #[should_panic]
1783    fn test_from_iterator_unequal_sizes() {
1784        let mut rng = random::test_rng();
1785        let shares = Share::random_with(&mut rng, N_PARTIES);
1786
1787        let mut collected: Vec<_> = shares.clone().into_iter().collect();
1788        collected.pop(); // Make the sizes unequal
1789        let _ = collected.into_iter().collect::<Share>();
1790    }
1791
1792    #[test]
1793    fn test_chunks() {
1794        type ChunkSize = typenum::U4;
1795        let m = M::to_usize();
1796        let chunk_size = ChunkSize::to_usize();
1797        let n_chunks = m / chunk_size;
1798
1799        let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1800        let mut chunks_iter = shares.chunks::<ChunkSize>();
1801
1802        assert_eq!(chunks_iter.len(), n_chunks);
1803
1804        for i in 0..n_chunks {
1805            // Check that the chunk size is correct
1806            assert_eq!(chunks_iter.len(), n_chunks - i);
1807            let chunk = chunks_iter.next().unwrap();
1808            assert_eq!(chunk.value.len(), chunk_size);
1809
1810            for j in 0..chunk_size {
1811                assert_eq!(chunk.value[j], shares.get_value()[i * chunk_size + j]);
1812            }
1813
1814            for (mac_chunk, macs) in izip_eq!(&chunk.macs, &shares.macs) {
1815                for j in 0..chunk_size {
1816                    assert_eq!(mac_chunk[j], macs[i * chunk_size + j]);
1817                }
1818            }
1819
1820            for (key_chunk, keys) in izip_eq!(&chunk.keys, &shares.keys) {
1821                assert_eq!(key_chunk.alpha, keys.alpha);
1822                for j in 0..chunk_size {
1823                    assert_eq!(key_chunk.betas[j], keys.betas[i * chunk_size + j]);
1824                }
1825            }
1826        }
1827
1828        assert!(chunks_iter.next().is_none());
1829    }
1830}