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#[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, {
92 pub(crate) value: SubfieldElements<F, M>,
94 pub(crate) macs: Box<[FieldElements<F, M>]>,
96 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 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 }
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
178impl<F: FieldExtension, M: Positive> VerifiableWith for FieldShares<F, M> {
182 type VerificationData = ();
183 #[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 #[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
213impl<F: FieldExtension, M: Positive> Reconstructible for FieldShares<F, M> {
218 type Opening = OpenFieldShares<F, M>;
219 type Secret = SubfieldElements<F, M>;
220
221 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 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 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
257fn 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 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 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 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 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 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 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 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 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 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 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#[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#[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#[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#[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#[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
599impl<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
608impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
611 #[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 #[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 #[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
656impl<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
682impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
685 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
713impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
718 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 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 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 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 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 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
889impl<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
915impl<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
950type 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
1095pub 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 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 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 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 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 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 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 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 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 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 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(); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 let choice = Choice::from(0u8);
1503 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1504 assert_eq!(selected, shares_a);
1505
1506 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 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 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 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 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 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(); 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 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}