Skip to main content

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