primitives/sharing/authenticated/batched/
field_shares.rs

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