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