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