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