1use std::{
2 any::Any,
3 iter::Sum,
4 marker::PhantomData,
5 mem::MaybeUninit,
6 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
7};
8
9use itertools::{enumerate, izip, Itertools};
10use rayon::prelude::IntoParallelIterator;
11use serde::{de::DeserializeOwned, Deserialize, Serialize};
12use subtle::{Choice, ConstantTimeEq};
13use typenum::{PartialDiv, Prod, U1, U2, U3, U5};
14use wincode::{
15 io::{Reader, Writer},
16 ReadResult,
17 SchemaRead,
18 SchemaWrite,
19 WriteResult,
20};
21
22use crate::{
23 algebra::{
24 elliptic_curve::{BaseField, Curve, Point, ScalarAsExtension, ScalarField},
25 field::{
26 binary::Gf2_128,
27 mersenne::Mersenne107,
28 FieldElement,
29 FieldExtension,
30 SubfieldElement,
31 },
32 ops::transpose::transpose,
33 },
34 errors::PrimitiveError,
35 izip_eq,
36 random::{CryptoRngCore, Random, RandomWith},
37 sharing::{
38 authenticated::{GlobalKey, PairwiseAuthKey, PairwiseAuthOpenShare},
39 unauthenticated::AdditiveShares,
40 PairwiseAuthenticated,
41 PlaintextOps,
42 Reconstructible,
43 Verifiable,
44 },
45 types::{
46 heap_array::{CurvePoints, FieldElements, SubfieldElements},
47 Batched,
48 CollectAll,
49 ConditionallySelectable,
50 HeapArray,
51 PeerIndex,
52 Positive,
53 TryFoldAll,
54 },
55 utils::IntoExactSizeIterator,
56};
57
58#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
76#[serde(
77 bound = "V: Serialize + DeserializeOwned, A: Serialize + DeserializeOwned, B: Serialize + DeserializeOwned"
78)]
79#[repr(C)]
80pub struct PairwiseAuthShare<V, A, B> {
81 pub(crate) value: V,
82 pub(crate) macs: Box<[B]>,
83 pub(crate) keys: Box<[PairwiseAuthKey<A, B>]>,
84}
85
86impl<V, A, B> SchemaWrite for PairwiseAuthShare<V, A, B>
87where
88 V: SchemaWrite<Src = V>,
89 B: SchemaWrite<Src = B>,
90 PairwiseAuthKey<A, B>: SchemaWrite<Src = PairwiseAuthKey<A, B>>,
91{
92 type Src = Self;
93
94 fn size_of(src: &Self) -> WriteResult<usize> {
95 Ok(V::size_of(&src.value)?
96 + <Box<[B]> as SchemaWrite>::size_of(&src.macs)?
97 + <Box<[PairwiseAuthKey<A, B>]> as SchemaWrite>::size_of(&src.keys)?)
98 }
99
100 fn write(writer: &mut impl Writer, src: &Self) -> WriteResult<()> {
101 V::write(writer, &src.value)?;
102 <Box<[B]> as SchemaWrite>::write(writer, &src.macs)?;
103 <Box<[PairwiseAuthKey<A, B>]> as SchemaWrite>::write(writer, &src.keys)
104 }
105}
106
107impl<'de, V, A, B> SchemaRead<'de> for PairwiseAuthShare<V, A, B>
108where
109 V: SchemaRead<'de, Dst = V>,
110 B: SchemaRead<'de, Dst = B>,
111 PairwiseAuthKey<A, B>: SchemaRead<'de, Dst = PairwiseAuthKey<A, B>>,
112{
113 type Dst = Self;
114
115 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self>) -> ReadResult<()> {
116 let mut value = MaybeUninit::<V>::uninit();
117 let mut macs = MaybeUninit::<Box<[B]>>::uninit();
118 let mut keys = MaybeUninit::<Box<[PairwiseAuthKey<A, B>]>>::uninit();
119 V::read(reader, &mut value)?;
120 <Box<[B]> as SchemaRead>::read(reader, &mut macs)?;
121 <Box<[PairwiseAuthKey<A, B>]> as SchemaRead>::read(reader, &mut keys)?;
122 let value = unsafe { value.assume_init() };
124 let macs = unsafe { macs.assume_init() };
125 let keys = unsafe { keys.assume_init() };
126 dst.write(PairwiseAuthShare { value, macs, keys });
127 Ok(())
128 }
129}
130
131impl<V, A, B> PairwiseAuthShare<V, A, B> {
132 pub fn try_new(
135 value: V,
136 macs: Box<[B]>,
137 keys: Box<[PairwiseAuthKey<A, B>]>,
138 ) -> Result<Self, PrimitiveError> {
139 if macs.is_empty() {
140 return Err(PrimitiveError::MinimumLength(2, 0));
141 }
142 if macs.len() != keys.len() {
143 return Err(PrimitiveError::InvalidSize(keys.len(), macs.len()));
144 }
145 Ok(Self { value, macs, keys })
146 }
147
148 #[inline]
150 pub fn get_value(&self) -> &V {
151 &self.value
152 }
153
154 #[inline]
156 pub fn get_value_mut(&mut self) -> &mut V {
157 &mut self.value
158 }
159
160 #[inline]
162 pub fn get_macs(&self) -> &[B] {
163 &self.macs
164 }
165
166 #[inline]
168 pub fn get_mac(&self, peer_index: PeerIndex) -> Option<&B> {
169 self.macs.get(peer_index)
170 }
171
172 #[inline]
174 pub fn get_keys(&self) -> &[PairwiseAuthKey<A, B>] {
175 &self.keys
176 }
177
178 #[inline]
180 pub fn get_keys_mut(&mut self) -> &mut [PairwiseAuthKey<A, B>] {
181 &mut self.keys
182 }
183
184 #[inline]
186 pub fn get_key(&self, peer_index: PeerIndex) -> Option<&PairwiseAuthKey<A, B>> {
187 self.keys.get(peer_index)
188 }
189
190 #[inline]
192 pub fn into_value(self) -> V {
193 self.value
194 }
195
196 #[allow(clippy::type_complexity)]
197 #[inline]
199 pub fn into_inner(self) -> (V, Box<[B]>, Box<[PairwiseAuthKey<A, B>]>) {
200 (self.value, self.macs, self.keys)
201 }
202
203 #[inline]
205 pub fn n_parties(&self) -> usize {
206 self.macs.len() + 1
207 }
208
209 #[inline]
211 pub fn n_distant_parties(&self) -> usize {
212 self.macs.len()
213 }
214
215 #[inline]
217 pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalKey<A>> + '_ {
218 self.keys.iter().map(|key| key.alpha())
219 }
220
221 #[inline]
223 pub fn get_betas(&self) -> impl ExactSizeIterator<Item = &B> + '_ {
224 self.keys.iter().map(|key| key.get_beta())
225 }
226}
227
228pub type BatchedShare<V, A, B, M> = PairwiseAuthShare<HeapArray<V, M>, A, HeapArray<B, M>>;
231
232impl<V, A, B, M: Positive> BatchedShare<V, A, B, M>
233where
234 V: Copy + for<'a> Add<&'a V, Output = V>,
235 B: Copy + for<'a> Add<&'a B, Output = B>,
236{
237 pub fn indexed_sum(&self, indices: &[usize]) -> Option<PairwiseAuthShare<V, A, B>> {
246 let (&first, rest) = indices.split_first()?;
247
248 let mut value = self.get_value()[first];
249 let mut macs: Box<[B]> = self.get_macs().iter().map(|mac| mac[first]).collect();
250 let mut keys: Box<[PairwiseAuthKey<A, B>]> = self
251 .get_keys()
252 .iter()
253 .map(|key| PairwiseAuthKey::new(key.alpha(), key.get_beta()[first]))
254 .collect();
255
256 for &i in rest {
257 value = value + &self.get_value()[i];
258 for (acc, mac) in izip_eq!(&mut macs, self.get_macs()) {
259 *acc = *acc + &mac[i];
260 }
261 for (key, src) in izip_eq!(&mut keys, self.get_keys()) {
262 key.beta = key.beta + &src.get_beta()[i];
263 }
264 }
265
266 Some(PairwiseAuthShare { value, macs, keys })
267 }
268}
269
270impl<V, A, B, M: Positive> PlaintextOps<V> for BatchedShare<V, A, B, M>
275where
276 BatchedShare<V, A, B, M>: Reconstructible<Value = HeapArray<V, M>> + Clone,
277 V: Copy,
278 HeapArray<V, M>: for<'a> AddAssign<&'a V> + for<'a> SubAssign<&'a V>,
279 HeapArray<B, M>: for<'b> AddAssign<&'b B> + for<'b> SubAssign<&'b B>,
280 for<'a> V: Mul<&'a A, Output = B>,
281{
282 fn add_plaintext(mut self, scalar: &V, is_first_peer: bool) -> Self {
284 if is_first_peer {
285 self.value += scalar;
286 } else {
287 let key0 = self.keys.get_mut(0).expect("Missing key 0");
288 key0.beta -= &(*scalar * &key0.alpha);
289 }
290 self
291 }
292
293 fn sub_plaintext(mut self, scalar: &V, is_first_peer: bool) -> Self {
295 if is_first_peer {
296 self.value -= scalar;
297 } else {
298 let key0 = self.keys.get_mut(0).expect("Missing key 0");
299 key0.beta += &(*scalar * &key0.alpha);
300 }
301 self
302 }
303}
304
305pub type FieldShare<F> = PairwiseAuthShare<SubfieldElement<F>, FieldElement<F>, FieldElement<F>>;
309pub type Mersenne107Share = FieldShare<Mersenne107>;
311
312pub type FieldExtShare<F> = PairwiseAuthShare<FieldElement<F>, FieldElement<F>, FieldElement<F>>;
315
316pub type PointShare<C> = PairwiseAuthShare<Point<C>, ScalarAsExtension<C>, Point<C>>;
322
323pub type FieldShares<F, M> =
331 PairwiseAuthShare<SubfieldElements<F, M>, FieldElement<F>, FieldElements<F, M>>;
332
333pub type PointShares<C, M> =
342 PairwiseAuthShare<CurvePoints<C, M>, ScalarAsExtension<C>, CurvePoints<C, M>>;
343
344pub type ScalarShare<C> = FieldShare<ScalarField<C>>;
348pub type BaseFieldShare<C> = FieldShare<BaseField<C>>;
350pub type BitShare = FieldShare<Gf2_128>;
352
353pub type ScalarShares<C, M> = FieldShares<ScalarField<C>, M>;
356pub type BaseFieldShares<C, M> = FieldShares<BaseField<C>, M>;
358pub type BitShares<M> = FieldShares<Gf2_128, M>;
360
361impl<V, A, B> PairwiseAuthShare<V, A, B> {
366 pub fn compute_mac(value: V, key: &PairwiseAuthKey<A, B>) -> B
369 where
370 A: Clone,
371 B: for<'b> Add<&'b B, Output = B>,
372 for<'a> V: Mul<&'a A, Output = B>,
373 {
374 value * key.get_alpha() + key.get_beta()
375 }
376
377 pub fn verify_mac(key: &PairwiseAuthKey<A, B>, opening: PairwiseAuthOpenShare<V, B>) -> Choice
380 where
381 A: Clone,
382 B: ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
383 for<'a> V: Mul<&'a A, Output = B>,
384 {
385 let PairwiseAuthOpenShare { value, mac } = opening;
386 let expected_mac = Self::compute_mac(value, key);
387 expected_mac.ct_eq(&mac)
388 }
389
390 pub(crate) fn compute_all_pairwise_macs(
391 all_unauth_shares: &[V],
392 all_keys: &[Box<[PairwiseAuthKey<A, B>]>],
393 ) -> Vec<Box<[B]>>
394 where
395 A: Clone,
396 V: Clone,
397 B: for<'b> Add<&'b B, Output = B>,
398 for<'a> V: Mul<&'a A, Output = B>,
399 {
400 let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
401 enumerate(all_unauth_shares.iter())
402 .map(|(i, my_unauth_share)| {
403 enumerate(all_key_iters.iter_mut())
404 .filter(|(j, _)| *j != i)
405 .map(|(_, keys_iter)| {
406 let next_key = keys_iter.next().unwrap();
407 Self::compute_mac(my_unauth_share.clone(), next_key)
408 })
409 .collect()
410 })
411 .collect()
412 }
413}
414
415impl<V, A, B> PairwiseAuthenticated for PairwiseAuthShare<V, A, B>
416where
417 V: Random + Clone,
418 A: Random + Clone + Any,
419 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
420 for<'a> V: Mul<&'a A, Output = B>,
421{
422 type GlobalAuthKey = GlobalKey<A>;
423
424 fn get_global_keys(&self) -> impl ExactSizeIterator<Item = Self::GlobalAuthKey> {
425 self.get_alphas()
426 }
427}
428
429impl<V, A, B> Verifiable for PairwiseAuthShare<V, A, B>
430where
431 V: Clone
432 + PartialEq
433 + Send
434 + Sync
435 + 'static
436 + Serialize
437 + DeserializeOwned
438 + SchemaWrite<Src = V>
439 + for<'de> SchemaRead<'de, Dst = V>,
440 A: Clone,
441 B: Clone
442 + Send
443 + Sync
444 + 'static
445 + Serialize
446 + DeserializeOwned
447 + SchemaWrite<Src = B>
448 + for<'de> SchemaRead<'de, Dst = B>
449 + ConstantTimeEq
450 + SubAssign
451 + for<'b> Add<&'b B, Output = B>,
452 for<'a> V: Add<&'a V, Output = V>,
453 for<'a> V: Mul<&'a A, Output = B>,
454{
455 #[inline]
457 fn verify_from(
458 &self,
459 open_share: PairwiseAuthOpenShare<V, B>,
460 peer: PeerIndex,
461 ) -> Result<(), PrimitiveError> {
462 let key = self
463 .get_key(peer)
464 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.keys.len()))?;
465 if bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(key, open_share)) {
466 Ok(())
467 } else {
468 Err(PrimitiveError::WrongMAC(format!("peer {peer}")).blame(peer))
469 }
470 }
471
472 #[inline]
474 fn verify(&self, open_shares: Vec<PairwiseAuthOpenShare<V, B>>) -> Result<(), PrimitiveError> {
475 enumerate(izip_eq!(open_shares, &self.keys))
476 .map(|(from_peer, (open_share, key))| {
477 if bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(key, open_share)) {
478 Ok(())
479 } else {
480 Err(PrimitiveError::WrongMAC(format!("peer {from_peer}")).blame(from_peer))
481 }
482 })
483 .collect_errors()?;
484 Ok(())
485 }
486}
487
488impl<V, A, B> Reconstructible for PairwiseAuthShare<V, A, B>
493where
494 V: Clone
495 + PartialEq
496 + Send
497 + Sync
498 + 'static
499 + Serialize
500 + DeserializeOwned
501 + SchemaWrite<Src = V>
502 + for<'de> SchemaRead<'de, Dst = V>,
503 A: Clone,
504 B: Clone
505 + Send
506 + Sync
507 + 'static
508 + Serialize
509 + DeserializeOwned
510 + SchemaWrite<Src = B>
511 + for<'de> SchemaRead<'de, Dst = B>
512 + ConstantTimeEq
513 + SubAssign
514 + for<'b> Add<&'b B, Output = B>,
515 for<'a> V: Add<&'a V, Output = V>,
516 for<'a> V: Mul<&'a A, Output = B>,
517{
518 type Opening = PairwiseAuthOpenShare<V, B>;
519 type Value = V;
520
521 fn open_to(&self, peer: PeerIndex) -> Result<PairwiseAuthOpenShare<V, B>, PrimitiveError> {
523 let mac = self
524 .get_mac(peer)
525 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.macs.len()))?
526 .to_owned();
527 Ok(PairwiseAuthOpenShare::new(self.get_value().to_owned(), mac))
528 }
529
530 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = PairwiseAuthOpenShare<V, B>> {
532 self.get_macs()
533 .iter()
534 .map(|mac| PairwiseAuthOpenShare::new(self.get_value().to_owned(), mac.to_owned()))
535 }
536
537 fn reconstruct(&self, openings: Vec<PairwiseAuthOpenShare<V, B>>) -> Result<V, PrimitiveError> {
539 if openings.len() != self.get_keys().len() {
540 return Err(PrimitiveError::InvalidSize(
541 self.get_keys().len(),
542 openings.len(),
543 ));
544 }
545 let reconstruct = enumerate(izip_eq!(openings, &self.keys)).try_fold_all(
546 self.get_value().to_owned(),
547 |mut reconstructed, (from_peer, (open_share, key))| {
548 reconstructed = reconstructed + open_share.get_value();
549 let mac_error = match bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(
550 key,
551 open_share.clone(),
552 )) {
553 true => None,
554 false => {
555 Some(PrimitiveError::WrongMAC(format!("peer {from_peer}")).blame(from_peer))
556 }
557 };
558 (reconstructed, mac_error)
559 },
560 )?;
561 Ok(reconstruct)
562 }
563}
564
565type NParties = usize;
571
572impl<V, A, B> Random for PairwiseAuthShare<V, A, B>
573where
574 V: Random + Clone,
575 A: Random + Clone,
576 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
577 for<'a> V: Mul<&'a A, Output = B>,
578{
579 fn random(_rng: impl CryptoRngCore) -> Self {
580 unimplemented!(
581 "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
582 std::any::type_name::<Self>()
583 )
584 }
585
586 fn random_n<Container: FromIterator<Self>>(
589 mut rng: impl CryptoRngCore,
590 n_parties: usize,
591 ) -> Container {
592 let all_unauth_shares: Vec<_> = V::random_n(&mut rng, n_parties);
593 let all_keys = (0..n_parties)
594 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
595 .collect::<Vec<_>>();
596 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
597 izip_eq!(all_unauth_shares, all_macs, all_keys)
598 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
599 .collect()
600 }
601}
602
603impl<V, A, B> RandomWith<V> for PairwiseAuthShare<V, A, B>
604where
605 V: AdditiveShares,
606 A: Random + Clone,
607 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
608 for<'a> V: Mul<&'a A, Output = B>,
609{
610 fn random_with(_rng: impl CryptoRngCore, _data: V) -> Self {
611 unimplemented!(
612 "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
613 std::any::type_name::<Self>()
614 )
615 }
616
617 fn random_n_with<Container: FromIterator<Self>>(
620 mut rng: impl CryptoRngCore,
621 n_parties: usize,
622 value: V,
623 ) -> Container {
624 let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
625 let all_keys = (0..n_parties)
626 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
627 .collect::<Vec<_>>();
628 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
629 izip_eq!(all_unauth_shares, all_macs, all_keys)
630 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
631 .collect()
632 }
633
634 fn random_n_with_each<Container: FromIterator<Self>>(
637 mut rng: impl CryptoRngCore,
638 unauth_shares: impl IntoExactSizeIterator<Item = V>,
639 ) -> Container {
640 let all_unauth_shares = unauth_shares.into_iter().collect::<Vec<_>>();
641 let n_parties = all_unauth_shares.len();
642 let all_keys = (0..n_parties)
643 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
644 .collect::<Vec<_>>();
645 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
646 izip_eq!(all_unauth_shares, all_macs, all_keys)
647 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
648 .collect()
649 }
650}
651
652impl<V, A, B> RandomWith<NParties> for PairwiseAuthShare<V, A, B>
653where
654 V: Random,
655 A: Random + Clone,
656 B: Random,
657{
658 fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
660 PairwiseAuthShare {
661 value: V::random(&mut rng),
662 macs: B::random_n(&mut rng, n_parties - 1),
663 keys: PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1),
664 }
665 }
666}
667
668impl<V, A, B> RandomWith<(NParties, V)> for PairwiseAuthShare<V, A, B>
669where
670 V: Clone,
671 A: Random + Clone,
672 B: Random,
673{
674 fn random_with(mut rng: impl CryptoRngCore, (n_parties, value): (NParties, V)) -> Self {
676 PairwiseAuthShare {
677 value,
678 macs: B::random_n(&mut rng, n_parties - 1),
679 keys: PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1),
680 }
681 }
682}
683
684impl<V, A, B> RandomWith<Vec<GlobalKey<A>>> for PairwiseAuthShare<V, A, B>
685where
686 V: Random + Clone,
687 A: Random + Clone,
688 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
689 for<'a> V: Mul<&'a A, Output = B>,
690{
691 fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalKey<A>>) -> Self {
693 let value = V::random(&mut rng);
694 let keys: Box<[_]> = PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, alphas);
695 let macs: Box<[B]> = keys
696 .iter()
697 .map(|key| Self::compute_mac(value.clone(), key))
698 .collect();
699 PairwiseAuthShare { value, macs, keys }
700 }
701
702 fn random_n_with_each<Container: FromIterator<Self>>(
705 mut rng: impl CryptoRngCore,
706 all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalKey<A>>>,
707 ) -> Container {
708 let all_alphas = all_alphas.into_iter();
709 let all_unauth_shares: Vec<_> = V::random_n(&mut rng, all_alphas.len());
710 let all_keys = all_alphas
711 .into_iter()
712 .map(|my_alphas| PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas))
713 .collect::<Vec<_>>();
714 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
715 izip_eq!(all_unauth_shares, all_macs, all_keys)
716 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
717 .collect()
718 }
719}
720
721impl<V, A, B> RandomWith<(V, Vec<GlobalKey<A>>)> for PairwiseAuthShare<V, A, B>
722where
723 V: Clone,
724 A: Random + Clone,
725 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
726 for<'a> V: Mul<&'a A, Output = B>,
727{
728 fn random_with(mut rng: impl CryptoRngCore, (value, alphas): (V, Vec<GlobalKey<A>>)) -> Self {
730 let keys: Box<[_]> = PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, alphas);
731 let macs: Box<[B]> = keys
732 .iter()
733 .map(|key| Self::compute_mac(value.clone(), key))
734 .collect();
735 PairwiseAuthShare { value, macs, keys }
736 }
737
738 fn random_n_with_each<Container: FromIterator<Self>>(
741 mut rng: impl CryptoRngCore,
742 unauth_shares_and_alphas: impl IntoExactSizeIterator<Item = (V, Vec<GlobalKey<A>>)>,
743 ) -> Container {
744 let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
745 .into_iter()
746 .map(|(value, my_alphas)| {
747 (
748 value,
749 PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas),
750 )
751 })
752 .unzip();
753 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
754 izip_eq!(all_unauth_shares, all_macs, all_keys)
755 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
756 .collect()
757 }
758}
759
760impl<V, A, B> RandomWith<(V, Vec<Vec<GlobalKey<A>>>)> for PairwiseAuthShare<V, A, B>
761where
762 V: AdditiveShares,
763 A: Random + Clone,
764 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
765 for<'a> V: Mul<&'a A, Output = B>,
766{
767 fn random_with(_rng: impl CryptoRngCore, _: (V, Vec<Vec<GlobalKey<A>>>)) -> Self {
768 unimplemented!(
769 "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
770 )
771 }
772
773 fn random_n_with<Container: FromIterator<Self>>(
775 mut rng: impl CryptoRngCore,
776 n_parties: usize,
777 (secret_value, all_alphas): (V, Vec<Vec<GlobalKey<A>>>),
778 ) -> Container {
779 assert_eq!(
780 all_alphas.len(),
781 n_parties,
782 "Number of alphas must match the number of parties"
783 );
784 let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
785 let all_keys = all_alphas
786 .into_iter()
787 .map(|my_alphas| PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas))
788 .collect::<Vec<_>>();
789 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
790 izip_eq!(all_unauth_shares, all_macs, all_keys)
791 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
792 .collect()
793 }
794}
795
796#[macros::op_variants(owned, borrowed, flipped_commutative)]
803impl<'a, V, A, B> Add<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
804where
805 for<'v> V: Add<&'v V, Output = V>,
806 for<'b> B: Add<&'b B, Output = B>,
807 for<'k> PairwiseAuthKey<A, B>: Add<&'k PairwiseAuthKey<A, B>, Output = PairwiseAuthKey<A, B>>,
808{
809 type Output = PairwiseAuthShare<V, A, B>;
810
811 #[inline]
812 fn add(self, other: &'a PairwiseAuthShare<V, A, B>) -> Self::Output {
813 PairwiseAuthShare {
814 value: self.value + &other.value,
815 macs: izip_eq!(self.macs, &other.macs)
816 .map(|(mac_i, mac_j)| mac_i + mac_j)
817 .collect(),
818 keys: izip_eq!(self.keys, &other.keys)
819 .map(|(key_i, key_j)| key_i + key_j)
820 .collect(),
821 }
822 }
823}
824
825#[macros::op_variants(owned)]
826impl<'a, V, A, B> AddAssign<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
827where
828 for<'v> V: AddAssign<&'v V>,
829 for<'b> B: AddAssign<&'b B>,
830 for<'k> PairwiseAuthKey<A, B>: AddAssign<&'k PairwiseAuthKey<A, B>>,
831{
832 #[inline]
833 fn add_assign(&mut self, other: &'a PairwiseAuthShare<V, A, B>) {
834 self.value += &other.value;
835 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
836 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
837 }
838}
839
840impl<'a, V, A, B> Sum<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
841where
842 PairwiseAuthShare<V, A, B>: Clone + Default + AddAssign<&'a PairwiseAuthShare<V, A, B>>,
843{
844 #[inline]
845 fn sum<I: Iterator<Item = &'a PairwiseAuthShare<V, A, B>>>(mut iter: I) -> Self {
846 let first = iter.next().cloned().unwrap_or_default();
847 iter.fold(first, |mut acc, item| {
848 acc += item;
849 acc
850 })
851 }
852}
853
854impl<V, A, B> Sum for PairwiseAuthShare<V, A, B>
855where
856 for<'v> V: AddAssign<&'v V>,
857 for<'b> B: AddAssign<&'b B>,
858 for<'k> PairwiseAuthKey<A, B>: AddAssign<&'k PairwiseAuthKey<A, B>>,
859 PairwiseAuthShare<V, A, B>: Default,
860{
861 #[inline]
862 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
863 let first = iter.next().unwrap_or_default();
864 iter.fold(first, |mut acc, item| {
865 acc += &item;
866 acc
867 })
868 }
869}
870
871#[macros::op_variants(owned, borrowed, flipped)]
874impl<'a, V, A, B> Sub<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
875where
876 for<'v> V: Sub<&'v V, Output = V>,
877 for<'b> B: Sub<&'b B, Output = B>,
878 for<'k> PairwiseAuthKey<A, B>: Sub<&'k PairwiseAuthKey<A, B>, Output = PairwiseAuthKey<A, B>>,
879{
880 type Output = PairwiseAuthShare<V, A, B>;
881
882 #[inline]
883 fn sub(self, other: &'a PairwiseAuthShare<V, A, B>) -> Self::Output {
884 PairwiseAuthShare {
885 value: self.value - &other.value,
886 macs: izip_eq!(self.macs, &other.macs)
887 .map(|(mac_i, mac_j)| mac_i - mac_j)
888 .collect(),
889 keys: izip_eq!(self.keys, &other.keys)
890 .map(|(key_i, key_j)| key_i - key_j)
891 .collect(),
892 }
893 }
894}
895
896#[macros::op_variants(owned)]
897impl<'a, V, A, B> SubAssign<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
898where
899 for<'v> V: SubAssign<&'v V>,
900 for<'b> B: SubAssign<&'b B>,
901 for<'k> PairwiseAuthKey<A, B>: SubAssign<&'k PairwiseAuthKey<A, B>>,
902{
903 #[inline]
904 fn sub_assign(&mut self, other: &'a PairwiseAuthShare<V, A, B>) {
905 self.value -= &other.value;
906 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
907 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
908 }
909}
910
911#[macros::op_variants(borrowed)]
914impl<'a, V, V2, A, B, B2, Const> Mul<&'a Const> for PairwiseAuthShare<V, A, B>
915where
916 for<'v> V: Mul<&'v Const, Output = V2>,
917 for<'b> B: Mul<&'b Const, Output = B2>,
918{
919 type Output = PairwiseAuthShare<V2, A, B2>;
920 #[inline]
921 fn mul(self, other: &'a Const) -> Self::Output {
922 PairwiseAuthShare {
923 value: self.value * other,
924 macs: self
925 .macs
926 .into_vec()
927 .into_iter()
928 .map(|mac| mac * other)
929 .collect(),
930 keys: self
931 .keys
932 .into_vec()
933 .into_iter()
934 .map(|key| key * other)
935 .collect(),
936 }
937 }
938}
939
940impl<'a, V, A, B, Const> MulAssign<&'a Const> for PairwiseAuthShare<V, A, B>
943where
944 for<'v> V: MulAssign<&'v Const>,
945 for<'b> B: MulAssign<&'b Const>,
946{
947 #[inline]
948 fn mul_assign(&mut self, other: &'a Const) {
949 self.value *= other;
950 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
951 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
952 }
953}
954
955#[macros::op_variants(borrowed)]
958impl<V, A, B> Neg for PairwiseAuthShare<V, A, B>
959where
960 V: Neg<Output = V>,
961 B: Neg<Output = B>,
962 PairwiseAuthKey<A, B>: Neg<Output = PairwiseAuthKey<A, B>>,
963{
964 type Output = PairwiseAuthShare<V, A, B>;
965
966 #[inline]
967 fn neg(self) -> Self::Output {
968 let PairwiseAuthShare { value, macs, keys } = self;
969 PairwiseAuthShare {
970 value: -value,
971 keys: keys.into_vec().into_iter().map(|key| -key).collect(),
972 macs: macs.into_vec().into_iter().map(|mac| -mac).collect(),
973 }
974 }
975}
976
977impl<V, A, B> PlaintextOps<V> for PairwiseAuthShare<V, A, B>
980where
981 PairwiseAuthShare<V, A, B>: Reconstructible<Value = V>,
982 V: Clone + for<'a> AddAssign<&'a V> + for<'a> SubAssign<&'a V>,
983 A: Clone,
984 B: Clone + for<'b> AddAssign<&'b B> + for<'b> SubAssign<&'b B> + ConstantTimeEq,
985 for<'a> V: Mul<&'a A, Output = B>,
986{
987 #[inline]
990 fn add_plaintext(mut self, ptx: &V, is_first_peer: bool) -> Self {
991 if is_first_peer {
992 self.value += ptx;
993 } else {
994 let key0 = self.keys.get_mut(0).expect("Missing key 0");
995 key0.beta -= &(ptx.to_owned() * &key0.alpha);
996 }
997 self
998 }
999
1000 #[inline]
1003 fn sub_plaintext(mut self, ptx: &V, is_first_peer: bool) -> Self {
1004 if is_first_peer {
1005 self.value -= ptx;
1006 } else {
1007 let key0 = self.keys.get_mut(0).expect("Missing key 0");
1008 key0.beta += &(ptx.to_owned() * &key0.alpha);
1009 }
1010 self
1011 }
1012}
1013
1014impl<V, A, B> ConstantTimeEq for PairwiseAuthShare<V, A, B>
1019where
1020 V: ConstantTimeEq,
1021 B: ConstantTimeEq,
1022 PairwiseAuthKey<A, B>: ConstantTimeEq,
1023{
1024 #[inline]
1025 fn ct_eq(&self, other: &Self) -> Choice {
1026 self.value.ct_eq(&other.value) & self.macs.ct_eq(&other.macs) & self.keys.ct_eq(&other.keys)
1027 }
1028}
1029
1030impl<V, A, B> ConditionallySelectable for PairwiseAuthShare<V, A, B>
1031where
1032 V: ConditionallySelectable,
1033 B: ConditionallySelectable,
1034 PairwiseAuthKey<A, B>: ConditionallySelectable,
1035{
1036 #[inline]
1037 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
1038 PairwiseAuthShare {
1039 value: V::conditional_select(&a.value, &b.value, choice),
1040 macs: izip_eq!(&a.macs, &b.macs)
1041 .map(|(a_mac, b_mac)| B::conditional_select(a_mac, b_mac, choice))
1042 .collect(),
1043 keys: izip_eq!(&a.keys, &b.keys)
1044 .map(|(a_key, b_key)| {
1045 PairwiseAuthKey::<A, B>::conditional_select(a_key, b_key, choice)
1046 })
1047 .collect(),
1048 }
1049 }
1050}
1051
1052#[derive(Clone, Debug)]
1057pub struct BatchedSharesIterator<VIter: Iterator, MacIter: Iterator, A, BIter: Iterator> {
1058 remaining: usize,
1059 value: VIter,
1060 macs: Vec<MacIter>,
1061 betas: Vec<BIter>,
1062 alphas: Vec<GlobalKey<A>>,
1063}
1064
1065impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator<Item = MacIter::Item>> Iterator
1066 for BatchedSharesIterator<VIter, MacIter, A, BIter>
1067{
1068 type Item = PairwiseAuthShare<VIter::Item, A, MacIter::Item>;
1069
1070 fn next(&mut self) -> Option<Self::Item> {
1071 if self.remaining == 0 {
1072 return None;
1073 }
1074 let value = self.value.next()?;
1075 let macs: Box<[_]> = self
1076 .macs
1077 .iter_mut()
1078 .map(|it| it.next())
1079 .collect::<Option<_>>()?;
1080 let keys: Box<[_]> = izip!(&mut self.betas, &self.alphas)
1081 .map(|(beta_iter, alpha)| {
1082 beta_iter
1083 .next()
1084 .map(|beta| PairwiseAuthKey::new(alpha.clone(), beta))
1085 })
1086 .collect::<Option<_>>()?;
1087 self.remaining -= 1;
1088 Some(PairwiseAuthShare { value, macs, keys })
1089 }
1090
1091 fn size_hint(&self) -> (usize, Option<usize>) {
1092 (self.remaining, Some(self.remaining))
1093 }
1094}
1095
1096impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator<Item = MacIter::Item>>
1097 ExactSizeIterator for BatchedSharesIterator<VIter, MacIter, A, BIter>
1098{
1099 fn len(&self) -> usize {
1100 self.remaining
1101 }
1102}
1103
1104impl<V, A, B> IntoIterator for PairwiseAuthShare<V, A, B>
1109where
1110 V: IntoIterator,
1111 V::IntoIter: ExactSizeIterator,
1112 B: IntoIterator,
1113 A: Clone,
1114{
1115 type Item = PairwiseAuthShare<V::Item, A, B::Item>;
1116 type IntoIter = BatchedSharesIterator<V::IntoIter, B::IntoIter, A, B::IntoIter>;
1117
1118 fn into_iter(self) -> Self::IntoIter {
1119 let PairwiseAuthShare { value, macs, keys } = self;
1120 let value_iter = value.into_iter();
1121 let remaining = value_iter.len();
1122 let macs = macs.into_vec().into_iter().map(|m| m.into_iter()).collect();
1123 let (betas, alphas): (Vec<_>, Vec<_>) = keys
1124 .into_vec()
1125 .into_iter()
1126 .map(|k| (k.beta.into_iter(), k.alpha))
1127 .unzip();
1128 BatchedSharesIterator {
1129 remaining,
1130 value: value_iter,
1131 macs,
1132 betas,
1133 alphas,
1134 }
1135 }
1136}
1137
1138impl<V, A, B> IntoIterator for &PairwiseAuthShare<V, A, B>
1139where
1140 V: Clone + IntoIterator,
1141 V::IntoIter: ExactSizeIterator,
1142 B: Clone + IntoIterator,
1143 A: Clone,
1144{
1145 type Item = PairwiseAuthShare<V::Item, A, B::Item>;
1146 type IntoIter = BatchedSharesIterator<V::IntoIter, B::IntoIter, A, B::IntoIter>;
1147
1148 fn into_iter(self) -> Self::IntoIter {
1149 let value_iter = self.value.clone().into_iter();
1150 let remaining = value_iter.len();
1151 let macs = self.macs.iter().map(|m| m.clone().into_iter()).collect();
1152 let (betas, alphas): (Vec<_>, Vec<_>) = self
1153 .keys
1154 .iter()
1155 .map(|k| (k.beta.clone().into_iter(), k.alpha.clone()))
1156 .unzip();
1157 BatchedSharesIterator {
1158 remaining,
1159 value: value_iter,
1160 macs,
1161 betas,
1162 alphas,
1163 }
1164 }
1165}
1166
1167impl<ItemV, A: Clone, ItemB, V, B> FromIterator<PairwiseAuthShare<ItemV, A, ItemB>>
1172 for PairwiseAuthShare<V, A, B>
1173where
1174 V: FromIterator<ItemV>,
1175 B: FromIterator<ItemB>,
1176{
1177 fn from_iter<T: IntoIterator<Item = PairwiseAuthShare<ItemV, A, ItemB>>>(iter: T) -> Self {
1178 let (values, macs, keys): (Vec<_>, Vec<Vec<_>>, Vec<Vec<_>>) = iter
1179 .into_iter()
1180 .map(|s| (s.value, s.macs.into_vec(), s.keys.into_vec()))
1181 .multiunzip();
1182 let macs: Box<[B]> = transpose(macs)
1183 .into_iter()
1184 .map(|pm| pm.into_iter().collect::<B>())
1185 .collect::<Vec<_>>()
1186 .into();
1187 let keys: Box<[PairwiseAuthKey<A, B>]> = transpose(keys)
1188 .into_iter()
1189 .map(|peer_keys: Vec<PairwiseAuthKey<A, ItemB>>| {
1190 let alpha = peer_keys[0].get_alpha().to_owned();
1191 let betas: B = peer_keys.into_iter().map(|k| k.beta).collect();
1192 PairwiseAuthKey::new(alpha.into(), betas)
1193 })
1194 .collect::<Vec<_>>()
1195 .into();
1196 PairwiseAuthShare {
1197 value: values.into_iter().collect::<V>(),
1198 macs,
1199 keys,
1200 }
1201 }
1202}
1203
1204impl<ItemV, A, ItemB> From<PairwiseAuthShare<ItemV, A, ItemB>>
1209 for BatchedShare<ItemV, A, ItemB, U1>
1210{
1211 fn from(share: PairwiseAuthShare<ItemV, A, ItemB>) -> Self {
1212 PairwiseAuthShare {
1213 value: HeapArray::from(share.value),
1214 macs: share
1215 .macs
1216 .into_vec()
1217 .into_iter()
1218 .map(HeapArray::from)
1219 .collect(),
1220 keys: share
1221 .keys
1222 .into_vec()
1223 .into_iter()
1224 .map(PairwiseAuthKey::from)
1225 .collect(),
1226 }
1227 }
1228}
1229
1230impl<ItemV, A: Clone, ItemB, V, B, N: Positive>
1235 From<HeapArray<PairwiseAuthShare<ItemV, A, ItemB>, N>> for PairwiseAuthShare<V, A, B>
1236where
1237 V: FromIterator<ItemV>,
1238 B: FromIterator<ItemB>,
1239{
1240 fn from(shares: HeapArray<PairwiseAuthShare<ItemV, A, ItemB>, N>) -> Self {
1241 shares.into_iter().collect()
1242 }
1243}
1244
1245impl<ItemV: Send, A: Clone + Send, ItemB: Send, M: Positive> IntoParallelIterator
1250 for BatchedShare<ItemV, A, ItemB, M>
1251where
1252 PairwiseAuthShare<ItemV, A, ItemB>: Send,
1253{
1254 type Item = PairwiseAuthShare<ItemV, A, ItemB>;
1255 type Iter = rayon::vec::IntoIter<Self::Item>;
1256
1257 fn into_par_iter(self) -> Self::Iter {
1258 let PairwiseAuthShare { value, macs, keys } = self;
1262 let value_iter = Vec::from(value).into_iter();
1263 let remaining = value_iter.len();
1264 let mac_iters: Vec<_> = macs
1265 .into_vec()
1266 .into_iter()
1267 .map(|m| Vec::from(m).into_iter())
1268 .collect();
1269 let (betas, alphas): (Vec<_>, Vec<_>) = keys
1270 .into_vec()
1271 .into_iter()
1272 .map(|k| (Vec::from(k.beta).into_iter(), k.alpha))
1273 .unzip();
1274 BatchedSharesIterator {
1275 remaining,
1276 value: value_iter,
1277 macs: mac_iters,
1278 betas,
1279 alphas,
1280 }
1281 .collect::<Vec<_>>()
1282 .into_par_iter()
1283 }
1284}
1285
1286impl<V, A, B, M: Positive> Batched for BatchedShare<V, A, B, M>
1291where
1292 V: Send,
1293 B: Send,
1294 A: Clone + Send + Sync,
1295{
1296 type Size = M;
1297}
1298
1299impl<V: Copy, A: Clone, B: Copy, M: Positive> BatchedShare<V, A, B, M> {
1300 #[allow(clippy::type_complexity)]
1301 pub fn split<M1, M2>(self) -> (BatchedShare<V, A, B, M1>, BatchedShare<V, A, B, M2>)
1304 where
1305 M1: Positive,
1306 M2: Positive + Add<M1, Output = M>,
1307 {
1308 let PairwiseAuthShare { value, macs, keys } = self;
1309 let (v1, v2) = value.split::<M1, M2>();
1310 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1311 .into_vec()
1312 .into_iter()
1313 .map(|m| m.split::<M1, M2>())
1314 .unzip();
1315 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1316 .into_vec()
1317 .into_iter()
1318 .map(|k| k.split::<M1, M2>())
1319 .unzip();
1320 (
1321 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1322 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1323 )
1324 }
1325
1326 #[allow(clippy::type_complexity)]
1327 pub fn split_last_pos<M1>(self) -> (BatchedShare<V, A, B, M1>, PairwiseAuthShare<V, A, B>)
1328 where
1329 M1: Positive + Add<typenum::B1, Output = M>,
1330 {
1331 let PairwiseAuthShare { value, macs, keys } = self;
1332 let (v1, v2) = value.split_last_pos();
1333 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1334 .into_vec()
1335 .into_iter()
1336 .map(|m| m.split_last_pos())
1337 .unzip();
1338 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1339 .into_vec()
1340 .into_iter()
1341 .map(|k| k.split_last_pos())
1342 .unzip();
1343 (
1344 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1345 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1346 )
1347 }
1348
1349 #[allow(clippy::type_complexity)]
1350 pub fn split_halves<MDiv2>(self) -> (BatchedShare<V, A, B, MDiv2>, BatchedShare<V, A, B, MDiv2>)
1353 where
1354 MDiv2: Positive + Mul<U2, Output = M>,
1355 {
1356 let PairwiseAuthShare { value, macs, keys } = self;
1357 let (v1, v2) = value.split_halves::<MDiv2>();
1358 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1359 .into_vec()
1360 .into_iter()
1361 .map(|m| m.split_halves::<MDiv2>())
1362 .unzip();
1363 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1364 .into_vec()
1365 .into_iter()
1366 .map(|k| k.split_halves::<MDiv2>())
1367 .unzip();
1368 (
1369 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1370 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1371 )
1372 }
1373
1374 #[allow(clippy::type_complexity)]
1375 pub fn merge_halves(this: Self, other: Self) -> BatchedShare<V, A, B, Prod<M, U2>>
1377 where
1378 M: Mul<U2, Output: Positive>,
1379 A: PartialEq,
1380 {
1381 let PairwiseAuthShare {
1382 value: v1,
1383 macs: m1,
1384 keys: k1,
1385 } = this;
1386 let PairwiseAuthShare {
1387 value: v2,
1388 macs: m2,
1389 keys: k2,
1390 } = other;
1391 let value = HeapArray::merge_halves(v1, v2);
1392 let macs: Box<[_]> = izip_eq!(m1, m2)
1393 .map(|(a, b)| HeapArray::merge_halves(a, b))
1394 .collect();
1395 let keys: Box<[_]> = izip_eq!(k1, k2)
1396 .map(|(a, b)| PairwiseAuthKey::merge_halves(a, b))
1397 .collect();
1398 PairwiseAuthShare::try_new(value, macs, keys).unwrap()
1399 }
1400
1401 #[allow(clippy::type_complexity)]
1402 pub fn split_thirds<MDiv3>(
1405 self,
1406 ) -> (
1407 BatchedShare<V, A, B, MDiv3>,
1408 BatchedShare<V, A, B, MDiv3>,
1409 BatchedShare<V, A, B, MDiv3>,
1410 )
1411 where
1412 MDiv3: Positive + Mul<U3, Output = M>,
1413 {
1414 let PairwiseAuthShare { value, macs, keys } = self;
1415 let (v1, v2, v3) = value.split_thirds::<MDiv3>();
1416 let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
1417 .into_vec()
1418 .into_iter()
1419 .map(|m| m.split_thirds::<MDiv3>())
1420 .multiunzip();
1421 let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
1422 .into_vec()
1423 .into_iter()
1424 .map(|k| k.split_thirds::<MDiv3>())
1425 .multiunzip();
1426 (
1427 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1428 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1429 PairwiseAuthShare::try_new(v3, macs3.into(), keys3.into()).unwrap(),
1430 )
1431 }
1432
1433 #[allow(clippy::type_complexity)]
1434 pub fn split_fifths<MDiv5>(
1436 self,
1437 ) -> (
1438 BatchedShare<V, A, B, MDiv5>,
1439 BatchedShare<V, A, B, MDiv5>,
1440 BatchedShare<V, A, B, MDiv5>,
1441 BatchedShare<V, A, B, MDiv5>,
1442 BatchedShare<V, A, B, MDiv5>,
1443 )
1444 where
1445 MDiv5: Positive + Mul<U5, Output = M>,
1446 {
1447 fn split_array<T: Copy, M: Positive, MDiv5: Positive + Mul<U5, Output = M>>(
1448 arr: HeapArray<T, M>,
1449 ) -> (
1450 HeapArray<T, MDiv5>,
1451 HeapArray<T, MDiv5>,
1452 HeapArray<T, MDiv5>,
1453 HeapArray<T, MDiv5>,
1454 HeapArray<T, MDiv5>,
1455 ) {
1456 let n = MDiv5::USIZE;
1457 let (a, rest) = arr.split_at(n);
1458 let (b, rest) = rest.split_at(n);
1459 let (c, rest) = rest.split_at(n);
1460 let (d, e) = rest.split_at(n);
1461 (
1462 HeapArray::<T, MDiv5>::try_from(a.to_vec()).unwrap(),
1463 HeapArray::<T, MDiv5>::try_from(b.to_vec()).unwrap(),
1464 HeapArray::<T, MDiv5>::try_from(c.to_vec()).unwrap(),
1465 HeapArray::<T, MDiv5>::try_from(d.to_vec()).unwrap(),
1466 HeapArray::<T, MDiv5>::try_from(e.to_vec()).unwrap(),
1467 )
1468 }
1469
1470 let PairwiseAuthShare { value, macs, keys } = self;
1471 let (v1, v2, v3, v4, v5) = split_array::<V, M, MDiv5>(value);
1472 let (macs1, macs2, macs3, macs4, macs5): (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = macs
1473 .into_vec()
1474 .into_iter()
1475 .map(split_array::<B, M, MDiv5>)
1476 .multiunzip();
1477 let (keys1, keys2, keys3, keys4, keys5): (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = keys
1478 .into_vec()
1479 .into_iter()
1480 .map(|k| {
1481 let PairwiseAuthKey { alpha, beta } = k;
1482 let (b1, b2, b3, b4, b5) = split_array::<B, M, MDiv5>(beta);
1483 (
1484 PairwiseAuthKey::new(alpha.clone(), b1),
1485 PairwiseAuthKey::new(alpha.clone(), b2),
1486 PairwiseAuthKey::new(alpha.clone(), b3),
1487 PairwiseAuthKey::new(alpha.clone(), b4),
1488 PairwiseAuthKey::new(alpha, b5),
1489 )
1490 })
1491 .multiunzip();
1492 (
1493 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1494 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1495 PairwiseAuthShare::try_new(v3, macs3.into(), keys3.into()).unwrap(),
1496 PairwiseAuthShare::try_new(v4, macs4.into(), keys4.into()).unwrap(),
1497 PairwiseAuthShare::try_new(v5, macs5.into(), keys5.into()).unwrap(),
1498 )
1499 }
1500
1501 #[allow(clippy::type_complexity)]
1502 pub fn merge_thirds(
1504 first: Self,
1505 second: Self,
1506 third: Self,
1507 ) -> BatchedShare<V, A, B, Prod<M, U3>>
1508 where
1509 M: Mul<U3, Output: Positive>,
1510 A: PartialEq,
1511 {
1512 let PairwiseAuthShare {
1513 value: v1,
1514 macs: m1,
1515 keys: k1,
1516 } = first;
1517 let PairwiseAuthShare {
1518 value: v2,
1519 macs: m2,
1520 keys: k2,
1521 } = second;
1522 let PairwiseAuthShare {
1523 value: v3,
1524 macs: m3,
1525 keys: k3,
1526 } = third;
1527 let value = HeapArray::merge_thirds(v1, v2, v3);
1528 let macs: Box<[_]> = izip_eq!(m1, m2, m3)
1529 .map(|(a, b, c)| HeapArray::merge_thirds(a, b, c))
1530 .collect();
1531 let keys: Box<[_]> = izip_eq!(k1, k2, k3)
1532 .map(|(a, b, c)| PairwiseAuthKey::merge_thirds(a, b, c))
1533 .collect();
1534 PairwiseAuthShare::try_new(value, macs, keys).unwrap()
1535 }
1536
1537 #[allow(clippy::type_complexity)]
1538 pub fn chunks<CS: Positive>(
1540 &self,
1541 ) -> BatchedSharesChunks<
1542 <HeapArray<V, M> as IntoIterator>::IntoIter,
1543 <HeapArray<B, M> as IntoIterator>::IntoIter,
1544 A,
1545 <HeapArray<B, M> as IntoIterator>::IntoIter,
1546 CS,
1547 >
1548 where
1549 M: PartialDiv<CS>,
1550 {
1551 BatchedSharesChunks {
1552 inner: self.into_iter(),
1553 remaining_chunks: M::USIZE / CS::USIZE,
1554 _ds: PhantomData,
1555 }
1556 }
1557
1558 pub fn swap(&mut self, i: usize, j: usize) {
1561 self.value.swap(i, j);
1562 for mac in self.macs.iter_mut() {
1563 mac.swap(i, j);
1564 }
1565 for key in self.keys.iter_mut() {
1566 key.beta.swap(i, j);
1567 }
1568 }
1569}
1570
1571pub struct BatchedSharesChunks<VIter: Iterator, MacIter: Iterator, A, BIter: Iterator, DS: Positive>
1577{
1578 inner: BatchedSharesIterator<VIter, MacIter, A, BIter>,
1579 remaining_chunks: usize,
1580 _ds: PhantomData<DS>,
1581}
1582
1583impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator, DS: Positive>
1584 BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1585{
1586 pub fn len(&self) -> usize {
1587 self.remaining_chunks
1588 }
1589
1590 pub fn is_empty(&self) -> bool {
1591 self.remaining_chunks == 0
1592 }
1593}
1594
1595impl<
1596 VIter: Iterator,
1597 MacIter: Iterator,
1598 A: Clone,
1599 BIter: Iterator<Item = MacIter::Item>,
1600 DS: Positive,
1601 > Iterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1602where
1603 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1604 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1605{
1606 type Item = BatchedShare<VIter::Item, A, MacIter::Item, DS>;
1607
1608 fn next(&mut self) -> Option<Self::Item> {
1609 if self.remaining_chunks == 0 {
1610 return None;
1611 }
1612 let chunk: Vec<_> = self.inner.by_ref().take(DS::to_usize()).collect();
1613 if chunk.is_empty() {
1614 return None;
1615 }
1616 self.remaining_chunks -= 1;
1617 Some(chunk.into_iter().collect())
1618 }
1619
1620 fn size_hint(&self) -> (usize, Option<usize>) {
1621 (self.remaining_chunks, Some(self.remaining_chunks))
1622 }
1623}
1624
1625impl<
1626 VIter: Iterator,
1627 MacIter: Iterator,
1628 A: Clone,
1629 BIter: Iterator<Item = MacIter::Item>,
1630 DS: Positive,
1631 > ExactSizeIterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1632where
1633 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1634 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1635{
1636 fn len(&self) -> usize {
1637 self.remaining_chunks
1638 }
1639}
1640
1641impl<V, A, B, N: Positive> Reconstructible for HeapArray<PairwiseAuthShare<V, A, B>, N>
1648where
1649 PairwiseAuthShare<V, A, B>: Reconstructible,
1650 <PairwiseAuthShare<V, A, B> as Reconstructible>::Opening: Clone,
1651{
1652 type Opening = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening, N>;
1653 type Value = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Value, N>;
1654
1655 fn open_to(&self, for_peer: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
1656 self.into_iter()
1657 .map(|s| s.open_to(for_peer))
1658 .collect::<Result<_, _>>()
1659 }
1660
1661 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
1662 let per_share: Vec<Vec<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening>> = self
1663 .into_iter()
1664 .map(|s| s.open_to_all_others().collect())
1665 .collect();
1666 transpose(per_share)
1667 .into_iter()
1668 .map(|col| col.try_into().expect("size mismatch in open_to_all_others"))
1669 }
1670
1671 fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
1672 self.iter()
1673 .enumerate()
1674 .map(|(i, share)| {
1675 let my_openings: Vec<_> = openings
1676 .iter()
1677 .map(|o| o.get(i).cloned())
1678 .collect::<Option<_>>()
1679 .ok_or_else(|| {
1680 PrimitiveError::InvalidParameters(
1681 "Opening is missing for some share.".to_string(),
1682 )
1683 })?;
1684 share.reconstruct(my_openings)
1685 })
1686 .collect::<Result<_, _>>()
1687 }
1688}
1689
1690impl<C: Curve> From<ScalarShare<C>> for PointShare<C> {
1693 #[inline]
1694 fn from(scalar_share: ScalarShare<C>) -> Self {
1695 scalar_share * &Point::<C>::generator()
1696 }
1697}
1698
1699impl<C: Curve, M: Positive> From<ScalarShares<C, M>> for PointShares<C, M> {
1700 #[inline]
1701 fn from(scalar_shares: ScalarShares<C, M>) -> Self {
1702 scalar_shares * &Point::<C>::generator()
1703 }
1704}
1705
1706impl<F: FieldExtension> From<FieldShare<F>> for FieldExtShare<F> {
1707 fn from(value: FieldShare<F>) -> Self {
1708 let PairwiseAuthShare { value, macs, keys } = value;
1709 let value = FieldElement(F::from_subfield_element(value.0));
1710 Self { value, macs, keys }
1711 }
1712}
1713
1714#[cfg(test)]
1715mod tests {
1716 use std::{fmt::Debug, ops::Div};
1717
1718 use typenum::{U2, U3};
1719
1720 use super::*;
1721 use crate::{random::test_rng, sharing::Verifiable};
1722
1723 #[test]
1725 fn test_indexed_sum_matches_reference() {
1726 use crate::algebra::field::mersenne::Mersenne107;
1727 const N_PARTIES: usize = 3;
1728 let mut rng = test_rng();
1729 let alphas: Vec<GlobalKey<FieldElement<Mersenne107>>> =
1730 Random::random_n(&mut rng, N_PARTIES - 1);
1731 let singles: Vec<FieldShare<Mersenne107>> =
1732 FieldShare::<Mersenne107>::random_n_with(&mut rng, 8, alphas);
1733 let fs: FieldShares<Mersenne107, typenum::U8> = singles.iter().cloned().collect();
1734 let mask = [true, false, true, true, false, false, true, false];
1735 let indices = [0usize, 2, 3, 6];
1736
1737 let expected = izip_eq!(&singles, &mask)
1738 .filter_map(|(s, &m)| m.then_some(s.clone()))
1739 .reduce(|a, b| a + &b);
1740 assert_eq!(fs.indexed_sum(&indices), expected);
1741
1742 assert!(fs.indexed_sum(&[]).is_none());
1744 }
1745
1746 #[test]
1749 fn test_add_plaintext_scalar_matches_reference() {
1750 use crate::{algebra::field::mersenne::Mersenne107, sharing::PlaintextOps};
1751 let mut rng = test_rng();
1752 let fs = FieldShares::<Mersenne107, typenum::U8>::random_with(&mut rng, 3);
1753 let scalar = SubfieldElement::<Mersenne107>::from(7u32);
1754 let broadcast: SubfieldElements<Mersenne107, typenum::U8> =
1755 std::iter::repeat_n(scalar, 8).collect();
1756
1757 for is_first_peer in [true, false] {
1758 assert_eq!(
1759 PlaintextOps::<SubfieldElement<Mersenne107>>::add_plaintext(
1760 fs.clone(),
1761 &scalar,
1762 is_first_peer,
1763 ),
1764 fs.clone().add_plaintext(&broadcast, is_first_peer),
1765 );
1766 assert_eq!(
1767 PlaintextOps::<SubfieldElement<Mersenne107>>::sub_plaintext(
1768 fs.clone(),
1769 &scalar,
1770 is_first_peer,
1771 ),
1772 fs.clone().sub_plaintext(&broadcast, is_first_peer),
1773 );
1774 }
1775 }
1776
1777 pub(super) trait ShareValue<A, B, Const>:
1783 Clone
1784 + PartialEq
1785 + Debug
1786 + Random
1787 + AdditiveShares
1788 + ConstantTimeEq
1789 + ConditionallySelectable
1790 + Neg<Output = Self>
1791 + for<'a> Sub<&'a Self, Output = Self>
1792 + for<'a> AddAssign<&'a Self>
1793 + for<'a> Mul<&'a A, Output = B>
1794 + for<'a> Mul<&'a Const, Output = Self>
1795 + for<'a> MulAssign<&'a Const>
1796 + Send
1797 + Sync
1798 + 'static
1799 + Serialize
1800 + DeserializeOwned
1801 + SchemaWrite<Src = Self>
1802 + for<'de> SchemaRead<'de, Dst = Self>
1803 {
1804 }
1805
1806 impl<V, A, B, Const> ShareValue<A, B, Const> for V where
1807 V: Clone
1808 + PartialEq
1809 + Debug
1810 + Random
1811 + AdditiveShares
1812 + ConstantTimeEq
1813 + ConditionallySelectable
1814 + Neg<Output = V>
1815 + for<'a> Sub<&'a V, Output = V>
1816 + for<'a> AddAssign<&'a V>
1817 + for<'a> Mul<&'a A, Output = B>
1818 + for<'a> Mul<&'a Const, Output = V>
1819 + for<'a> MulAssign<&'a Const>
1820 + Send
1821 + Sync
1822 + 'static
1823 + Serialize
1824 + DeserializeOwned
1825 + SchemaWrite<Src = V>
1826 + for<'de> SchemaRead<'de, Dst = V>
1827 {
1828 }
1829
1830 pub(super) trait ShareKey:
1834 Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1835 {
1836 }
1837
1838 impl<A> ShareKey for A where
1839 A: Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1840 {
1841 }
1842
1843 pub(super) trait ShareMac<V, A, Const>:
1847 Clone
1848 + PartialEq
1849 + Debug
1850 + Random
1851 + ConstantTimeEq
1852 + ConditionallySelectable
1853 + SubAssign
1854 + Neg<Output = Self>
1855 + for<'b> Add<&'b Self, Output = Self>
1856 + for<'b> AddAssign<&'b Self>
1857 + for<'b> Sub<&'b Self, Output = Self>
1858 + for<'b> SubAssign<&'b Self>
1859 + for<'c> Mul<&'c Const, Output = Self>
1860 + for<'c> MulAssign<&'c Const>
1861 + Send
1862 + Sync
1863 + 'static
1864 + Serialize
1865 + DeserializeOwned
1866 + SchemaWrite<Src = Self>
1867 + for<'de> SchemaRead<'de, Dst = Self>
1868 {
1869 }
1870
1871 impl<B, V, A, Const> ShareMac<V, A, Const> for B where
1872 B: Clone
1873 + PartialEq
1874 + Debug
1875 + Random
1876 + ConstantTimeEq
1877 + ConditionallySelectable
1878 + SubAssign
1879 + Neg<Output = B>
1880 + for<'b> Add<&'b B, Output = B>
1881 + for<'b> AddAssign<&'b B>
1882 + for<'b> Sub<&'b B, Output = B>
1883 + for<'b> SubAssign<&'b B>
1884 + for<'c> Mul<&'c Const, Output = B>
1885 + for<'c> MulAssign<&'c Const>
1886 + Send
1887 + Sync
1888 + 'static
1889 + Serialize
1890 + DeserializeOwned
1891 + SchemaWrite<Src = B>
1892 + for<'de> SchemaRead<'de, Dst = B>
1893 {
1894 }
1895
1896 pub(super) trait BatchedShareItem<A, IB>:
1902 Copy
1903 + Clone
1904 + PartialEq
1905 + Debug
1906 + Random
1907 + ConstantTimeEq
1908 + ConditionallySelectable
1909 + for<'a> Mul<&'a A, Output = IB>
1910 {
1911 }
1912
1913 impl<IV, A, IB> BatchedShareItem<A, IB> for IV where
1914 IV: Copy
1915 + Clone
1916 + PartialEq
1917 + Debug
1918 + Random
1919 + ConstantTimeEq
1920 + ConditionallySelectable
1921 + for<'a> Mul<&'a A, Output = IB>
1922 {
1923 }
1924
1925 pub(super) trait BatchedShareMacItem<IV, A>:
1929 Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1930 {
1931 }
1932
1933 impl<IB, IV, A> BatchedShareMacItem<IV, A> for IB where
1934 IB: Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1935 {
1936 }
1937
1938 pub(super) fn test_open_to<V, A, B, Const>(n_parties: usize)
1941 where
1942 V: ShareValue<A, B, Const>,
1943 A: ShareKey,
1944 B: ShareMac<V, A, Const>,
1945 Const: Random,
1946 {
1947 let mut rng = test_rng();
1948 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1949 for i in 0..n_parties - 1 {
1950 let open = share.open_to(i).unwrap();
1951 assert_eq!(open.get_value(), &share.value);
1952 assert_eq!(open.get_mac(), &share.macs[i]);
1953 }
1954 }
1955
1956 pub(super) fn test_random<V, A, B, Const>(n_parties: usize)
1957 where
1958 V: ShareValue<A, B, Const>,
1959 A: ShareKey,
1960 B: ShareMac<V, A, Const>,
1961 Const: Random,
1962 {
1963 let mut rng = test_rng();
1964 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1965 assert_eq!(share.get_macs().len(), n_parties - 1);
1966 assert_eq!(share.get_keys().len(), n_parties - 1);
1967 let value = V::random(&mut rng);
1968 let share_with_value =
1969 PairwiseAuthShare::<V, A, B>::random_with(&mut rng, (n_parties, value.clone()));
1970 assert_eq!(share_with_value.get_value(), &value);
1971 assert_eq!(share_with_value.get_macs().len(), n_parties - 1);
1972 assert_eq!(share_with_value.get_keys().len(), n_parties - 1);
1973 }
1974
1975 pub(super) fn test_random_vec_and_reconstruct<V, A, B, Const>(n_parties: usize)
1976 where
1977 V: ShareValue<A, B, Const>,
1978 A: ShareKey,
1979 B: ShareMac<V, A, Const>,
1980 Const: Random,
1981 {
1982 let mut rng = test_rng();
1983 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
1984 assert_eq!(shares.len(), n_parties);
1985 for share in &shares {
1986 assert_eq!(share.get_macs().len(), n_parties - 1);
1987 assert_eq!(share.get_keys().len(), n_parties - 1);
1988 }
1989 let unauth: Vec<_> = shares.iter().map(|s| s.get_value().clone()).collect();
1990 let expected = V::from_additive_shares(&unauth);
1991 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1992 assert_eq!(reconstructed, expected);
1993
1994 let value = V::random(&mut rng);
1995 let shares: Vec<_> =
1996 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, value.clone());
1997 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1998 assert_eq!(reconstructed, value);
1999 }
2000
2001 pub(super) fn test_random_vec_with_global_key_and_reconstruct<V, A, B, Const>(n_parties: usize)
2002 where
2003 V: ShareValue<A, B, Const>,
2004 A: ShareKey,
2005 B: ShareMac<V, A, Const>,
2006 Const: Random,
2007 {
2008 let mut rng = test_rng();
2009 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2011 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2012 .collect();
2013 let shares_from_alphas: Vec<_> =
2014 PairwiseAuthShare::<V, A, B>::random_n_with_each(&mut rng, alphas.clone());
2015 assert_eq!(shares_from_alphas.len(), n_parties);
2016 for (share, my_alphas) in izip_eq!(&shares_from_alphas, &alphas) {
2017 assert_eq!(share.get_macs().len(), n_parties - 1);
2018 assert_eq!(share.get_keys().len(), n_parties - 1);
2019 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
2020 }
2021 let _ = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_alphas).unwrap();
2022
2023 let value = V::random(&mut rng);
2025 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2026 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2027 .collect();
2028 let shares_from_value_and_alphas: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
2029 &mut rng,
2030 n_parties,
2031 (value.clone(), alphas.clone()),
2032 );
2033 assert_eq!(shares_from_value_and_alphas.len(), n_parties);
2034 for (share, my_alphas) in izip_eq!(&shares_from_value_and_alphas, &alphas) {
2035 assert_eq!(share.get_macs().len(), n_parties - 1);
2036 assert_eq!(share.get_keys().len(), n_parties - 1);
2037 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
2038 }
2039 let reconstructed =
2040 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_value_and_alphas).unwrap();
2041 assert_eq!(reconstructed, value);
2042
2043 let value = V::random(&mut rng);
2045 let unauth = value.to_additive_shares(n_parties, &mut rng);
2046 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2047 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2048 .collect();
2049 let shares_from_unauth: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with_each(
2050 &mut rng,
2051 izip_eq!(unauth, alphas.clone()),
2052 );
2053 assert_eq!(shares_from_unauth.len(), n_parties);
2054 for (share, my_alphas) in izip_eq!(&shares_from_unauth, &alphas) {
2055 assert_eq!(share.get_macs().len(), n_parties - 1);
2056 assert_eq!(share.get_keys().len(), n_parties - 1);
2057 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
2058 }
2059 let reconstructed =
2060 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_unauth).unwrap();
2061 assert_eq!(reconstructed, value);
2062 }
2063
2064 pub(super) fn test_verify_mac<V, A, B, Const>(n_parties: usize)
2065 where
2066 V: ShareValue<A, B, Const>,
2067 A: ShareKey,
2068 B: ShareMac<V, A, Const>,
2069 Const: Random,
2070 {
2071 let mut rng = test_rng();
2072 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
2073 for i in 0..shares.len() {
2074 for j in 0..shares.len() {
2075 if i == j {
2076 continue;
2077 }
2078 let open = shares[j].open_to(i - (i > j) as usize).unwrap();
2079 shares[i].verify_from(open, j - (j > i) as usize).unwrap();
2080 }
2081 }
2082 PairwiseAuthShare::<V, A, B>::verify_all(shares).unwrap();
2083 }
2084
2085 pub(super) fn test_add<V, A, B, Const>(n_parties: usize)
2086 where
2087 V: ShareValue<A, B, Const>,
2088 A: ShareKey,
2089 B: ShareMac<V, A, Const>,
2090 Const: Random,
2091 {
2092 let mut rng = test_rng();
2093 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2094 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2095 .collect();
2096 let a = V::random(&mut rng);
2097 let b = V::random(&mut rng);
2098 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
2099 &mut rng,
2100 n_parties,
2101 (a.clone(), alphas.clone()),
2102 );
2103 let shares_b: Vec<_> =
2104 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
2105 let expected = a.clone() + &b;
2106
2107 let sum: Vec<_> = izip_eq!(&shares_a, &shares_b)
2108 .map(|(sa, sb)| sa + sb)
2109 .collect();
2110 assert_eq!(
2111 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2112 expected
2113 );
2114
2115 let sum: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
2116 .map(|(sa, sb)| sa + sb)
2117 .collect();
2118 assert_eq!(
2119 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2120 expected
2121 );
2122
2123 let sum: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
2124 .map(|(sa, sb)| sa + sb)
2125 .collect();
2126 assert_eq!(
2127 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2128 expected
2129 );
2130
2131 let sum: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
2132 .map(|(sa, sb)| sa + sb)
2133 .collect();
2134 assert_eq!(
2135 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2136 expected
2137 );
2138
2139 let mut shares_a_mut = shares_a.clone();
2140 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa += sb);
2141 assert_eq!(
2142 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2143 expected
2144 );
2145
2146 let mut shares_a_mut = shares_a;
2147 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa += sb);
2148 assert_eq!(
2149 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2150 expected
2151 );
2152 }
2153
2154 pub(super) fn test_add_plaintext<V, A, B, Const>(n_parties: usize)
2155 where
2156 V: ShareValue<A, B, Const>,
2157 A: ShareKey,
2158 B: ShareMac<V, A, Const>,
2159 Const: Random,
2160 {
2161 let mut rng = test_rng();
2162 let a = V::random(&mut rng);
2163 let k = V::random(&mut rng);
2164 let shares_a: Vec<_> =
2165 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2166
2167 let shares_plus_k_ref: Vec<_> = shares_a
2168 .iter()
2169 .enumerate()
2170 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
2171 .collect();
2172 assert_eq!(
2173 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k_ref).unwrap(),
2174 a.clone() + &k,
2175 );
2176
2177 let shares_plus_k: Vec<_> = shares_a
2178 .into_iter()
2179 .enumerate()
2180 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
2181 .collect();
2182 assert_eq!(
2183 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k).unwrap(),
2184 a + &k,
2185 );
2186 }
2187
2188 pub(super) fn test_mul_constant<V, A, B, Const>(n_parties: usize)
2189 where
2190 V: ShareValue<A, B, Const>,
2191 A: ShareKey,
2192 B: ShareMac<V, A, Const>,
2193 Const: Random + PartialEq + Debug,
2194 {
2195 let mut rng = test_rng();
2196 let a = V::random(&mut rng);
2197 let k = Const::random(&mut rng);
2198 let shares_a: Vec<_> =
2199 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2200
2201 let shares_a_times_k: Vec<_> = izip_eq!(shares_a.clone()).map(|sa| sa * &k).collect();
2202 assert_eq!(
2203 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_times_k).unwrap(),
2204 a.clone() * &k,
2205 );
2206
2207 let mut shares_a_mut = shares_a;
2208 izip_eq!(&mut shares_a_mut).for_each(|sa| *sa *= &k);
2209 assert_eq!(
2210 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2211 a * &k,
2212 );
2213 }
2214
2215 pub(super) fn test_sub<V, A, B, Const>(n_parties: usize)
2216 where
2217 V: ShareValue<A, B, Const>,
2218 A: ShareKey,
2219 B: ShareMac<V, A, Const>,
2220 Const: Random,
2221 {
2222 let mut rng = test_rng();
2223 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2224 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2225 .collect();
2226 let a = V::random(&mut rng);
2227 let b = V::random(&mut rng);
2228 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
2229 &mut rng,
2230 n_parties,
2231 (a.clone(), alphas.clone()),
2232 );
2233 let shares_b: Vec<_> =
2234 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
2235 let expected = a.clone() - &b;
2236
2237 let diff: Vec<_> = izip_eq!(&shares_a, &shares_b)
2238 .map(|(sa, sb)| sa - sb)
2239 .collect();
2240 assert_eq!(
2241 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2242 expected
2243 );
2244
2245 let diff: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
2246 .map(|(sa, sb)| sa - sb)
2247 .collect();
2248 assert_eq!(
2249 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2250 expected
2251 );
2252
2253 let diff: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
2254 .map(|(sa, sb)| sa - sb)
2255 .collect();
2256 assert_eq!(
2257 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2258 expected
2259 );
2260
2261 let diff: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
2262 .map(|(sa, sb)| sa - sb)
2263 .collect();
2264 assert_eq!(
2265 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2266 expected
2267 );
2268
2269 let mut shares_a_mut = shares_a.clone();
2270 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa -= sb);
2271 assert_eq!(
2272 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2273 expected
2274 );
2275
2276 let mut shares_a_mut = shares_a;
2277 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa -= sb);
2278 assert_eq!(
2279 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2280 expected
2281 );
2282 }
2283
2284 pub(super) fn test_neg<V, A, B, Const>(n_parties: usize)
2285 where
2286 V: ShareValue<A, B, Const>,
2287 A: ShareKey,
2288 B: ShareMac<V, A, Const>,
2289 Const: Random,
2290 {
2291 let mut rng = test_rng();
2292 let a = V::random(&mut rng);
2293 let shares_a: Vec<_> =
2294 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2295
2296 let neg_ref: Vec<_> = shares_a.iter().map(|sa| -sa).collect();
2297 assert_eq!(
2298 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg_ref).unwrap(),
2299 -a.clone(),
2300 );
2301 let neg: Vec<_> = shares_a.into_iter().map(|sa| -sa).collect();
2302 assert_eq!(
2303 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg).unwrap(),
2304 -a,
2305 );
2306 }
2307
2308 pub(super) fn test_conditional_select<V, A, B, Const>(n_parties: usize)
2309 where
2310 V: ShareValue<A, B, Const>,
2311 A: ShareKey,
2312 B: ShareMac<V, A, Const>,
2313 Const: Random,
2314 {
2315 let mut rng = test_rng();
2316 let shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2317 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2318 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2319 &shares_a,
2320 &shares_b,
2321 Choice::from(0u8),
2322 );
2323 assert_eq!(selected, shares_a);
2324 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2325 &shares_a,
2326 &shares_b,
2327 Choice::from(1u8),
2328 );
2329 assert_eq!(selected, shares_b);
2330 }
2331
2332 pub(super) fn test_ct_eq<V, A, B, Const>(n_parties: usize)
2333 where
2334 V: ShareValue<A, B, Const>,
2335 A: ShareKey,
2336 B: ShareMac<V, A, Const>,
2337 Const: Random,
2338 {
2339 let mut rng = test_rng();
2340 let shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2341 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2342 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
2343 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
2344 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
2345 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
2346 }
2347
2348 pub(super) fn test_split_halves<IV, A, IB, M, MDiv2>(n_parties: usize)
2351 where
2352 IV: BatchedShareItem<A, IB>,
2353 A: ShareKey,
2354 IB: BatchedShareMacItem<IV, A>,
2355 M: Positive + Div<U2, Output = MDiv2>,
2356 MDiv2: Positive + Mul<U2, Output = M>,
2357 {
2358 let mut rng = test_rng();
2359 let m_div2 = MDiv2::to_usize();
2360 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2361 let (shares1, shares2) = shares.clone().split_halves::<MDiv2>();
2362
2363 assert_eq!(shares1.get_value().len(), m_div2);
2364 assert_eq!(shares2.get_value().len(), m_div2);
2365 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div2]);
2366 assert_eq!(shares2.get_value().as_ref(), &shares.get_value()[m_div2..]);
2367
2368 izip_eq!(&shares1.macs, &shares2.macs, &shares.macs).for_each(|(mac1, mac2, mac)| {
2369 assert_eq!(mac1.as_ref(), &mac[..m_div2]);
2370 assert_eq!(mac2.as_ref(), &mac[m_div2..]);
2371 });
2372 izip_eq!(&shares1.keys, &shares2.keys, &shares.keys).for_each(|(key1, key2, key)| {
2373 assert_eq!(key1.alpha, key.alpha);
2374 assert_eq!(key2.alpha, key.alpha);
2375 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div2]);
2376 assert_eq!(key2.beta.as_ref(), &key.beta[m_div2..]);
2377 });
2378
2379 let merged = BatchedShare::<IV, A, IB, MDiv2>::merge_halves(shares1, shares2);
2380 assert_eq!(merged, shares);
2381 }
2382
2383 pub(super) fn test_split_thirds<IV, A, IB, M, MDiv3>(n_parties: usize)
2384 where
2385 IV: BatchedShareItem<A, IB>,
2386 A: ShareKey,
2387 IB: BatchedShareMacItem<IV, A>,
2388 M: Positive,
2389 MDiv3: Positive + Mul<U3, Output = M>,
2390 M: Mul<U3, Output: Positive>,
2391 {
2392 let mut rng = test_rng();
2393 let m_div3 = MDiv3::to_usize();
2394 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2395 let (shares1, shares2, shares3) = shares.clone().split_thirds::<MDiv3>();
2396
2397 assert_eq!(shares1.get_value().len(), m_div3);
2398 assert_eq!(shares2.get_value().len(), m_div3);
2399 assert_eq!(shares3.get_value().len(), m_div3);
2400 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div3]);
2401 assert_eq!(
2402 shares2.get_value().as_ref(),
2403 &shares.get_value()[m_div3..(2 * m_div3)]
2404 );
2405 assert_eq!(
2406 shares3.get_value().as_ref(),
2407 &shares.get_value()[(2 * m_div3)..]
2408 );
2409
2410 izip_eq!(&shares1.macs, &shares2.macs, &shares3.macs, &shares.macs).for_each(
2411 |(mac1, mac2, mac3, mac)| {
2412 assert_eq!(mac1.as_ref(), &mac[..m_div3]);
2413 assert_eq!(mac2.as_ref(), &mac[m_div3..(2 * m_div3)]);
2414 assert_eq!(mac3.as_ref(), &mac[(2 * m_div3)..(3 * m_div3)]);
2415 },
2416 );
2417 izip_eq!(&shares1.keys, &shares2.keys, &shares3.keys, &shares.keys).for_each(
2418 |(key1, key2, key3, key)| {
2419 assert_eq!(key1.alpha, key.alpha);
2420 assert_eq!(key2.alpha, key.alpha);
2421 assert_eq!(key3.alpha, key.alpha);
2422 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div3]);
2423 assert_eq!(key2.beta.as_ref(), &key.beta[m_div3..(2 * m_div3)]);
2424 assert_eq!(key3.beta.as_ref(), &key.beta[(2 * m_div3)..(3 * m_div3)]);
2425 },
2426 );
2427
2428 let merged = BatchedShare::<IV, A, IB, MDiv3>::merge_thirds(shares1, shares2, shares3);
2429 assert_eq!(merged, shares);
2430 }
2431
2432 pub(super) fn test_into_iter<IV, A, IB, M>(n_parties: usize)
2433 where
2434 IV: BatchedShareItem<A, IB>,
2435 A: ShareKey,
2436 IB: BatchedShareMacItem<IV, A>,
2437 M: Positive,
2438 {
2439 let mut rng = test_rng();
2440 let m = M::to_usize();
2441 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2442 let mut iter = shares.clone().into_iter();
2443 assert_eq!(iter.len(), m);
2444 for i in 0..m {
2445 assert_eq!(iter.len(), m - i);
2446 let share = iter.next().unwrap();
2447 assert_eq!(share.value, shares.get_value()[i]);
2448 for j in 0..n_parties - 1 {
2449 assert_eq!(share.macs[j], shares.macs[j][i]);
2450 assert_eq!(share.keys[j].alpha, shares.keys[j].alpha);
2451 assert_eq!(share.keys[j].beta, shares.keys[j].beta[i]);
2452 }
2453 }
2454 }
2455
2456 pub(super) fn test_from_iterator<IV, A, IB, M>(n_parties: usize)
2457 where
2458 IV: BatchedShareItem<A, IB>,
2459 A: ShareKey,
2460 IB: BatchedShareMacItem<IV, A>,
2461 M: Positive,
2462 {
2463 let mut rng = test_rng();
2464 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2465 let collected: Vec<_> = shares.clone().into_iter().collect();
2466 let from_iterator: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2467 assert_eq!(shares, from_iterator);
2468 }
2469
2470 pub(super) fn test_from_iterator_unequal_sizes<IV, A, IB, M>(n_parties: usize)
2471 where
2472 IV: BatchedShareItem<A, IB>,
2473 A: ShareKey,
2474 IB: BatchedShareMacItem<IV, A>,
2475 M: Positive,
2476 BatchedShare<IV, A, IB, M>: RandomWith<usize>,
2477 {
2478 let mut rng = test_rng();
2479 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2480 let mut collected: Vec<_> = shares.into_iter().collect();
2481 collected.pop();
2482 let _: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2483 }
2484
2485 pub(super) fn test_chunks<IV, A, IB, M, CS>(n_parties: usize)
2486 where
2487 IV: BatchedShareItem<A, IB>,
2488 A: ShareKey,
2489 IB: BatchedShareMacItem<IV, A>,
2490 M: Positive + typenum::PartialDiv<CS>,
2491 CS: Positive,
2492 BatchedShare<IV, A, IB, M>: RandomWith<usize> + Clone + Debug,
2493 {
2494 let mut rng = test_rng();
2495 let m = M::to_usize();
2496 let chunk_size = CS::to_usize();
2497 let n_chunks = m / chunk_size;
2498 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2499 let mut chunks_iter = shares.chunks::<CS>();
2500 assert_eq!(chunks_iter.len(), n_chunks);
2501 for i in 0..n_chunks {
2502 assert_eq!(chunks_iter.len(), n_chunks - i);
2503 let chunk = chunks_iter.next().unwrap();
2504 assert_eq!(chunk.value.len(), chunk_size);
2505 for j in 0..chunk_size {
2506 assert_eq!(chunk.value[j], shares.get_value()[i * chunk_size + j]);
2507 }
2508 for (mac_chunk, macs) in izip_eq!(&chunk.macs, &shares.macs) {
2509 for j in 0..chunk_size {
2510 assert_eq!(mac_chunk[j], macs[i * chunk_size + j]);
2511 }
2512 }
2513 for (key_chunk, keys) in izip_eq!(&chunk.keys, &shares.keys) {
2514 assert_eq!(key_chunk.alpha, keys.alpha);
2515 for j in 0..chunk_size {
2516 assert_eq!(key_chunk.beta[j], keys.beta[i * chunk_size + j]);
2517 }
2518 }
2519 }
2520 assert!(chunks_iter.next().is_none());
2521 }
2522
2523 mod field_share_tests {
2526 use crate::algebra::{
2527 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2528 field::SubfieldElement,
2529 };
2530
2531 type V = SubfieldElement<ScalarField<C>>;
2534 type A = ScalarAsExtension<C>; type B = ScalarAsExtension<C>;
2536 type Const = SubfieldElement<ScalarField<C>>;
2537 const N: usize = 3;
2538
2539 #[test]
2540 fn test_open_to() {
2541 super::test_open_to::<V, A, B, Const>(N);
2542 }
2543 #[test]
2544 fn test_random() {
2545 super::test_random::<V, A, B, Const>(N);
2546 }
2547 #[test]
2548 fn test_random_vec_and_reconstruct() {
2549 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2550 }
2551 #[test]
2552 fn test_random_vec_with_global_key_and_reconstruct() {
2553 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2554 }
2555 #[test]
2556 fn test_verify_mac() {
2557 super::test_verify_mac::<V, A, B, Const>(N);
2558 }
2559 #[test]
2560 fn test_add() {
2561 super::test_add::<V, A, B, Const>(N);
2562 }
2563 #[test]
2564 fn test_add_plaintext() {
2565 super::test_add_plaintext::<V, A, B, Const>(N);
2566 }
2567 #[test]
2568 fn test_mul_constant() {
2569 super::test_mul_constant::<V, A, B, Const>(N);
2570 }
2571 #[test]
2572 fn test_sub() {
2573 super::test_sub::<V, A, B, Const>(N);
2574 }
2575 #[test]
2576 fn test_neg() {
2577 super::test_neg::<V, A, B, Const>(N);
2578 }
2579 #[test]
2580 fn test_conditional_select() {
2581 super::test_conditional_select::<V, A, B, Const>(N);
2582 }
2583 #[test]
2584 fn test_ct_eq() {
2585 super::test_ct_eq::<V, A, B, Const>(N);
2586 }
2587 }
2588
2589 mod point_share_tests {
2590 use crate::algebra::{
2591 elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension, ScalarField},
2592 field::SubfieldElement,
2593 };
2594
2595 type V = Point<C>;
2597 type A = ScalarAsExtension<C>;
2598 type B = Point<C>;
2599 type Const = SubfieldElement<ScalarField<C>>; const N: usize = 3;
2601
2602 #[test]
2603 fn test_open_to() {
2604 super::test_open_to::<V, A, B, Const>(N);
2605 }
2606 #[test]
2607 fn test_random() {
2608 super::test_random::<V, A, B, Const>(N);
2609 }
2610 #[test]
2611 fn test_random_vec_and_reconstruct() {
2612 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2613 }
2614 #[test]
2615 fn test_random_vec_with_global_key_and_reconstruct() {
2616 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2617 }
2618 #[test]
2619 fn test_verify_mac() {
2620 super::test_verify_mac::<V, A, B, Const>(N);
2621 }
2622 #[test]
2623 fn test_add() {
2624 super::test_add::<V, A, B, Const>(N);
2625 }
2626 #[test]
2627 fn test_add_plaintext() {
2628 super::test_add_plaintext::<V, A, B, Const>(N);
2629 }
2630 #[test]
2631 fn test_mul_constant() {
2632 super::test_mul_constant::<V, A, B, Const>(N);
2633 }
2634 #[test]
2635 fn test_sub() {
2636 super::test_sub::<V, A, B, Const>(N);
2637 }
2638 #[test]
2639 fn test_neg() {
2640 super::test_neg::<V, A, B, Const>(N);
2641 }
2642 #[test]
2643 fn test_conditional_select() {
2644 super::test_conditional_select::<V, A, B, Const>(N);
2645 }
2646 #[test]
2647 fn test_ct_eq() {
2648 super::test_ct_eq::<V, A, B, Const>(N);
2649 }
2650 }
2651
2652 mod field_shares_tests {
2653 use std::ops::Div;
2654
2655 use typenum::{U12, U2, U3, U4};
2656
2657 use crate::{
2658 algebra::{
2659 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2660 field::SubfieldElement,
2661 },
2662 types::heap_array::{FieldElements, SubfieldElements},
2663 };
2664
2665 type F = ScalarField<C>;
2668 type M = U12;
2669 type IV = SubfieldElement<F>;
2670 type A = ScalarAsExtension<C>; type IB = ScalarAsExtension<C>; type V = SubfieldElements<F, M>;
2673 type B = FieldElements<F, M>;
2674 type Const = V; const N: usize = 3;
2676
2677 #[test]
2680 fn test_open_to() {
2681 super::test_open_to::<V, A, B, Const>(N);
2682 }
2683 #[test]
2684 fn test_random() {
2685 super::test_random::<V, A, B, Const>(N);
2686 }
2687 #[test]
2688 fn test_random_vec_and_reconstruct() {
2689 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2690 }
2691 #[test]
2692 fn test_random_vec_with_global_key_and_reconstruct() {
2693 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2694 }
2695 #[test]
2696 fn test_verify_mac() {
2697 super::test_verify_mac::<V, A, B, Const>(N);
2698 }
2699 #[test]
2700 fn test_add() {
2701 super::test_add::<V, A, B, Const>(N);
2702 }
2703 #[test]
2704 fn test_add_plaintext() {
2705 super::test_add_plaintext::<V, A, B, Const>(N);
2706 }
2707 #[test]
2708 fn test_mul_constant() {
2709 super::test_mul_constant::<V, A, B, Const>(N);
2710 }
2711 #[test]
2712 fn test_sub() {
2713 super::test_sub::<V, A, B, Const>(N);
2714 }
2715 #[test]
2716 fn test_neg() {
2717 super::test_neg::<V, A, B, Const>(N);
2718 }
2719 #[test]
2720 fn test_conditional_select() {
2721 super::test_conditional_select::<V, A, B, Const>(N);
2722 }
2723 #[test]
2724 fn test_ct_eq() {
2725 super::test_ct_eq::<V, A, B, Const>(N);
2726 }
2727
2728 type MDiv2 = <U12 as Div<U2>>::Output;
2731 type MDiv3 = <U12 as Div<U3>>::Output;
2732
2733 #[test]
2734 fn test_split_halves() {
2735 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2736 }
2737 #[test]
2738 fn test_split_thirds() {
2739 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2740 }
2741 #[test]
2742 fn test_into_iter() {
2743 super::test_into_iter::<IV, A, IB, M>(N);
2744 }
2745 #[test]
2746 fn test_from_iterator() {
2747 super::test_from_iterator::<IV, A, IB, M>(N);
2748 }
2749 #[test]
2750 #[should_panic]
2751 fn test_from_iterator_unequal_sizes() {
2752 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2753 }
2754 #[test]
2755 fn test_chunks() {
2756 super::test_chunks::<IV, A, IB, M, U4>(N);
2757 }
2758 }
2759
2760 mod point_shares_tests {
2761 use std::ops::Div;
2762
2763 use typenum::{U12, U2, U3, U4};
2764
2765 use crate::{
2766 algebra::elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension},
2767 types::heap_array::{CurvePoints, Scalars},
2768 };
2769
2770 type M = U12;
2773 type IV = Point<C>;
2774 type A = ScalarAsExtension<C>;
2775 type IB = Point<C>;
2776 type V = CurvePoints<C, M>;
2777 type B = CurvePoints<C, M>;
2778 type Const = Scalars<C, M>;
2779 const N: usize = 3;
2780
2781 #[test]
2784 fn test_open_to() {
2785 super::test_open_to::<V, A, B, Const>(N);
2786 }
2787 #[test]
2788 fn test_random() {
2789 super::test_random::<V, A, B, Const>(N);
2790 }
2791 #[test]
2792 fn test_random_vec_and_reconstruct() {
2793 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2794 }
2795 #[test]
2796 fn test_random_vec_with_global_key_and_reconstruct() {
2797 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2798 }
2799 #[test]
2800 fn test_verify_mac() {
2801 super::test_verify_mac::<V, A, B, Const>(N);
2802 }
2803 #[test]
2804 fn test_add() {
2805 super::test_add::<V, A, B, Const>(N);
2806 }
2807 #[test]
2808 fn test_add_plaintext() {
2809 super::test_add_plaintext::<V, A, B, Const>(N);
2810 }
2811 #[test]
2812 fn test_mul_constant() {
2813 super::test_mul_constant::<V, A, B, Const>(N);
2814 }
2815 #[test]
2816 fn test_sub() {
2817 super::test_sub::<V, A, B, Const>(N);
2818 }
2819 #[test]
2820 fn test_neg() {
2821 super::test_neg::<V, A, B, Const>(N);
2822 }
2823 #[test]
2824 fn test_conditional_select() {
2825 super::test_conditional_select::<V, A, B, Const>(N);
2826 }
2827 #[test]
2828 fn test_ct_eq() {
2829 super::test_ct_eq::<V, A, B, Const>(N);
2830 }
2831
2832 type MDiv2 = <U12 as Div<U2>>::Output;
2835 type MDiv3 = <U12 as Div<U3>>::Output;
2836
2837 #[test]
2838 fn test_split_halves() {
2839 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2840 }
2841 #[test]
2842 fn test_split_thirds() {
2843 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2844 }
2845 #[test]
2846 fn test_into_iter() {
2847 super::test_into_iter::<IV, A, IB, M>(N);
2848 }
2849 #[test]
2850 fn test_from_iterator() {
2851 super::test_from_iterator::<IV, A, IB, M>(N);
2852 }
2853 #[test]
2854 #[should_panic]
2855 fn test_from_iterator_unequal_sizes() {
2856 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2857 }
2858 #[test]
2859 fn test_chunks() {
2860 super::test_chunks::<IV, A, IB, M, U4>(N);
2861 }
2862 }
2863}