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: Random + Any, B> PairwiseAuthenticated for PairwiseAuthShare<V, A, B> {
416 type GlobalAuthKey = GlobalKey<A>;
417
418 fn get_global_keys(&self) -> impl ExactSizeIterator<Item = Self::GlobalAuthKey> {
419 self.get_alphas()
420 }
421}
422
423impl<V, A, B> Verifiable for PairwiseAuthShare<V, A, B>
424where
425 V: Clone
426 + PartialEq
427 + Send
428 + Sync
429 + 'static
430 + Serialize
431 + DeserializeOwned
432 + SchemaWrite<Src = V>
433 + for<'de> SchemaRead<'de, Dst = V>,
434 A: Clone,
435 B: Clone
436 + Send
437 + Sync
438 + 'static
439 + Serialize
440 + DeserializeOwned
441 + SchemaWrite<Src = B>
442 + for<'de> SchemaRead<'de, Dst = B>
443 + ConstantTimeEq
444 + SubAssign
445 + for<'b> Add<&'b B, Output = B>,
446 for<'a> V: Add<&'a V, Output = V>,
447 for<'a> V: Mul<&'a A, Output = B>,
448{
449 #[inline]
451 fn verify_from(
452 &self,
453 open_share: PairwiseAuthOpenShare<V, B>,
454 peer: PeerIndex,
455 ) -> Result<(), PrimitiveError> {
456 let key = self
457 .get_key(peer)
458 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.keys.len()))?;
459 if bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(key, open_share)) {
460 Ok(())
461 } else {
462 Err(PrimitiveError::WrongMAC(format!("peer {peer}")).blame(peer))
463 }
464 }
465
466 #[inline]
468 fn verify(&self, open_shares: Vec<PairwiseAuthOpenShare<V, B>>) -> Result<(), PrimitiveError> {
469 enumerate(izip_eq!(open_shares, &self.keys))
470 .map(|(from_peer, (open_share, key))| {
471 if bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(key, open_share)) {
472 Ok(())
473 } else {
474 Err(PrimitiveError::WrongMAC(format!("peer {from_peer}")).blame(from_peer))
475 }
476 })
477 .collect_errors()?;
478 Ok(())
479 }
480}
481
482impl<V, A, B> Reconstructible for PairwiseAuthShare<V, A, B>
487where
488 V: Clone
489 + PartialEq
490 + Send
491 + Sync
492 + 'static
493 + Serialize
494 + DeserializeOwned
495 + SchemaWrite<Src = V>
496 + for<'de> SchemaRead<'de, Dst = V>,
497 A: Clone,
498 B: Clone
499 + Send
500 + Sync
501 + 'static
502 + Serialize
503 + DeserializeOwned
504 + SchemaWrite<Src = B>
505 + for<'de> SchemaRead<'de, Dst = B>
506 + ConstantTimeEq
507 + SubAssign
508 + for<'b> Add<&'b B, Output = B>,
509 for<'a> V: Add<&'a V, Output = V>,
510 for<'a> V: Mul<&'a A, Output = B>,
511{
512 type Opening = PairwiseAuthOpenShare<V, B>;
513 type Value = V;
514
515 fn open_to(&self, peer: PeerIndex) -> Result<PairwiseAuthOpenShare<V, B>, PrimitiveError> {
517 let mac = self
518 .get_mac(peer)
519 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.macs.len()))?
520 .to_owned();
521 Ok(PairwiseAuthOpenShare::new(self.get_value().to_owned(), mac))
522 }
523
524 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = PairwiseAuthOpenShare<V, B>> {
526 self.get_macs()
527 .iter()
528 .map(|mac| PairwiseAuthOpenShare::new(self.get_value().to_owned(), mac.to_owned()))
529 }
530
531 fn reconstruct(&self, openings: Vec<PairwiseAuthOpenShare<V, B>>) -> Result<V, PrimitiveError> {
533 if openings.len() != self.get_keys().len() {
534 return Err(PrimitiveError::InvalidSize(
535 self.get_keys().len(),
536 openings.len(),
537 ));
538 }
539 let reconstruct = enumerate(izip_eq!(openings, &self.keys)).try_fold_all(
540 self.get_value().to_owned(),
541 |mut reconstructed, (from_peer, (open_share, key))| {
542 reconstructed = reconstructed + open_share.get_value();
543 let mac_error = match bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(
544 key,
545 open_share.clone(),
546 )) {
547 true => None,
548 false => {
549 Some(PrimitiveError::WrongMAC(format!("peer {from_peer}")).blame(from_peer))
550 }
551 };
552 (reconstructed, mac_error)
553 },
554 )?;
555 Ok(reconstruct)
556 }
557}
558
559type NParties = usize;
565
566impl<V, A, B> Random for PairwiseAuthShare<V, A, B>
567where
568 V: Random + Clone,
569 A: Random + Clone,
570 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
571 for<'a> V: Mul<&'a A, Output = B>,
572{
573 fn random(_rng: impl CryptoRngCore) -> Self {
574 unimplemented!(
575 "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
576 std::any::type_name::<Self>()
577 )
578 }
579
580 fn random_n<Container: FromIterator<Self>>(
583 mut rng: impl CryptoRngCore,
584 n_parties: usize,
585 ) -> Container {
586 let all_unauth_shares: Vec<_> = V::random_n(&mut rng, n_parties);
587 let all_keys = (0..n_parties)
588 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
589 .collect::<Vec<_>>();
590 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
591 izip_eq!(all_unauth_shares, all_macs, all_keys)
592 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
593 .collect()
594 }
595}
596
597impl<V, A, B> RandomWith<V> for PairwiseAuthShare<V, A, B>
598where
599 V: AdditiveShares,
600 A: Random + Clone,
601 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
602 for<'a> V: Mul<&'a A, Output = B>,
603{
604 fn random_with(_rng: impl CryptoRngCore, _data: V) -> Self {
605 unimplemented!(
606 "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
607 std::any::type_name::<Self>()
608 )
609 }
610
611 fn random_n_with<Container: FromIterator<Self>>(
614 mut rng: impl CryptoRngCore,
615 n_parties: usize,
616 value: V,
617 ) -> Container {
618 let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
619 let all_keys = (0..n_parties)
620 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
621 .collect::<Vec<_>>();
622 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
623 izip_eq!(all_unauth_shares, all_macs, all_keys)
624 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
625 .collect()
626 }
627
628 fn random_n_with_each<Container: FromIterator<Self>>(
631 mut rng: impl CryptoRngCore,
632 unauth_shares: impl IntoExactSizeIterator<Item = V>,
633 ) -> Container {
634 let all_unauth_shares = unauth_shares.into_iter().collect::<Vec<_>>();
635 let n_parties = all_unauth_shares.len();
636 let all_keys = (0..n_parties)
637 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
638 .collect::<Vec<_>>();
639 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
640 izip_eq!(all_unauth_shares, all_macs, all_keys)
641 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
642 .collect()
643 }
644}
645
646impl<V, A, B> RandomWith<NParties> for PairwiseAuthShare<V, A, B>
647where
648 V: Random,
649 A: Random + Clone,
650 B: Random,
651{
652 fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
654 PairwiseAuthShare {
655 value: V::random(&mut rng),
656 macs: B::random_n(&mut rng, n_parties - 1),
657 keys: PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1),
658 }
659 }
660}
661
662impl<V, A, B> RandomWith<(NParties, V)> for PairwiseAuthShare<V, A, B>
663where
664 V: Clone,
665 A: Random + Clone,
666 B: Random,
667{
668 fn random_with(mut rng: impl CryptoRngCore, (n_parties, value): (NParties, V)) -> Self {
670 PairwiseAuthShare {
671 value,
672 macs: B::random_n(&mut rng, n_parties - 1),
673 keys: PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1),
674 }
675 }
676}
677
678impl<V, A, B> RandomWith<Vec<GlobalKey<A>>> for PairwiseAuthShare<V, A, B>
679where
680 V: Random + Clone,
681 A: Random + Clone,
682 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
683 for<'a> V: Mul<&'a A, Output = B>,
684{
685 fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalKey<A>>) -> Self {
687 let value = V::random(&mut rng);
688 let keys: Box<[_]> = PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, alphas);
689 let macs: Box<[B]> = keys
690 .iter()
691 .map(|key| Self::compute_mac(value.clone(), key))
692 .collect();
693 PairwiseAuthShare { value, macs, keys }
694 }
695
696 fn random_n_with_each<Container: FromIterator<Self>>(
699 mut rng: impl CryptoRngCore,
700 all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalKey<A>>>,
701 ) -> Container {
702 let all_alphas = all_alphas.into_iter();
703 let all_unauth_shares: Vec<_> = V::random_n(&mut rng, all_alphas.len());
704 let all_keys = all_alphas
705 .into_iter()
706 .map(|my_alphas| PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas))
707 .collect::<Vec<_>>();
708 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
709 izip_eq!(all_unauth_shares, all_macs, all_keys)
710 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
711 .collect()
712 }
713}
714
715impl<V, A, B> RandomWith<(V, Vec<GlobalKey<A>>)> for PairwiseAuthShare<V, A, B>
716where
717 V: Clone,
718 A: Random + Clone,
719 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
720 for<'a> V: Mul<&'a A, Output = B>,
721{
722 fn random_with(mut rng: impl CryptoRngCore, (value, alphas): (V, Vec<GlobalKey<A>>)) -> Self {
724 let keys: Box<[_]> = PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, alphas);
725 let macs: Box<[B]> = keys
726 .iter()
727 .map(|key| Self::compute_mac(value.clone(), key))
728 .collect();
729 PairwiseAuthShare { value, macs, keys }
730 }
731
732 fn random_n_with_each<Container: FromIterator<Self>>(
735 mut rng: impl CryptoRngCore,
736 unauth_shares_and_alphas: impl IntoExactSizeIterator<Item = (V, Vec<GlobalKey<A>>)>,
737 ) -> Container {
738 let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
739 .into_iter()
740 .map(|(value, my_alphas)| {
741 (
742 value,
743 PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas),
744 )
745 })
746 .unzip();
747 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
748 izip_eq!(all_unauth_shares, all_macs, all_keys)
749 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
750 .collect()
751 }
752}
753
754impl<V, A, B> RandomWith<(V, Vec<Vec<GlobalKey<A>>>)> for PairwiseAuthShare<V, A, B>
755where
756 V: AdditiveShares,
757 A: Random + Clone,
758 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
759 for<'a> V: Mul<&'a A, Output = B>,
760{
761 fn random_with(_rng: impl CryptoRngCore, _: (V, Vec<Vec<GlobalKey<A>>>)) -> Self {
762 unimplemented!(
763 "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
764 )
765 }
766
767 fn random_n_with<Container: FromIterator<Self>>(
769 mut rng: impl CryptoRngCore,
770 n_parties: usize,
771 (secret_value, all_alphas): (V, Vec<Vec<GlobalKey<A>>>),
772 ) -> Container {
773 assert_eq!(
774 all_alphas.len(),
775 n_parties,
776 "Number of alphas must match the number of parties"
777 );
778 let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
779 let all_keys = all_alphas
780 .into_iter()
781 .map(|my_alphas| PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas))
782 .collect::<Vec<_>>();
783 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
784 izip_eq!(all_unauth_shares, all_macs, all_keys)
785 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
786 .collect()
787 }
788}
789
790#[macros::op_variants(owned, borrowed, flipped_commutative)]
797impl<'a, V, A, B> Add<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
798where
799 for<'v> V: Add<&'v V, Output = V>,
800 for<'b> B: Add<&'b B, Output = B>,
801 for<'k> PairwiseAuthKey<A, B>: Add<&'k PairwiseAuthKey<A, B>, Output = PairwiseAuthKey<A, B>>,
802{
803 type Output = PairwiseAuthShare<V, A, B>;
804
805 #[inline]
806 fn add(self, other: &'a PairwiseAuthShare<V, A, B>) -> Self::Output {
807 PairwiseAuthShare {
808 value: self.value + &other.value,
809 macs: izip_eq!(self.macs, &other.macs)
810 .map(|(mac_i, mac_j)| mac_i + mac_j)
811 .collect(),
812 keys: izip_eq!(self.keys, &other.keys)
813 .map(|(key_i, key_j)| key_i + key_j)
814 .collect(),
815 }
816 }
817}
818
819#[macros::op_variants(owned)]
820impl<'a, V, A, B> AddAssign<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
821where
822 for<'v> V: AddAssign<&'v V>,
823 for<'b> B: AddAssign<&'b B>,
824 for<'k> PairwiseAuthKey<A, B>: AddAssign<&'k PairwiseAuthKey<A, B>>,
825{
826 #[inline]
827 fn add_assign(&mut self, other: &'a PairwiseAuthShare<V, A, B>) {
828 self.value += &other.value;
829 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
830 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
831 }
832}
833
834impl<'a, V, A, B> Sum<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
835where
836 PairwiseAuthShare<V, A, B>: Clone + Default + AddAssign<&'a PairwiseAuthShare<V, A, B>>,
837{
838 #[inline]
839 fn sum<I: Iterator<Item = &'a PairwiseAuthShare<V, A, B>>>(mut iter: I) -> Self {
840 let first = iter.next().cloned().unwrap_or_default();
841 iter.fold(first, |mut acc, item| {
842 acc += item;
843 acc
844 })
845 }
846}
847
848impl<V, A, B> Sum for PairwiseAuthShare<V, A, B>
849where
850 for<'v> V: AddAssign<&'v V>,
851 for<'b> B: AddAssign<&'b B>,
852 for<'k> PairwiseAuthKey<A, B>: AddAssign<&'k PairwiseAuthKey<A, B>>,
853 PairwiseAuthShare<V, A, B>: Default,
854{
855 #[inline]
856 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
857 let first = iter.next().unwrap_or_default();
858 iter.fold(first, |mut acc, item| {
859 acc += &item;
860 acc
861 })
862 }
863}
864
865#[macros::op_variants(owned, borrowed, flipped)]
868impl<'a, V, A, B> Sub<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
869where
870 for<'v> V: Sub<&'v V, Output = V>,
871 for<'b> B: Sub<&'b B, Output = B>,
872 for<'k> PairwiseAuthKey<A, B>: Sub<&'k PairwiseAuthKey<A, B>, Output = PairwiseAuthKey<A, B>>,
873{
874 type Output = PairwiseAuthShare<V, A, B>;
875
876 #[inline]
877 fn sub(self, other: &'a PairwiseAuthShare<V, A, B>) -> Self::Output {
878 PairwiseAuthShare {
879 value: self.value - &other.value,
880 macs: izip_eq!(self.macs, &other.macs)
881 .map(|(mac_i, mac_j)| mac_i - mac_j)
882 .collect(),
883 keys: izip_eq!(self.keys, &other.keys)
884 .map(|(key_i, key_j)| key_i - key_j)
885 .collect(),
886 }
887 }
888}
889
890#[macros::op_variants(owned)]
891impl<'a, V, A, B> SubAssign<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
892where
893 for<'v> V: SubAssign<&'v V>,
894 for<'b> B: SubAssign<&'b B>,
895 for<'k> PairwiseAuthKey<A, B>: SubAssign<&'k PairwiseAuthKey<A, B>>,
896{
897 #[inline]
898 fn sub_assign(&mut self, other: &'a PairwiseAuthShare<V, A, B>) {
899 self.value -= &other.value;
900 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
901 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
902 }
903}
904
905#[macros::op_variants(borrowed)]
908impl<'a, V, V2, A, B, B2, Const> Mul<&'a Const> for PairwiseAuthShare<V, A, B>
909where
910 for<'v> V: Mul<&'v Const, Output = V2>,
911 for<'b> B: Mul<&'b Const, Output = B2>,
912{
913 type Output = PairwiseAuthShare<V2, A, B2>;
914 #[inline]
915 fn mul(self, other: &'a Const) -> Self::Output {
916 PairwiseAuthShare {
917 value: self.value * other,
918 macs: self
919 .macs
920 .into_vec()
921 .into_iter()
922 .map(|mac| mac * other)
923 .collect(),
924 keys: self
925 .keys
926 .into_vec()
927 .into_iter()
928 .map(|key| key * other)
929 .collect(),
930 }
931 }
932}
933
934impl<'a, V, A, B, Const> MulAssign<&'a Const> for PairwiseAuthShare<V, A, B>
937where
938 for<'v> V: MulAssign<&'v Const>,
939 for<'b> B: MulAssign<&'b Const>,
940{
941 #[inline]
942 fn mul_assign(&mut self, other: &'a Const) {
943 self.value *= other;
944 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
945 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
946 }
947}
948
949#[macros::op_variants(borrowed)]
952impl<V, A, B> Neg for PairwiseAuthShare<V, A, B>
953where
954 V: Neg<Output = V>,
955 B: Neg<Output = B>,
956 PairwiseAuthKey<A, B>: Neg<Output = PairwiseAuthKey<A, B>>,
957{
958 type Output = PairwiseAuthShare<V, A, B>;
959
960 #[inline]
961 fn neg(self) -> Self::Output {
962 let PairwiseAuthShare { value, macs, keys } = self;
963 PairwiseAuthShare {
964 value: -value,
965 keys: keys.into_vec().into_iter().map(|key| -key).collect(),
966 macs: macs.into_vec().into_iter().map(|mac| -mac).collect(),
967 }
968 }
969}
970
971impl<V, A, B> PlaintextOps for PairwiseAuthShare<V, A, B>
974where
975 PairwiseAuthShare<V, A, B>: Reconstructible<Value = V>,
976 V: Clone + for<'a> AddAssign<&'a V> + for<'a> SubAssign<&'a V>,
977 A: Clone,
978 B: Clone + for<'b> AddAssign<&'b B> + for<'b> SubAssign<&'b B> + ConstantTimeEq,
979 for<'a> V: Mul<&'a A, Output = B>,
980{
981 #[inline]
984 fn add_plaintext(mut self, ptx: &V, is_first_peer: bool) -> Self {
985 if is_first_peer {
986 self.value += ptx;
987 } else {
988 let key0 = self.keys.get_mut(0).expect("Missing key 0");
989 key0.beta -= &(ptx.to_owned() * &key0.alpha);
990 }
991 self
992 }
993
994 #[inline]
997 fn sub_plaintext(mut self, ptx: &V, is_first_peer: bool) -> Self {
998 if is_first_peer {
999 self.value -= ptx;
1000 } else {
1001 let key0 = self.keys.get_mut(0).expect("Missing key 0");
1002 key0.beta += &(ptx.to_owned() * &key0.alpha);
1003 }
1004 self
1005 }
1006}
1007
1008impl<V, A, B> ConstantTimeEq for PairwiseAuthShare<V, A, B>
1013where
1014 V: ConstantTimeEq,
1015 B: ConstantTimeEq,
1016 PairwiseAuthKey<A, B>: ConstantTimeEq,
1017{
1018 #[inline]
1019 fn ct_eq(&self, other: &Self) -> Choice {
1020 self.value.ct_eq(&other.value) & self.macs.ct_eq(&other.macs) & self.keys.ct_eq(&other.keys)
1021 }
1022}
1023
1024impl<V, A, B> ConditionallySelectable for PairwiseAuthShare<V, A, B>
1025where
1026 V: ConditionallySelectable,
1027 B: ConditionallySelectable,
1028 PairwiseAuthKey<A, B>: ConditionallySelectable,
1029{
1030 #[inline]
1031 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
1032 PairwiseAuthShare {
1033 value: V::conditional_select(&a.value, &b.value, choice),
1034 macs: izip_eq!(&a.macs, &b.macs)
1035 .map(|(a_mac, b_mac)| B::conditional_select(a_mac, b_mac, choice))
1036 .collect(),
1037 keys: izip_eq!(&a.keys, &b.keys)
1038 .map(|(a_key, b_key)| {
1039 PairwiseAuthKey::<A, B>::conditional_select(a_key, b_key, choice)
1040 })
1041 .collect(),
1042 }
1043 }
1044}
1045
1046#[derive(Clone, Debug)]
1051pub struct BatchedSharesIterator<VIter: Iterator, MacIter: Iterator, A, BIter: Iterator> {
1052 remaining: usize,
1053 value: VIter,
1054 macs: Vec<MacIter>,
1055 betas: Vec<BIter>,
1056 alphas: Vec<GlobalKey<A>>,
1057}
1058
1059impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator<Item = MacIter::Item>> Iterator
1060 for BatchedSharesIterator<VIter, MacIter, A, BIter>
1061{
1062 type Item = PairwiseAuthShare<VIter::Item, A, MacIter::Item>;
1063
1064 fn next(&mut self) -> Option<Self::Item> {
1065 if self.remaining == 0 {
1066 return None;
1067 }
1068 let value = self.value.next()?;
1069 let macs: Box<[_]> = self
1070 .macs
1071 .iter_mut()
1072 .map(|it| it.next())
1073 .collect::<Option<_>>()?;
1074 let keys: Box<[_]> = izip!(&mut self.betas, &self.alphas)
1075 .map(|(beta_iter, alpha)| {
1076 beta_iter
1077 .next()
1078 .map(|beta| PairwiseAuthKey::new(alpha.clone(), beta))
1079 })
1080 .collect::<Option<_>>()?;
1081 self.remaining -= 1;
1082 Some(PairwiseAuthShare { value, macs, keys })
1083 }
1084
1085 fn size_hint(&self) -> (usize, Option<usize>) {
1086 (self.remaining, Some(self.remaining))
1087 }
1088}
1089
1090impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator<Item = MacIter::Item>>
1091 ExactSizeIterator for BatchedSharesIterator<VIter, MacIter, A, BIter>
1092{
1093 fn len(&self) -> usize {
1094 self.remaining
1095 }
1096}
1097
1098impl<V, A, B> IntoIterator for PairwiseAuthShare<V, A, B>
1103where
1104 V: IntoIterator,
1105 V::IntoIter: ExactSizeIterator,
1106 B: IntoIterator,
1107 A: Clone,
1108{
1109 type Item = PairwiseAuthShare<V::Item, A, B::Item>;
1110 type IntoIter = BatchedSharesIterator<V::IntoIter, B::IntoIter, A, B::IntoIter>;
1111
1112 fn into_iter(self) -> Self::IntoIter {
1113 let PairwiseAuthShare { value, macs, keys } = self;
1114 let value_iter = value.into_iter();
1115 let remaining = value_iter.len();
1116 let macs = macs.into_vec().into_iter().map(|m| m.into_iter()).collect();
1117 let (betas, alphas): (Vec<_>, Vec<_>) = keys
1118 .into_vec()
1119 .into_iter()
1120 .map(|k| (k.beta.into_iter(), k.alpha))
1121 .unzip();
1122 BatchedSharesIterator {
1123 remaining,
1124 value: value_iter,
1125 macs,
1126 betas,
1127 alphas,
1128 }
1129 }
1130}
1131
1132impl<V, A, B> IntoIterator for &PairwiseAuthShare<V, A, B>
1133where
1134 V: Clone + IntoIterator,
1135 V::IntoIter: ExactSizeIterator,
1136 B: Clone + IntoIterator,
1137 A: Clone,
1138{
1139 type Item = PairwiseAuthShare<V::Item, A, B::Item>;
1140 type IntoIter = BatchedSharesIterator<V::IntoIter, B::IntoIter, A, B::IntoIter>;
1141
1142 fn into_iter(self) -> Self::IntoIter {
1143 let value_iter = self.value.clone().into_iter();
1144 let remaining = value_iter.len();
1145 let macs = self.macs.iter().map(|m| m.clone().into_iter()).collect();
1146 let (betas, alphas): (Vec<_>, Vec<_>) = self
1147 .keys
1148 .iter()
1149 .map(|k| (k.beta.clone().into_iter(), k.alpha.clone()))
1150 .unzip();
1151 BatchedSharesIterator {
1152 remaining,
1153 value: value_iter,
1154 macs,
1155 betas,
1156 alphas,
1157 }
1158 }
1159}
1160
1161impl<ItemV, A: Clone, ItemB, V, B> FromIterator<PairwiseAuthShare<ItemV, A, ItemB>>
1166 for PairwiseAuthShare<V, A, B>
1167where
1168 V: FromIterator<ItemV>,
1169 B: FromIterator<ItemB>,
1170{
1171 fn from_iter<T: IntoIterator<Item = PairwiseAuthShare<ItemV, A, ItemB>>>(iter: T) -> Self {
1172 let (values, macs, keys): (Vec<_>, Vec<Vec<_>>, Vec<Vec<_>>) = iter
1173 .into_iter()
1174 .map(|s| (s.value, s.macs.into_vec(), s.keys.into_vec()))
1175 .multiunzip();
1176 let macs: Box<[B]> = transpose(macs)
1177 .into_iter()
1178 .map(|pm| pm.into_iter().collect::<B>())
1179 .collect::<Vec<_>>()
1180 .into();
1181 let keys: Box<[PairwiseAuthKey<A, B>]> = transpose(keys)
1182 .into_iter()
1183 .map(|peer_keys: Vec<PairwiseAuthKey<A, ItemB>>| {
1184 let alpha = peer_keys[0].get_alpha().to_owned();
1185 let betas: B = peer_keys.into_iter().map(|k| k.beta).collect();
1186 PairwiseAuthKey::new(alpha.into(), betas)
1187 })
1188 .collect::<Vec<_>>()
1189 .into();
1190 PairwiseAuthShare {
1191 value: values.into_iter().collect::<V>(),
1192 macs,
1193 keys,
1194 }
1195 }
1196}
1197
1198impl<ItemV, A, ItemB> From<PairwiseAuthShare<ItemV, A, ItemB>>
1203 for BatchedShare<ItemV, A, ItemB, U1>
1204{
1205 fn from(share: PairwiseAuthShare<ItemV, A, ItemB>) -> Self {
1206 PairwiseAuthShare {
1207 value: HeapArray::from(share.value),
1208 macs: share
1209 .macs
1210 .into_vec()
1211 .into_iter()
1212 .map(HeapArray::from)
1213 .collect(),
1214 keys: share
1215 .keys
1216 .into_vec()
1217 .into_iter()
1218 .map(PairwiseAuthKey::from)
1219 .collect(),
1220 }
1221 }
1222}
1223
1224impl<ItemV, A: Clone, ItemB, V, B, N: Positive>
1229 From<HeapArray<PairwiseAuthShare<ItemV, A, ItemB>, N>> for PairwiseAuthShare<V, A, B>
1230where
1231 V: FromIterator<ItemV>,
1232 B: FromIterator<ItemB>,
1233{
1234 fn from(shares: HeapArray<PairwiseAuthShare<ItemV, A, ItemB>, N>) -> Self {
1235 shares.into_iter().collect()
1236 }
1237}
1238
1239impl<ItemV: Send, A: Clone + Send, ItemB: Send, M: Positive> IntoParallelIterator
1244 for BatchedShare<ItemV, A, ItemB, M>
1245where
1246 PairwiseAuthShare<ItemV, A, ItemB>: Send,
1247{
1248 type Item = PairwiseAuthShare<ItemV, A, ItemB>;
1249 type Iter = rayon::vec::IntoIter<Self::Item>;
1250
1251 fn into_par_iter(self) -> Self::Iter {
1252 let PairwiseAuthShare { value, macs, keys } = self;
1256 let value_iter = Vec::from(value).into_iter();
1257 let remaining = value_iter.len();
1258 let mac_iters: Vec<_> = macs
1259 .into_vec()
1260 .into_iter()
1261 .map(|m| Vec::from(m).into_iter())
1262 .collect();
1263 let (betas, alphas): (Vec<_>, Vec<_>) = keys
1264 .into_vec()
1265 .into_iter()
1266 .map(|k| (Vec::from(k.beta).into_iter(), k.alpha))
1267 .unzip();
1268 BatchedSharesIterator {
1269 remaining,
1270 value: value_iter,
1271 macs: mac_iters,
1272 betas,
1273 alphas,
1274 }
1275 .collect::<Vec<_>>()
1276 .into_par_iter()
1277 }
1278}
1279
1280impl<V, A, B, M: Positive> Batched for BatchedShare<V, A, B, M>
1285where
1286 V: Send,
1287 B: Send,
1288 A: Clone + Send + Sync,
1289{
1290 type Size = M;
1291}
1292
1293impl<V: Copy, A: Clone, B: Copy, M: Positive> BatchedShare<V, A, B, M> {
1294 #[allow(clippy::type_complexity)]
1295 pub fn split<M1, M2>(self) -> (BatchedShare<V, A, B, M1>, BatchedShare<V, A, B, M2>)
1298 where
1299 M1: Positive,
1300 M2: Positive + Add<M1, Output = M>,
1301 {
1302 let PairwiseAuthShare { value, macs, keys } = self;
1303 let (v1, v2) = value.split::<M1, M2>();
1304 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1305 .into_vec()
1306 .into_iter()
1307 .map(|m| m.split::<M1, M2>())
1308 .unzip();
1309 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1310 .into_vec()
1311 .into_iter()
1312 .map(|k| k.split::<M1, M2>())
1313 .unzip();
1314 (
1315 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1316 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1317 )
1318 }
1319
1320 #[allow(clippy::type_complexity)]
1321 pub fn split_last_pos<M1>(self) -> (BatchedShare<V, A, B, M1>, PairwiseAuthShare<V, A, B>)
1322 where
1323 M1: Positive + Add<typenum::B1, Output = M>,
1324 {
1325 let PairwiseAuthShare { value, macs, keys } = self;
1326 let (v1, v2) = value.split_last_pos();
1327 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1328 .into_vec()
1329 .into_iter()
1330 .map(|m| m.split_last_pos())
1331 .unzip();
1332 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1333 .into_vec()
1334 .into_iter()
1335 .map(|k| k.split_last_pos())
1336 .unzip();
1337 (
1338 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1339 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1340 )
1341 }
1342
1343 #[allow(clippy::type_complexity)]
1344 pub fn split_halves<MDiv2>(self) -> (BatchedShare<V, A, B, MDiv2>, BatchedShare<V, A, B, MDiv2>)
1347 where
1348 MDiv2: Positive + Mul<U2, Output = M>,
1349 {
1350 let PairwiseAuthShare { value, macs, keys } = self;
1351 let (v1, v2) = value.split_halves::<MDiv2>();
1352 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1353 .into_vec()
1354 .into_iter()
1355 .map(|m| m.split_halves::<MDiv2>())
1356 .unzip();
1357 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1358 .into_vec()
1359 .into_iter()
1360 .map(|k| k.split_halves::<MDiv2>())
1361 .unzip();
1362 (
1363 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1364 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1365 )
1366 }
1367
1368 #[allow(clippy::type_complexity)]
1369 pub fn merge_halves(this: Self, other: Self) -> BatchedShare<V, A, B, Prod<M, U2>>
1371 where
1372 M: Mul<U2, Output: Positive>,
1373 A: PartialEq,
1374 {
1375 let PairwiseAuthShare {
1376 value: v1,
1377 macs: m1,
1378 keys: k1,
1379 } = this;
1380 let PairwiseAuthShare {
1381 value: v2,
1382 macs: m2,
1383 keys: k2,
1384 } = other;
1385 let value = HeapArray::merge_halves(v1, v2);
1386 let macs: Box<[_]> = izip_eq!(m1, m2)
1387 .map(|(a, b)| HeapArray::merge_halves(a, b))
1388 .collect();
1389 let keys: Box<[_]> = izip_eq!(k1, k2)
1390 .map(|(a, b)| PairwiseAuthKey::merge_halves(a, b))
1391 .collect();
1392 PairwiseAuthShare::try_new(value, macs, keys).unwrap()
1393 }
1394
1395 #[allow(clippy::type_complexity)]
1396 pub fn split_thirds<MDiv3>(
1399 self,
1400 ) -> (
1401 BatchedShare<V, A, B, MDiv3>,
1402 BatchedShare<V, A, B, MDiv3>,
1403 BatchedShare<V, A, B, MDiv3>,
1404 )
1405 where
1406 MDiv3: Positive + Mul<U3, Output = M>,
1407 {
1408 let PairwiseAuthShare { value, macs, keys } = self;
1409 let (v1, v2, v3) = value.split_thirds::<MDiv3>();
1410 let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
1411 .into_vec()
1412 .into_iter()
1413 .map(|m| m.split_thirds::<MDiv3>())
1414 .multiunzip();
1415 let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
1416 .into_vec()
1417 .into_iter()
1418 .map(|k| k.split_thirds::<MDiv3>())
1419 .multiunzip();
1420 (
1421 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1422 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1423 PairwiseAuthShare::try_new(v3, macs3.into(), keys3.into()).unwrap(),
1424 )
1425 }
1426
1427 #[allow(clippy::type_complexity)]
1428 pub fn split_fifths<MDiv5>(
1430 self,
1431 ) -> (
1432 BatchedShare<V, A, B, MDiv5>,
1433 BatchedShare<V, A, B, MDiv5>,
1434 BatchedShare<V, A, B, MDiv5>,
1435 BatchedShare<V, A, B, MDiv5>,
1436 BatchedShare<V, A, B, MDiv5>,
1437 )
1438 where
1439 MDiv5: Positive + Mul<U5, Output = M>,
1440 {
1441 fn split_array<T: Copy, M: Positive, MDiv5: Positive + Mul<U5, Output = M>>(
1442 arr: HeapArray<T, M>,
1443 ) -> (
1444 HeapArray<T, MDiv5>,
1445 HeapArray<T, MDiv5>,
1446 HeapArray<T, MDiv5>,
1447 HeapArray<T, MDiv5>,
1448 HeapArray<T, MDiv5>,
1449 ) {
1450 let n = MDiv5::USIZE;
1451 let (a, rest) = arr.split_at(n);
1452 let (b, rest) = rest.split_at(n);
1453 let (c, rest) = rest.split_at(n);
1454 let (d, e) = rest.split_at(n);
1455 (
1456 HeapArray::<T, MDiv5>::try_from(a.to_vec()).unwrap(),
1457 HeapArray::<T, MDiv5>::try_from(b.to_vec()).unwrap(),
1458 HeapArray::<T, MDiv5>::try_from(c.to_vec()).unwrap(),
1459 HeapArray::<T, MDiv5>::try_from(d.to_vec()).unwrap(),
1460 HeapArray::<T, MDiv5>::try_from(e.to_vec()).unwrap(),
1461 )
1462 }
1463
1464 let PairwiseAuthShare { value, macs, keys } = self;
1465 let (v1, v2, v3, v4, v5) = split_array::<V, M, MDiv5>(value);
1466 let (macs1, macs2, macs3, macs4, macs5): (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = macs
1467 .into_vec()
1468 .into_iter()
1469 .map(split_array::<B, M, MDiv5>)
1470 .multiunzip();
1471 let (keys1, keys2, keys3, keys4, keys5): (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = keys
1472 .into_vec()
1473 .into_iter()
1474 .map(|k| {
1475 let PairwiseAuthKey { alpha, beta } = k;
1476 let (b1, b2, b3, b4, b5) = split_array::<B, M, MDiv5>(beta);
1477 (
1478 PairwiseAuthKey::new(alpha.clone(), b1),
1479 PairwiseAuthKey::new(alpha.clone(), b2),
1480 PairwiseAuthKey::new(alpha.clone(), b3),
1481 PairwiseAuthKey::new(alpha.clone(), b4),
1482 PairwiseAuthKey::new(alpha, b5),
1483 )
1484 })
1485 .multiunzip();
1486 (
1487 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1488 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1489 PairwiseAuthShare::try_new(v3, macs3.into(), keys3.into()).unwrap(),
1490 PairwiseAuthShare::try_new(v4, macs4.into(), keys4.into()).unwrap(),
1491 PairwiseAuthShare::try_new(v5, macs5.into(), keys5.into()).unwrap(),
1492 )
1493 }
1494
1495 #[allow(clippy::type_complexity)]
1496 pub fn merge_thirds(
1498 first: Self,
1499 second: Self,
1500 third: Self,
1501 ) -> BatchedShare<V, A, B, Prod<M, U3>>
1502 where
1503 M: Mul<U3, Output: Positive>,
1504 A: PartialEq,
1505 {
1506 let PairwiseAuthShare {
1507 value: v1,
1508 macs: m1,
1509 keys: k1,
1510 } = first;
1511 let PairwiseAuthShare {
1512 value: v2,
1513 macs: m2,
1514 keys: k2,
1515 } = second;
1516 let PairwiseAuthShare {
1517 value: v3,
1518 macs: m3,
1519 keys: k3,
1520 } = third;
1521 let value = HeapArray::merge_thirds(v1, v2, v3);
1522 let macs: Box<[_]> = izip_eq!(m1, m2, m3)
1523 .map(|(a, b, c)| HeapArray::merge_thirds(a, b, c))
1524 .collect();
1525 let keys: Box<[_]> = izip_eq!(k1, k2, k3)
1526 .map(|(a, b, c)| PairwiseAuthKey::merge_thirds(a, b, c))
1527 .collect();
1528 PairwiseAuthShare::try_new(value, macs, keys).unwrap()
1529 }
1530
1531 #[allow(clippy::type_complexity)]
1532 pub fn chunks<CS: Positive>(
1534 &self,
1535 ) -> BatchedSharesChunks<
1536 <HeapArray<V, M> as IntoIterator>::IntoIter,
1537 <HeapArray<B, M> as IntoIterator>::IntoIter,
1538 A,
1539 <HeapArray<B, M> as IntoIterator>::IntoIter,
1540 CS,
1541 >
1542 where
1543 M: PartialDiv<CS>,
1544 {
1545 BatchedSharesChunks {
1546 inner: self.into_iter(),
1547 remaining_chunks: M::USIZE / CS::USIZE,
1548 _ds: PhantomData,
1549 }
1550 }
1551
1552 pub fn swap(&mut self, i: usize, j: usize) {
1555 self.value.swap(i, j);
1556 for mac in self.macs.iter_mut() {
1557 mac.swap(i, j);
1558 }
1559 for key in self.keys.iter_mut() {
1560 key.beta.swap(i, j);
1561 }
1562 }
1563}
1564
1565pub struct BatchedSharesChunks<VIter: Iterator, MacIter: Iterator, A, BIter: Iterator, DS: Positive>
1571{
1572 inner: BatchedSharesIterator<VIter, MacIter, A, BIter>,
1573 remaining_chunks: usize,
1574 _ds: PhantomData<DS>,
1575}
1576
1577impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator, DS: Positive>
1578 BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1579{
1580 pub fn len(&self) -> usize {
1581 self.remaining_chunks
1582 }
1583
1584 pub fn is_empty(&self) -> bool {
1585 self.remaining_chunks == 0
1586 }
1587}
1588
1589impl<
1590 VIter: Iterator,
1591 MacIter: Iterator,
1592 A: Clone,
1593 BIter: Iterator<Item = MacIter::Item>,
1594 DS: Positive,
1595 > Iterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1596where
1597 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1598 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1599{
1600 type Item = BatchedShare<VIter::Item, A, MacIter::Item, DS>;
1601
1602 fn next(&mut self) -> Option<Self::Item> {
1603 if self.remaining_chunks == 0 {
1604 return None;
1605 }
1606 let chunk: Vec<_> = self.inner.by_ref().take(DS::to_usize()).collect();
1607 if chunk.is_empty() {
1608 return None;
1609 }
1610 self.remaining_chunks -= 1;
1611 Some(chunk.into_iter().collect())
1612 }
1613
1614 fn size_hint(&self) -> (usize, Option<usize>) {
1615 (self.remaining_chunks, Some(self.remaining_chunks))
1616 }
1617}
1618
1619impl<
1620 VIter: Iterator,
1621 MacIter: Iterator,
1622 A: Clone,
1623 BIter: Iterator<Item = MacIter::Item>,
1624 DS: Positive,
1625 > ExactSizeIterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1626where
1627 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1628 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1629{
1630 fn len(&self) -> usize {
1631 self.remaining_chunks
1632 }
1633}
1634
1635impl<V, A, B, N: Positive> Reconstructible for HeapArray<PairwiseAuthShare<V, A, B>, N>
1642where
1643 PairwiseAuthShare<V, A, B>: Reconstructible,
1644 <PairwiseAuthShare<V, A, B> as Reconstructible>::Opening: Clone,
1645{
1646 type Opening = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening, N>;
1647 type Value = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Value, N>;
1648
1649 fn open_to(&self, for_peer: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
1650 self.into_iter()
1651 .map(|s| s.open_to(for_peer))
1652 .collect::<Result<_, _>>()
1653 }
1654
1655 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
1656 let per_share: Vec<Vec<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening>> = self
1657 .into_iter()
1658 .map(|s| s.open_to_all_others().collect())
1659 .collect();
1660 transpose(per_share)
1661 .into_iter()
1662 .map(|col| col.try_into().expect("size mismatch in open_to_all_others"))
1663 }
1664
1665 fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
1666 self.iter()
1667 .enumerate()
1668 .map(|(i, share)| {
1669 let my_openings: Vec<_> = openings
1670 .iter()
1671 .map(|o| o.get(i).cloned())
1672 .collect::<Option<_>>()
1673 .ok_or_else(|| {
1674 PrimitiveError::InvalidParameters(
1675 "Opening is missing for some share.".to_string(),
1676 )
1677 })?;
1678 share.reconstruct(my_openings)
1679 })
1680 .collect::<Result<_, _>>()
1681 }
1682}
1683
1684impl<C: Curve> From<ScalarShare<C>> for PointShare<C> {
1687 #[inline]
1688 fn from(scalar_share: ScalarShare<C>) -> Self {
1689 scalar_share * &Point::<C>::generator()
1690 }
1691}
1692
1693impl<C: Curve, M: Positive> From<ScalarShares<C, M>> for PointShares<C, M> {
1694 #[inline]
1695 fn from(scalar_shares: ScalarShares<C, M>) -> Self {
1696 scalar_shares * &Point::<C>::generator()
1697 }
1698}
1699
1700impl<F: FieldExtension> From<FieldShare<F>> for FieldExtShare<F> {
1701 fn from(value: FieldShare<F>) -> Self {
1702 let PairwiseAuthShare { value, macs, keys } = value;
1703 let value = FieldElement(F::from_subfield_element(value.0));
1704 Self { value, macs, keys }
1705 }
1706}
1707
1708#[cfg(test)]
1709mod tests {
1710 use std::{fmt::Debug, ops::Div};
1711
1712 use typenum::{U2, U3};
1713
1714 use super::*;
1715 use crate::{random::test_rng, sharing::Verifiable};
1716
1717 #[test]
1719 fn test_indexed_sum_matches_reference() {
1720 use crate::algebra::field::mersenne::Mersenne107;
1721 const N_PARTIES: usize = 3;
1722 let mut rng = test_rng();
1723 let alphas: Vec<GlobalKey<FieldElement<Mersenne107>>> =
1724 Random::random_n(&mut rng, N_PARTIES - 1);
1725 let singles: Vec<FieldShare<Mersenne107>> =
1726 FieldShare::<Mersenne107>::random_n_with(&mut rng, 8, alphas);
1727 let fs: FieldShares<Mersenne107, typenum::U8> = singles.iter().cloned().collect();
1728 let mask = [true, false, true, true, false, false, true, false];
1729 let indices = [0usize, 2, 3, 6];
1730
1731 let expected = izip_eq!(&singles, &mask)
1732 .filter_map(|(s, &m)| m.then_some(s.clone()))
1733 .reduce(|a, b| a + &b);
1734 assert_eq!(fs.indexed_sum(&indices), expected);
1735
1736 assert!(fs.indexed_sum(&[]).is_none());
1738 }
1739
1740 #[test]
1743 fn test_add_plaintext_scalar_matches_reference() {
1744 use crate::{algebra::field::mersenne::Mersenne107, sharing::PlaintextOps};
1745 let mut rng = test_rng();
1746 let fs = FieldShares::<Mersenne107, typenum::U8>::random_with(&mut rng, 3);
1747 let scalar = SubfieldElement::<Mersenne107>::from(7u32);
1748 let broadcast: SubfieldElements<Mersenne107, typenum::U8> =
1749 std::iter::repeat_n(scalar, 8).collect();
1750
1751 for is_first_peer in [true, false] {
1752 assert_eq!(
1753 PlaintextOps::<SubfieldElement<Mersenne107>>::add_plaintext(
1754 fs.clone(),
1755 &scalar,
1756 is_first_peer,
1757 ),
1758 fs.clone().add_plaintext(&broadcast, is_first_peer),
1759 );
1760 assert_eq!(
1761 PlaintextOps::<SubfieldElement<Mersenne107>>::sub_plaintext(
1762 fs.clone(),
1763 &scalar,
1764 is_first_peer,
1765 ),
1766 fs.clone().sub_plaintext(&broadcast, is_first_peer),
1767 );
1768 }
1769 }
1770
1771 pub(super) trait ShareValue<A, B, Const>:
1777 Clone
1778 + PartialEq
1779 + Debug
1780 + Random
1781 + AdditiveShares
1782 + ConstantTimeEq
1783 + ConditionallySelectable
1784 + Neg<Output = Self>
1785 + for<'a> Sub<&'a Self, Output = Self>
1786 + for<'a> AddAssign<&'a Self>
1787 + for<'a> Mul<&'a A, Output = B>
1788 + for<'a> Mul<&'a Const, Output = Self>
1789 + for<'a> MulAssign<&'a Const>
1790 + Send
1791 + Sync
1792 + 'static
1793 + Serialize
1794 + DeserializeOwned
1795 + SchemaWrite<Src = Self>
1796 + for<'de> SchemaRead<'de, Dst = Self>
1797 {
1798 }
1799
1800 impl<V, A, B, Const> ShareValue<A, B, Const> for V where
1801 V: Clone
1802 + PartialEq
1803 + Debug
1804 + Random
1805 + AdditiveShares
1806 + ConstantTimeEq
1807 + ConditionallySelectable
1808 + Neg<Output = V>
1809 + for<'a> Sub<&'a V, Output = V>
1810 + for<'a> AddAssign<&'a V>
1811 + for<'a> Mul<&'a A, Output = B>
1812 + for<'a> Mul<&'a Const, Output = V>
1813 + for<'a> MulAssign<&'a Const>
1814 + Send
1815 + Sync
1816 + 'static
1817 + Serialize
1818 + DeserializeOwned
1819 + SchemaWrite<Src = V>
1820 + for<'de> SchemaRead<'de, Dst = V>
1821 {
1822 }
1823
1824 pub(super) trait ShareKey:
1828 Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1829 {
1830 }
1831
1832 impl<A> ShareKey for A where
1833 A: Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1834 {
1835 }
1836
1837 pub(super) trait ShareMac<V, A, Const>:
1841 Clone
1842 + PartialEq
1843 + Debug
1844 + Random
1845 + ConstantTimeEq
1846 + ConditionallySelectable
1847 + SubAssign
1848 + Neg<Output = Self>
1849 + for<'b> Add<&'b Self, Output = Self>
1850 + for<'b> AddAssign<&'b Self>
1851 + for<'b> Sub<&'b Self, Output = Self>
1852 + for<'b> SubAssign<&'b Self>
1853 + for<'c> Mul<&'c Const, Output = Self>
1854 + for<'c> MulAssign<&'c Const>
1855 + Send
1856 + Sync
1857 + 'static
1858 + Serialize
1859 + DeserializeOwned
1860 + SchemaWrite<Src = Self>
1861 + for<'de> SchemaRead<'de, Dst = Self>
1862 {
1863 }
1864
1865 impl<B, V, A, Const> ShareMac<V, A, Const> for B where
1866 B: Clone
1867 + PartialEq
1868 + Debug
1869 + Random
1870 + ConstantTimeEq
1871 + ConditionallySelectable
1872 + SubAssign
1873 + Neg<Output = B>
1874 + for<'b> Add<&'b B, Output = B>
1875 + for<'b> AddAssign<&'b B>
1876 + for<'b> Sub<&'b B, Output = B>
1877 + for<'b> SubAssign<&'b B>
1878 + for<'c> Mul<&'c Const, Output = B>
1879 + for<'c> MulAssign<&'c Const>
1880 + Send
1881 + Sync
1882 + 'static
1883 + Serialize
1884 + DeserializeOwned
1885 + SchemaWrite<Src = B>
1886 + for<'de> SchemaRead<'de, Dst = B>
1887 {
1888 }
1889
1890 pub(super) trait BatchedShareItem<A, IB>:
1896 Copy
1897 + Clone
1898 + PartialEq
1899 + Debug
1900 + Random
1901 + ConstantTimeEq
1902 + ConditionallySelectable
1903 + for<'a> Mul<&'a A, Output = IB>
1904 {
1905 }
1906
1907 impl<IV, A, IB> BatchedShareItem<A, IB> for IV where
1908 IV: Copy
1909 + Clone
1910 + PartialEq
1911 + Debug
1912 + Random
1913 + ConstantTimeEq
1914 + ConditionallySelectable
1915 + for<'a> Mul<&'a A, Output = IB>
1916 {
1917 }
1918
1919 pub(super) trait BatchedShareMacItem<IV, A>:
1923 Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1924 {
1925 }
1926
1927 impl<IB, IV, A> BatchedShareMacItem<IV, A> for IB where
1928 IB: Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1929 {
1930 }
1931
1932 pub(super) fn test_open_to<V, A, B, Const>(n_parties: usize)
1935 where
1936 V: ShareValue<A, B, Const>,
1937 A: ShareKey,
1938 B: ShareMac<V, A, Const>,
1939 Const: Random,
1940 {
1941 let mut rng = test_rng();
1942 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1943 for i in 0..n_parties - 1 {
1944 let open = share.open_to(i).unwrap();
1945 assert_eq!(open.get_value(), &share.value);
1946 assert_eq!(open.get_mac(), &share.macs[i]);
1947 }
1948 }
1949
1950 pub(super) fn test_random<V, A, B, Const>(n_parties: usize)
1951 where
1952 V: ShareValue<A, B, Const>,
1953 A: ShareKey,
1954 B: ShareMac<V, A, Const>,
1955 Const: Random,
1956 {
1957 let mut rng = test_rng();
1958 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1959 assert_eq!(share.get_macs().len(), n_parties - 1);
1960 assert_eq!(share.get_keys().len(), n_parties - 1);
1961 let value = V::random(&mut rng);
1962 let share_with_value =
1963 PairwiseAuthShare::<V, A, B>::random_with(&mut rng, (n_parties, value.clone()));
1964 assert_eq!(share_with_value.get_value(), &value);
1965 assert_eq!(share_with_value.get_macs().len(), n_parties - 1);
1966 assert_eq!(share_with_value.get_keys().len(), n_parties - 1);
1967 }
1968
1969 pub(super) fn test_random_vec_and_reconstruct<V, A, B, Const>(n_parties: usize)
1970 where
1971 V: ShareValue<A, B, Const>,
1972 A: ShareKey,
1973 B: ShareMac<V, A, Const>,
1974 Const: Random,
1975 {
1976 let mut rng = test_rng();
1977 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
1978 assert_eq!(shares.len(), n_parties);
1979 for share in &shares {
1980 assert_eq!(share.get_macs().len(), n_parties - 1);
1981 assert_eq!(share.get_keys().len(), n_parties - 1);
1982 }
1983 let unauth: Vec<_> = shares.iter().map(|s| s.get_value().clone()).collect();
1984 let expected = V::from_additive_shares(&unauth);
1985 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1986 assert_eq!(reconstructed, expected);
1987
1988 let value = V::random(&mut rng);
1989 let shares: Vec<_> =
1990 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, value.clone());
1991 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1992 assert_eq!(reconstructed, value);
1993 }
1994
1995 pub(super) fn test_random_vec_with_global_key_and_reconstruct<V, A, B, Const>(n_parties: usize)
1996 where
1997 V: ShareValue<A, B, Const>,
1998 A: ShareKey,
1999 B: ShareMac<V, A, Const>,
2000 Const: Random,
2001 {
2002 let mut rng = test_rng();
2003 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2005 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2006 .collect();
2007 let shares_from_alphas: Vec<_> =
2008 PairwiseAuthShare::<V, A, B>::random_n_with_each(&mut rng, alphas.clone());
2009 assert_eq!(shares_from_alphas.len(), n_parties);
2010 for (share, my_alphas) in izip_eq!(&shares_from_alphas, &alphas) {
2011 assert_eq!(share.get_macs().len(), n_parties - 1);
2012 assert_eq!(share.get_keys().len(), n_parties - 1);
2013 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
2014 }
2015 let _ = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_alphas).unwrap();
2016
2017 let value = V::random(&mut rng);
2019 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2020 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2021 .collect();
2022 let shares_from_value_and_alphas: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
2023 &mut rng,
2024 n_parties,
2025 (value.clone(), alphas.clone()),
2026 );
2027 assert_eq!(shares_from_value_and_alphas.len(), n_parties);
2028 for (share, my_alphas) in izip_eq!(&shares_from_value_and_alphas, &alphas) {
2029 assert_eq!(share.get_macs().len(), n_parties - 1);
2030 assert_eq!(share.get_keys().len(), n_parties - 1);
2031 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
2032 }
2033 let reconstructed =
2034 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_value_and_alphas).unwrap();
2035 assert_eq!(reconstructed, value);
2036
2037 let value = V::random(&mut rng);
2039 let unauth = value.to_additive_shares(n_parties, &mut rng);
2040 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2041 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2042 .collect();
2043 let shares_from_unauth: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with_each(
2044 &mut rng,
2045 izip_eq!(unauth, alphas.clone()),
2046 );
2047 assert_eq!(shares_from_unauth.len(), n_parties);
2048 for (share, my_alphas) in izip_eq!(&shares_from_unauth, &alphas) {
2049 assert_eq!(share.get_macs().len(), n_parties - 1);
2050 assert_eq!(share.get_keys().len(), n_parties - 1);
2051 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
2052 }
2053 let reconstructed =
2054 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_unauth).unwrap();
2055 assert_eq!(reconstructed, value);
2056 }
2057
2058 pub(super) fn test_verify_mac<V, A, B, Const>(n_parties: usize)
2059 where
2060 V: ShareValue<A, B, Const>,
2061 A: ShareKey,
2062 B: ShareMac<V, A, Const>,
2063 Const: Random,
2064 {
2065 let mut rng = test_rng();
2066 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
2067 for i in 0..shares.len() {
2068 for j in 0..shares.len() {
2069 if i == j {
2070 continue;
2071 }
2072 let open = shares[j].open_to(i - (i > j) as usize).unwrap();
2073 shares[i].verify_from(open, j - (j > i) as usize).unwrap();
2074 }
2075 }
2076 PairwiseAuthShare::<V, A, B>::verify_all(shares).unwrap();
2077 }
2078
2079 pub(super) fn test_add<V, A, B, Const>(n_parties: usize)
2080 where
2081 V: ShareValue<A, B, Const>,
2082 A: ShareKey,
2083 B: ShareMac<V, A, Const>,
2084 Const: Random,
2085 {
2086 let mut rng = test_rng();
2087 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2088 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2089 .collect();
2090 let a = V::random(&mut rng);
2091 let b = V::random(&mut rng);
2092 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
2093 &mut rng,
2094 n_parties,
2095 (a.clone(), alphas.clone()),
2096 );
2097 let shares_b: Vec<_> =
2098 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
2099 let expected = a.clone() + &b;
2100
2101 let sum: Vec<_> = izip_eq!(&shares_a, &shares_b)
2102 .map(|(sa, sb)| sa + sb)
2103 .collect();
2104 assert_eq!(
2105 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2106 expected
2107 );
2108
2109 let sum: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
2110 .map(|(sa, sb)| sa + sb)
2111 .collect();
2112 assert_eq!(
2113 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2114 expected
2115 );
2116
2117 let sum: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
2118 .map(|(sa, sb)| sa + sb)
2119 .collect();
2120 assert_eq!(
2121 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2122 expected
2123 );
2124
2125 let sum: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
2126 .map(|(sa, sb)| sa + sb)
2127 .collect();
2128 assert_eq!(
2129 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
2130 expected
2131 );
2132
2133 let mut shares_a_mut = shares_a.clone();
2134 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa += sb);
2135 assert_eq!(
2136 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2137 expected
2138 );
2139
2140 let mut shares_a_mut = shares_a;
2141 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa += sb);
2142 assert_eq!(
2143 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2144 expected
2145 );
2146 }
2147
2148 pub(super) fn test_add_plaintext<V, A, B, Const>(n_parties: usize)
2149 where
2150 V: ShareValue<A, B, Const>,
2151 A: ShareKey,
2152 B: ShareMac<V, A, Const>,
2153 Const: Random,
2154 {
2155 let mut rng = test_rng();
2156 let a = V::random(&mut rng);
2157 let k = V::random(&mut rng);
2158 let shares_a: Vec<_> =
2159 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2160
2161 let shares_plus_k_ref: Vec<_> = shares_a
2162 .iter()
2163 .enumerate()
2164 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
2165 .collect();
2166 assert_eq!(
2167 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k_ref).unwrap(),
2168 a.clone() + &k,
2169 );
2170
2171 let shares_plus_k: Vec<_> = shares_a
2172 .into_iter()
2173 .enumerate()
2174 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
2175 .collect();
2176 assert_eq!(
2177 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k).unwrap(),
2178 a + &k,
2179 );
2180 }
2181
2182 pub(super) fn test_mul_constant<V, A, B, Const>(n_parties: usize)
2183 where
2184 V: ShareValue<A, B, Const>,
2185 A: ShareKey,
2186 B: ShareMac<V, A, Const>,
2187 Const: Random + PartialEq + Debug,
2188 {
2189 let mut rng = test_rng();
2190 let a = V::random(&mut rng);
2191 let k = Const::random(&mut rng);
2192 let shares_a: Vec<_> =
2193 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2194
2195 let shares_a_times_k: Vec<_> = izip_eq!(shares_a.clone()).map(|sa| sa * &k).collect();
2196 assert_eq!(
2197 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_times_k).unwrap(),
2198 a.clone() * &k,
2199 );
2200
2201 let mut shares_a_mut = shares_a;
2202 izip_eq!(&mut shares_a_mut).for_each(|sa| *sa *= &k);
2203 assert_eq!(
2204 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2205 a * &k,
2206 );
2207 }
2208
2209 pub(super) fn test_sub<V, A, B, Const>(n_parties: usize)
2210 where
2211 V: ShareValue<A, B, Const>,
2212 A: ShareKey,
2213 B: ShareMac<V, A, Const>,
2214 Const: Random,
2215 {
2216 let mut rng = test_rng();
2217 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2218 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2219 .collect();
2220 let a = V::random(&mut rng);
2221 let b = V::random(&mut rng);
2222 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
2223 &mut rng,
2224 n_parties,
2225 (a.clone(), alphas.clone()),
2226 );
2227 let shares_b: Vec<_> =
2228 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
2229 let expected = a.clone() - &b;
2230
2231 let diff: Vec<_> = izip_eq!(&shares_a, &shares_b)
2232 .map(|(sa, sb)| sa - sb)
2233 .collect();
2234 assert_eq!(
2235 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2236 expected
2237 );
2238
2239 let diff: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
2240 .map(|(sa, sb)| sa - sb)
2241 .collect();
2242 assert_eq!(
2243 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2244 expected
2245 );
2246
2247 let diff: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
2248 .map(|(sa, sb)| sa - sb)
2249 .collect();
2250 assert_eq!(
2251 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2252 expected
2253 );
2254
2255 let diff: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
2256 .map(|(sa, sb)| sa - sb)
2257 .collect();
2258 assert_eq!(
2259 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2260 expected
2261 );
2262
2263 let mut shares_a_mut = shares_a.clone();
2264 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa -= sb);
2265 assert_eq!(
2266 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2267 expected
2268 );
2269
2270 let mut shares_a_mut = shares_a;
2271 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa -= sb);
2272 assert_eq!(
2273 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2274 expected
2275 );
2276 }
2277
2278 pub(super) fn test_neg<V, A, B, Const>(n_parties: usize)
2279 where
2280 V: ShareValue<A, B, Const>,
2281 A: ShareKey,
2282 B: ShareMac<V, A, Const>,
2283 Const: Random,
2284 {
2285 let mut rng = test_rng();
2286 let a = V::random(&mut rng);
2287 let shares_a: Vec<_> =
2288 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2289
2290 let neg_ref: Vec<_> = shares_a.iter().map(|sa| -sa).collect();
2291 assert_eq!(
2292 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg_ref).unwrap(),
2293 -a.clone(),
2294 );
2295 let neg: Vec<_> = shares_a.into_iter().map(|sa| -sa).collect();
2296 assert_eq!(
2297 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg).unwrap(),
2298 -a,
2299 );
2300 }
2301
2302 pub(super) fn test_conditional_select<V, A, B, Const>(n_parties: usize)
2303 where
2304 V: ShareValue<A, B, Const>,
2305 A: ShareKey,
2306 B: ShareMac<V, A, Const>,
2307 Const: Random,
2308 {
2309 let mut rng = test_rng();
2310 let shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2311 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2312 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2313 &shares_a,
2314 &shares_b,
2315 Choice::from(0u8),
2316 );
2317 assert_eq!(selected, shares_a);
2318 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2319 &shares_a,
2320 &shares_b,
2321 Choice::from(1u8),
2322 );
2323 assert_eq!(selected, shares_b);
2324 }
2325
2326 pub(super) fn test_ct_eq<V, A, B, Const>(n_parties: usize)
2327 where
2328 V: ShareValue<A, B, Const>,
2329 A: ShareKey,
2330 B: ShareMac<V, A, Const>,
2331 Const: Random,
2332 {
2333 let mut rng = test_rng();
2334 let shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2335 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2336 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
2337 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
2338 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
2339 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
2340 }
2341
2342 pub(super) fn test_split_halves<IV, A, IB, M, MDiv2>(n_parties: usize)
2345 where
2346 IV: BatchedShareItem<A, IB>,
2347 A: ShareKey,
2348 IB: BatchedShareMacItem<IV, A>,
2349 M: Positive + Div<U2, Output = MDiv2>,
2350 MDiv2: Positive + Mul<U2, Output = M>,
2351 {
2352 let mut rng = test_rng();
2353 let m_div2 = MDiv2::to_usize();
2354 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2355 let (shares1, shares2) = shares.clone().split_halves::<MDiv2>();
2356
2357 assert_eq!(shares1.get_value().len(), m_div2);
2358 assert_eq!(shares2.get_value().len(), m_div2);
2359 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div2]);
2360 assert_eq!(shares2.get_value().as_ref(), &shares.get_value()[m_div2..]);
2361
2362 izip_eq!(&shares1.macs, &shares2.macs, &shares.macs).for_each(|(mac1, mac2, mac)| {
2363 assert_eq!(mac1.as_ref(), &mac[..m_div2]);
2364 assert_eq!(mac2.as_ref(), &mac[m_div2..]);
2365 });
2366 izip_eq!(&shares1.keys, &shares2.keys, &shares.keys).for_each(|(key1, key2, key)| {
2367 assert_eq!(key1.alpha, key.alpha);
2368 assert_eq!(key2.alpha, key.alpha);
2369 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div2]);
2370 assert_eq!(key2.beta.as_ref(), &key.beta[m_div2..]);
2371 });
2372
2373 let merged = BatchedShare::<IV, A, IB, MDiv2>::merge_halves(shares1, shares2);
2374 assert_eq!(merged, shares);
2375 }
2376
2377 pub(super) fn test_split_thirds<IV, A, IB, M, MDiv3>(n_parties: usize)
2378 where
2379 IV: BatchedShareItem<A, IB>,
2380 A: ShareKey,
2381 IB: BatchedShareMacItem<IV, A>,
2382 M: Positive,
2383 MDiv3: Positive + Mul<U3, Output = M>,
2384 M: Mul<U3, Output: Positive>,
2385 {
2386 let mut rng = test_rng();
2387 let m_div3 = MDiv3::to_usize();
2388 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2389 let (shares1, shares2, shares3) = shares.clone().split_thirds::<MDiv3>();
2390
2391 assert_eq!(shares1.get_value().len(), m_div3);
2392 assert_eq!(shares2.get_value().len(), m_div3);
2393 assert_eq!(shares3.get_value().len(), m_div3);
2394 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div3]);
2395 assert_eq!(
2396 shares2.get_value().as_ref(),
2397 &shares.get_value()[m_div3..(2 * m_div3)]
2398 );
2399 assert_eq!(
2400 shares3.get_value().as_ref(),
2401 &shares.get_value()[(2 * m_div3)..]
2402 );
2403
2404 izip_eq!(&shares1.macs, &shares2.macs, &shares3.macs, &shares.macs).for_each(
2405 |(mac1, mac2, mac3, mac)| {
2406 assert_eq!(mac1.as_ref(), &mac[..m_div3]);
2407 assert_eq!(mac2.as_ref(), &mac[m_div3..(2 * m_div3)]);
2408 assert_eq!(mac3.as_ref(), &mac[(2 * m_div3)..(3 * m_div3)]);
2409 },
2410 );
2411 izip_eq!(&shares1.keys, &shares2.keys, &shares3.keys, &shares.keys).for_each(
2412 |(key1, key2, key3, key)| {
2413 assert_eq!(key1.alpha, key.alpha);
2414 assert_eq!(key2.alpha, key.alpha);
2415 assert_eq!(key3.alpha, key.alpha);
2416 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div3]);
2417 assert_eq!(key2.beta.as_ref(), &key.beta[m_div3..(2 * m_div3)]);
2418 assert_eq!(key3.beta.as_ref(), &key.beta[(2 * m_div3)..(3 * m_div3)]);
2419 },
2420 );
2421
2422 let merged = BatchedShare::<IV, A, IB, MDiv3>::merge_thirds(shares1, shares2, shares3);
2423 assert_eq!(merged, shares);
2424 }
2425
2426 pub(super) fn test_into_iter<IV, A, IB, M>(n_parties: usize)
2427 where
2428 IV: BatchedShareItem<A, IB>,
2429 A: ShareKey,
2430 IB: BatchedShareMacItem<IV, A>,
2431 M: Positive,
2432 {
2433 let mut rng = test_rng();
2434 let m = M::to_usize();
2435 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2436 let mut iter = shares.clone().into_iter();
2437 assert_eq!(iter.len(), m);
2438 for i in 0..m {
2439 assert_eq!(iter.len(), m - i);
2440 let share = iter.next().unwrap();
2441 assert_eq!(share.value, shares.get_value()[i]);
2442 for j in 0..n_parties - 1 {
2443 assert_eq!(share.macs[j], shares.macs[j][i]);
2444 assert_eq!(share.keys[j].alpha, shares.keys[j].alpha);
2445 assert_eq!(share.keys[j].beta, shares.keys[j].beta[i]);
2446 }
2447 }
2448 }
2449
2450 pub(super) fn test_from_iterator<IV, A, IB, M>(n_parties: usize)
2451 where
2452 IV: BatchedShareItem<A, IB>,
2453 A: ShareKey,
2454 IB: BatchedShareMacItem<IV, A>,
2455 M: Positive,
2456 {
2457 let mut rng = test_rng();
2458 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2459 let collected: Vec<_> = shares.clone().into_iter().collect();
2460 let from_iterator: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2461 assert_eq!(shares, from_iterator);
2462 }
2463
2464 pub(super) fn test_from_iterator_unequal_sizes<IV, A, IB, M>(n_parties: usize)
2465 where
2466 IV: BatchedShareItem<A, IB>,
2467 A: ShareKey,
2468 IB: BatchedShareMacItem<IV, A>,
2469 M: Positive,
2470 BatchedShare<IV, A, IB, M>: RandomWith<usize>,
2471 {
2472 let mut rng = test_rng();
2473 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2474 let mut collected: Vec<_> = shares.into_iter().collect();
2475 collected.pop();
2476 let _: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2477 }
2478
2479 pub(super) fn test_chunks<IV, A, IB, M, CS>(n_parties: usize)
2480 where
2481 IV: BatchedShareItem<A, IB>,
2482 A: ShareKey,
2483 IB: BatchedShareMacItem<IV, A>,
2484 M: Positive + typenum::PartialDiv<CS>,
2485 CS: Positive,
2486 BatchedShare<IV, A, IB, M>: RandomWith<usize> + Clone + Debug,
2487 {
2488 let mut rng = test_rng();
2489 let m = M::to_usize();
2490 let chunk_size = CS::to_usize();
2491 let n_chunks = m / chunk_size;
2492 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2493 let mut chunks_iter = shares.chunks::<CS>();
2494 assert_eq!(chunks_iter.len(), n_chunks);
2495 for i in 0..n_chunks {
2496 assert_eq!(chunks_iter.len(), n_chunks - i);
2497 let chunk = chunks_iter.next().unwrap();
2498 assert_eq!(chunk.value.len(), chunk_size);
2499 for j in 0..chunk_size {
2500 assert_eq!(chunk.value[j], shares.get_value()[i * chunk_size + j]);
2501 }
2502 for (mac_chunk, macs) in izip_eq!(&chunk.macs, &shares.macs) {
2503 for j in 0..chunk_size {
2504 assert_eq!(mac_chunk[j], macs[i * chunk_size + j]);
2505 }
2506 }
2507 for (key_chunk, keys) in izip_eq!(&chunk.keys, &shares.keys) {
2508 assert_eq!(key_chunk.alpha, keys.alpha);
2509 for j in 0..chunk_size {
2510 assert_eq!(key_chunk.beta[j], keys.beta[i * chunk_size + j]);
2511 }
2512 }
2513 }
2514 assert!(chunks_iter.next().is_none());
2515 }
2516
2517 mod field_share_tests {
2520 use crate::algebra::{
2521 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2522 field::SubfieldElement,
2523 };
2524
2525 type V = SubfieldElement<ScalarField<C>>;
2528 type A = ScalarAsExtension<C>; type B = ScalarAsExtension<C>;
2530 type Const = SubfieldElement<ScalarField<C>>;
2531 const N: usize = 3;
2532
2533 #[test]
2534 fn test_open_to() {
2535 super::test_open_to::<V, A, B, Const>(N);
2536 }
2537 #[test]
2538 fn test_random() {
2539 super::test_random::<V, A, B, Const>(N);
2540 }
2541 #[test]
2542 fn test_random_vec_and_reconstruct() {
2543 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2544 }
2545 #[test]
2546 fn test_random_vec_with_global_key_and_reconstruct() {
2547 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2548 }
2549 #[test]
2550 fn test_verify_mac() {
2551 super::test_verify_mac::<V, A, B, Const>(N);
2552 }
2553 #[test]
2554 fn test_add() {
2555 super::test_add::<V, A, B, Const>(N);
2556 }
2557 #[test]
2558 fn test_add_plaintext() {
2559 super::test_add_plaintext::<V, A, B, Const>(N);
2560 }
2561 #[test]
2562 fn test_mul_constant() {
2563 super::test_mul_constant::<V, A, B, Const>(N);
2564 }
2565 #[test]
2566 fn test_sub() {
2567 super::test_sub::<V, A, B, Const>(N);
2568 }
2569 #[test]
2570 fn test_neg() {
2571 super::test_neg::<V, A, B, Const>(N);
2572 }
2573 #[test]
2574 fn test_conditional_select() {
2575 super::test_conditional_select::<V, A, B, Const>(N);
2576 }
2577 #[test]
2578 fn test_ct_eq() {
2579 super::test_ct_eq::<V, A, B, Const>(N);
2580 }
2581 }
2582
2583 mod point_share_tests {
2584 use crate::algebra::{
2585 elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension, ScalarField},
2586 field::SubfieldElement,
2587 };
2588
2589 type V = Point<C>;
2591 type A = ScalarAsExtension<C>;
2592 type B = Point<C>;
2593 type Const = SubfieldElement<ScalarField<C>>; const N: usize = 3;
2595
2596 #[test]
2597 fn test_open_to() {
2598 super::test_open_to::<V, A, B, Const>(N);
2599 }
2600 #[test]
2601 fn test_random() {
2602 super::test_random::<V, A, B, Const>(N);
2603 }
2604 #[test]
2605 fn test_random_vec_and_reconstruct() {
2606 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2607 }
2608 #[test]
2609 fn test_random_vec_with_global_key_and_reconstruct() {
2610 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2611 }
2612 #[test]
2613 fn test_verify_mac() {
2614 super::test_verify_mac::<V, A, B, Const>(N);
2615 }
2616 #[test]
2617 fn test_add() {
2618 super::test_add::<V, A, B, Const>(N);
2619 }
2620 #[test]
2621 fn test_add_plaintext() {
2622 super::test_add_plaintext::<V, A, B, Const>(N);
2623 }
2624 #[test]
2625 fn test_mul_constant() {
2626 super::test_mul_constant::<V, A, B, Const>(N);
2627 }
2628 #[test]
2629 fn test_sub() {
2630 super::test_sub::<V, A, B, Const>(N);
2631 }
2632 #[test]
2633 fn test_neg() {
2634 super::test_neg::<V, A, B, Const>(N);
2635 }
2636 #[test]
2637 fn test_conditional_select() {
2638 super::test_conditional_select::<V, A, B, Const>(N);
2639 }
2640 #[test]
2641 fn test_ct_eq() {
2642 super::test_ct_eq::<V, A, B, Const>(N);
2643 }
2644 }
2645
2646 mod field_shares_tests {
2647 use std::ops::Div;
2648
2649 use typenum::{U12, U2, U3, U4};
2650
2651 use crate::{
2652 algebra::{
2653 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2654 field::SubfieldElement,
2655 },
2656 types::heap_array::{FieldElements, SubfieldElements},
2657 };
2658
2659 type F = ScalarField<C>;
2662 type M = U12;
2663 type IV = SubfieldElement<F>;
2664 type A = ScalarAsExtension<C>; type IB = ScalarAsExtension<C>; type V = SubfieldElements<F, M>;
2667 type B = FieldElements<F, M>;
2668 type Const = V; const N: usize = 3;
2670
2671 #[test]
2674 fn test_open_to() {
2675 super::test_open_to::<V, A, B, Const>(N);
2676 }
2677 #[test]
2678 fn test_random() {
2679 super::test_random::<V, A, B, Const>(N);
2680 }
2681 #[test]
2682 fn test_random_vec_and_reconstruct() {
2683 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2684 }
2685 #[test]
2686 fn test_random_vec_with_global_key_and_reconstruct() {
2687 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2688 }
2689 #[test]
2690 fn test_verify_mac() {
2691 super::test_verify_mac::<V, A, B, Const>(N);
2692 }
2693 #[test]
2694 fn test_add() {
2695 super::test_add::<V, A, B, Const>(N);
2696 }
2697 #[test]
2698 fn test_add_plaintext() {
2699 super::test_add_plaintext::<V, A, B, Const>(N);
2700 }
2701 #[test]
2702 fn test_mul_constant() {
2703 super::test_mul_constant::<V, A, B, Const>(N);
2704 }
2705 #[test]
2706 fn test_sub() {
2707 super::test_sub::<V, A, B, Const>(N);
2708 }
2709 #[test]
2710 fn test_neg() {
2711 super::test_neg::<V, A, B, Const>(N);
2712 }
2713 #[test]
2714 fn test_conditional_select() {
2715 super::test_conditional_select::<V, A, B, Const>(N);
2716 }
2717 #[test]
2718 fn test_ct_eq() {
2719 super::test_ct_eq::<V, A, B, Const>(N);
2720 }
2721
2722 type MDiv2 = <U12 as Div<U2>>::Output;
2725 type MDiv3 = <U12 as Div<U3>>::Output;
2726
2727 #[test]
2728 fn test_split_halves() {
2729 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2730 }
2731 #[test]
2732 fn test_split_thirds() {
2733 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2734 }
2735 #[test]
2736 fn test_into_iter() {
2737 super::test_into_iter::<IV, A, IB, M>(N);
2738 }
2739 #[test]
2740 fn test_from_iterator() {
2741 super::test_from_iterator::<IV, A, IB, M>(N);
2742 }
2743 #[test]
2744 #[should_panic]
2745 fn test_from_iterator_unequal_sizes() {
2746 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2747 }
2748 #[test]
2749 fn test_chunks() {
2750 super::test_chunks::<IV, A, IB, M, U4>(N);
2751 }
2752 }
2753
2754 mod point_shares_tests {
2755 use std::ops::Div;
2756
2757 use typenum::{U12, U2, U3, U4};
2758
2759 use crate::{
2760 algebra::elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension},
2761 types::heap_array::{CurvePoints, Scalars},
2762 };
2763
2764 type M = U12;
2767 type IV = Point<C>;
2768 type A = ScalarAsExtension<C>;
2769 type IB = Point<C>;
2770 type V = CurvePoints<C, M>;
2771 type B = CurvePoints<C, M>;
2772 type Const = Scalars<C, M>;
2773 const N: usize = 3;
2774
2775 #[test]
2778 fn test_open_to() {
2779 super::test_open_to::<V, A, B, Const>(N);
2780 }
2781 #[test]
2782 fn test_random() {
2783 super::test_random::<V, A, B, Const>(N);
2784 }
2785 #[test]
2786 fn test_random_vec_and_reconstruct() {
2787 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2788 }
2789 #[test]
2790 fn test_random_vec_with_global_key_and_reconstruct() {
2791 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2792 }
2793 #[test]
2794 fn test_verify_mac() {
2795 super::test_verify_mac::<V, A, B, Const>(N);
2796 }
2797 #[test]
2798 fn test_add() {
2799 super::test_add::<V, A, B, Const>(N);
2800 }
2801 #[test]
2802 fn test_add_plaintext() {
2803 super::test_add_plaintext::<V, A, B, Const>(N);
2804 }
2805 #[test]
2806 fn test_mul_constant() {
2807 super::test_mul_constant::<V, A, B, Const>(N);
2808 }
2809 #[test]
2810 fn test_sub() {
2811 super::test_sub::<V, A, B, Const>(N);
2812 }
2813 #[test]
2814 fn test_neg() {
2815 super::test_neg::<V, A, B, Const>(N);
2816 }
2817 #[test]
2818 fn test_conditional_select() {
2819 super::test_conditional_select::<V, A, B, Const>(N);
2820 }
2821 #[test]
2822 fn test_ct_eq() {
2823 super::test_ct_eq::<V, A, B, Const>(N);
2824 }
2825
2826 type MDiv2 = <U12 as Div<U2>>::Output;
2829 type MDiv3 = <U12 as Div<U3>>::Output;
2830
2831 #[test]
2832 fn test_split_halves() {
2833 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2834 }
2835 #[test]
2836 fn test_split_thirds() {
2837 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2838 }
2839 #[test]
2840 fn test_into_iter() {
2841 super::test_into_iter::<IV, A, IB, M>(N);
2842 }
2843 #[test]
2844 fn test_from_iterator() {
2845 super::test_from_iterator::<IV, A, IB, M>(N);
2846 }
2847 #[test]
2848 #[should_panic]
2849 fn test_from_iterator_unequal_sizes() {
2850 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2851 }
2852 #[test]
2853 fn test_chunks() {
2854 super::test_chunks::<IV, A, IB, M, U4>(N);
2855 }
2856 }
2857}