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