1use std::{
2 iter::Sum,
3 marker::PhantomData,
4 mem::MaybeUninit,
5 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
6};
7
8use itertools::{enumerate, izip, Itertools};
9use rayon::prelude::IntoParallelIterator;
10use serde::{de::DeserializeOwned, Deserialize, Serialize};
11use subtle::{Choice, ConstantTimeEq};
12use typenum::{PartialDiv, Prod, U1, U2, U3};
13use wincode::{
14 io::{Reader, Writer},
15 ReadResult,
16 SchemaRead,
17 SchemaWrite,
18 WriteResult,
19};
20
21use crate::{
22 algebra::{
23 elliptic_curve::{BaseField, Curve, Point, ScalarAsExtension, ScalarField},
24 field::{binary::Gf2_128, mersenne::Mersenne107, FieldElement, SubfieldElement},
25 ops::transpose::transpose,
26 },
27 errors::PrimitiveError,
28 izip_eq,
29 random::{CryptoRngCore, Random, RandomWith},
30 sharing::{
31 authenticated::{GlobalKey, PairwiseAuthKey, PairwiseAuthOpenShare},
32 unauthenticated::AdditiveShares,
33 PlaintextOps,
34 Reconstructible,
35 VerifiableWith,
36 },
37 types::{
38 heap_array::{CurvePoints, FieldElements, SubfieldElements},
39 CollectAll,
40 ConditionallySelectable,
41 HeapArray,
42 PeerIndex,
43 Positive,
44 TryFoldAll,
45 },
46 utils::IntoExactSizeIterator,
47};
48
49#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
67#[serde(
68 bound = "V: Serialize + DeserializeOwned, A: Serialize + DeserializeOwned, B: Serialize + DeserializeOwned"
69)]
70#[repr(C)]
71pub struct PairwiseAuthShare<V, A, B> {
72 pub(crate) value: V,
73 pub(crate) macs: Box<[B]>,
74 pub(crate) keys: Box<[PairwiseAuthKey<A, B>]>,
75}
76
77impl<V, A, B> SchemaWrite for PairwiseAuthShare<V, A, B>
78where
79 V: SchemaWrite<Src = V>,
80 B: SchemaWrite<Src = B>,
81 PairwiseAuthKey<A, B>: SchemaWrite<Src = PairwiseAuthKey<A, B>>,
82{
83 type Src = Self;
84
85 fn size_of(src: &Self) -> WriteResult<usize> {
86 Ok(V::size_of(&src.value)?
87 + <Box<[B]> as SchemaWrite>::size_of(&src.macs)?
88 + <Box<[PairwiseAuthKey<A, B>]> as SchemaWrite>::size_of(&src.keys)?)
89 }
90
91 fn write(writer: &mut impl Writer, src: &Self) -> WriteResult<()> {
92 V::write(writer, &src.value)?;
93 <Box<[B]> as SchemaWrite>::write(writer, &src.macs)?;
94 <Box<[PairwiseAuthKey<A, B>]> as SchemaWrite>::write(writer, &src.keys)
95 }
96}
97
98impl<'de, V, A, B> SchemaRead<'de> for PairwiseAuthShare<V, A, B>
99where
100 V: SchemaRead<'de, Dst = V>,
101 B: SchemaRead<'de, Dst = B>,
102 PairwiseAuthKey<A, B>: SchemaRead<'de, Dst = PairwiseAuthKey<A, B>>,
103{
104 type Dst = Self;
105
106 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self>) -> ReadResult<()> {
107 let mut value = MaybeUninit::<V>::uninit();
108 let mut macs = MaybeUninit::<Box<[B]>>::uninit();
109 let mut keys = MaybeUninit::<Box<[PairwiseAuthKey<A, B>]>>::uninit();
110 V::read(reader, &mut value)?;
111 <Box<[B]> as SchemaRead>::read(reader, &mut macs)?;
112 <Box<[PairwiseAuthKey<A, B>]> as SchemaRead>::read(reader, &mut keys)?;
113 let value = unsafe { value.assume_init() };
115 let macs = unsafe { macs.assume_init() };
116 let keys = unsafe { keys.assume_init() };
117 dst.write(PairwiseAuthShare { value, macs, keys });
118 Ok(())
119 }
120}
121
122impl<V, A, B> PairwiseAuthShare<V, A, B> {
123 pub fn try_new(
126 value: V,
127 macs: Box<[B]>,
128 keys: Box<[PairwiseAuthKey<A, B>]>,
129 ) -> Result<Self, PrimitiveError> {
130 if macs.is_empty() {
131 return Err(PrimitiveError::MinimumLength(2, 0));
132 }
133 if macs.len() != keys.len() {
134 return Err(PrimitiveError::InvalidSize(keys.len(), macs.len()));
135 }
136 Ok(Self { value, macs, keys })
137 }
138
139 #[inline]
141 pub fn get_value(&self) -> &V {
142 &self.value
143 }
144
145 #[inline]
147 pub fn get_value_mut(&mut self) -> &mut V {
148 &mut self.value
149 }
150
151 #[inline]
153 pub fn get_macs(&self) -> &[B] {
154 &self.macs
155 }
156
157 #[inline]
159 pub fn get_mac(&self, peer_index: PeerIndex) -> Option<&B> {
160 self.macs.get(peer_index)
161 }
162
163 #[inline]
165 pub fn get_keys(&self) -> &[PairwiseAuthKey<A, B>] {
166 &self.keys
167 }
168
169 #[inline]
171 pub fn get_keys_mut(&mut self) -> &mut [PairwiseAuthKey<A, B>] {
172 &mut self.keys
173 }
174
175 #[inline]
177 pub fn get_key(&self, peer_index: PeerIndex) -> Option<&PairwiseAuthKey<A, B>> {
178 self.keys.get(peer_index)
179 }
180
181 #[inline]
183 pub fn into_value(self) -> V {
184 self.value
185 }
186
187 #[allow(clippy::type_complexity)]
188 #[inline]
190 pub fn into_inner(self) -> (V, Box<[B]>, Box<[PairwiseAuthKey<A, B>]>) {
191 (self.value, self.macs, self.keys)
192 }
193
194 #[inline]
196 pub fn n_parties(&self) -> usize {
197 self.macs.len() + 1
198 }
199
200 #[inline]
202 pub fn n_distant_parties(&self) -> usize {
203 self.macs.len()
204 }
205
206 #[inline]
208 pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalKey<A>> + '_ {
209 self.keys.iter().map(|key| key.alpha())
210 }
211
212 #[inline]
214 pub fn get_betas(&self) -> impl ExactSizeIterator<Item = &B> + '_ {
215 self.keys.iter().map(|key| key.get_beta())
216 }
217}
218
219pub type BatchedShare<V, A, B, M> = PairwiseAuthShare<HeapArray<V, M>, A, HeapArray<B, M>>;
222
223pub type FieldShare<F> = PairwiseAuthShare<SubfieldElement<F>, FieldElement<F>, FieldElement<F>>;
227pub type Mersenne107Share = FieldShare<Mersenne107>;
229
230pub type FieldExtShare<F> = PairwiseAuthShare<FieldElement<F>, FieldElement<F>, FieldElement<F>>;
233
234pub type PointShare<C> = PairwiseAuthShare<Point<C>, ScalarAsExtension<C>, Point<C>>;
240
241pub type FieldShares<F, M> =
249 PairwiseAuthShare<SubfieldElements<F, M>, FieldElement<F>, FieldElements<F, M>>;
250
251pub type PointShares<C, M> =
260 PairwiseAuthShare<CurvePoints<C, M>, ScalarAsExtension<C>, CurvePoints<C, M>>;
261
262pub type ScalarShare<C> = FieldShare<ScalarField<C>>;
266pub type BaseFieldShare<C> = FieldShare<BaseField<C>>;
268pub type BitShare = FieldShare<Gf2_128>;
270
271pub type ScalarShares<C, M> = FieldShares<ScalarField<C>, M>;
274pub type BaseFieldShares<C, M> = FieldShares<BaseField<C>, M>;
276
277impl<V, A, B> PairwiseAuthShare<V, A, B> {
282 pub fn compute_mac(value: V, key: &PairwiseAuthKey<A, B>) -> B
285 where
286 A: Clone,
287 B: for<'b> Add<&'b B, Output = B>,
288 for<'a> V: Mul<&'a A, Output = B>,
289 {
290 value * key.get_alpha() + key.get_beta()
291 }
292
293 pub fn verify_mac(key: &PairwiseAuthKey<A, B>, opening: PairwiseAuthOpenShare<V, B>) -> Choice
296 where
297 A: Clone,
298 B: ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
299 for<'a> V: Mul<&'a A, Output = B>,
300 {
301 let PairwiseAuthOpenShare { value, mac } = opening;
302 let expected_mac = Self::compute_mac(value, key);
303 expected_mac.ct_eq(&mac)
304 }
305
306 pub(crate) fn compute_all_pairwise_macs(
307 all_unauth_shares: &[V],
308 all_keys: &[Box<[PairwiseAuthKey<A, B>]>],
309 ) -> Vec<Box<[B]>>
310 where
311 A: Clone,
312 V: Clone,
313 B: for<'b> Add<&'b B, Output = B>,
314 for<'a> V: Mul<&'a A, Output = B>,
315 {
316 let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
317 enumerate(all_unauth_shares.iter())
318 .map(|(i, my_unauth_share)| {
319 enumerate(all_key_iters.iter_mut())
320 .filter(|(j, _)| *j != i)
321 .map(|(_, keys_iter)| {
322 let next_key = keys_iter.next().unwrap();
323 Self::compute_mac(my_unauth_share.clone(), next_key)
324 })
325 .collect()
326 })
327 .collect()
328 }
329}
330
331impl<V, A, B> VerifiableWith for PairwiseAuthShare<V, A, B>
332where
333 V: Clone
334 + PartialEq
335 + Send
336 + Sync
337 + 'static
338 + Serialize
339 + DeserializeOwned
340 + SchemaWrite<Src = V>
341 + for<'de> SchemaRead<'de, Dst = V>,
342 A: Clone,
343 B: Clone
344 + Send
345 + Sync
346 + 'static
347 + Serialize
348 + DeserializeOwned
349 + SchemaWrite<Src = B>
350 + for<'de> SchemaRead<'de, Dst = B>
351 + ConstantTimeEq
352 + SubAssign
353 + for<'b> Add<&'b B, Output = B>,
354 for<'a> V: Add<&'a V, Output = V>,
355 for<'a> V: Mul<&'a A, Output = B>,
356{
357 type VerificationData = ();
358
359 #[inline]
361 fn verify_from_peer_with(
362 &self,
363 open_share: PairwiseAuthOpenShare<V, B>,
364 peer: PeerIndex,
365 _verification_data: (),
366 ) -> Result<(), PrimitiveError> {
367 let key = self
368 .get_key(peer)
369 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.keys.len()))?;
370 if bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(key, open_share)) {
371 Ok(())
372 } else {
373 Err(PrimitiveError::WrongMAC(format!("peer {peer}")).blame(peer))
374 }
375 }
376
377 #[inline]
379 fn verify_with(
380 &self,
381 open_shares: Vec<PairwiseAuthOpenShare<V, B>>,
382 _verification_data: (),
383 ) -> Result<(), PrimitiveError> {
384 enumerate(izip_eq!(open_shares, &self.keys))
385 .map(|(from_peer, (open_share, key))| {
386 if bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(key, open_share)) {
387 Ok(())
388 } else {
389 Err(PrimitiveError::WrongMAC(format!("peer {from_peer}")).blame(from_peer))
390 }
391 })
392 .collect_errors()?;
393 Ok(())
394 }
395}
396
397impl<V, A, B> Reconstructible for PairwiseAuthShare<V, A, B>
402where
403 V: Clone
404 + PartialEq
405 + Send
406 + Sync
407 + 'static
408 + Serialize
409 + DeserializeOwned
410 + SchemaWrite<Src = V>
411 + for<'de> SchemaRead<'de, Dst = V>,
412 A: Clone,
413 B: Clone
414 + Send
415 + Sync
416 + 'static
417 + Serialize
418 + DeserializeOwned
419 + SchemaWrite<Src = B>
420 + for<'de> SchemaRead<'de, Dst = B>
421 + ConstantTimeEq
422 + SubAssign
423 + for<'b> Add<&'b B, Output = B>,
424 for<'a> V: Add<&'a V, Output = V>,
425 for<'a> V: Mul<&'a A, Output = B>,
426{
427 type Opening = PairwiseAuthOpenShare<V, B>;
428 type Value = V;
429
430 fn open_to(&self, peer: PeerIndex) -> Result<PairwiseAuthOpenShare<V, B>, PrimitiveError> {
432 let mac = self
433 .get_mac(peer)
434 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.macs.len()))?
435 .to_owned();
436 Ok(PairwiseAuthOpenShare::new(self.get_value().to_owned(), mac))
437 }
438
439 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = PairwiseAuthOpenShare<V, B>> {
441 self.get_macs()
442 .iter()
443 .map(|mac| PairwiseAuthOpenShare::new(self.get_value().to_owned(), mac.to_owned()))
444 }
445
446 fn reconstruct(&self, openings: Vec<PairwiseAuthOpenShare<V, B>>) -> Result<V, PrimitiveError> {
448 if openings.len() != self.get_keys().len() {
449 return Err(PrimitiveError::InvalidSize(
450 self.get_keys().len(),
451 openings.len(),
452 ));
453 }
454 let reconstruct = enumerate(izip_eq!(openings, &self.keys)).try_fold_all(
455 self.get_value().to_owned(),
456 |mut reconstructed, (from_peer, (open_share, key))| {
457 reconstructed = reconstructed + open_share.get_value();
458 let mac_error = match bool::from(PairwiseAuthShare::<V, A, B>::verify_mac(
459 key,
460 open_share.clone(),
461 )) {
462 true => None,
463 false => {
464 Some(PrimitiveError::WrongMAC(format!("peer {from_peer}")).blame(from_peer))
465 }
466 };
467 (reconstructed, mac_error)
468 },
469 )?;
470 Ok(reconstruct)
471 }
472}
473
474type NParties = usize;
480
481impl<V, A, B> Random for PairwiseAuthShare<V, A, B>
482where
483 V: Random + Clone,
484 A: Random + Clone,
485 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
486 for<'a> V: Mul<&'a A, Output = B>,
487{
488 fn random(_rng: impl CryptoRngCore) -> Self {
489 unimplemented!(
490 "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
491 std::any::type_name::<Self>()
492 )
493 }
494
495 fn random_n<Container: FromIterator<Self>>(
498 mut rng: impl CryptoRngCore,
499 n_parties: usize,
500 ) -> Container {
501 let all_unauth_shares: Vec<_> = V::random_n(&mut rng, n_parties);
502 let all_keys = (0..n_parties)
503 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
504 .collect::<Vec<_>>();
505 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
506 izip_eq!(all_unauth_shares, all_macs, all_keys)
507 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
508 .collect()
509 }
510}
511
512impl<V, A, B> RandomWith<V> for PairwiseAuthShare<V, A, B>
513where
514 V: AdditiveShares,
515 A: Random + Clone,
516 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
517 for<'a> V: Mul<&'a A, Output = B>,
518{
519 fn random_with(_rng: impl CryptoRngCore, _data: V) -> Self {
520 unimplemented!(
521 "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
522 std::any::type_name::<Self>()
523 )
524 }
525
526 fn random_n_with<Container: FromIterator<Self>>(
529 mut rng: impl CryptoRngCore,
530 n_parties: usize,
531 value: V,
532 ) -> Container {
533 let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
534 let all_keys = (0..n_parties)
535 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
536 .collect::<Vec<_>>();
537 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
538 izip_eq!(all_unauth_shares, all_macs, all_keys)
539 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
540 .collect()
541 }
542
543 fn random_n_with_each<Container: FromIterator<Self>>(
546 mut rng: impl CryptoRngCore,
547 unauth_shares: impl IntoExactSizeIterator<Item = V>,
548 ) -> Container {
549 let all_unauth_shares = unauth_shares.into_iter().collect::<Vec<_>>();
550 let n_parties = all_unauth_shares.len();
551 let all_keys = (0..n_parties)
552 .map(|_| PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1))
553 .collect::<Vec<_>>();
554 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
555 izip_eq!(all_unauth_shares, all_macs, all_keys)
556 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
557 .collect()
558 }
559}
560
561impl<V, A, B> RandomWith<NParties> for PairwiseAuthShare<V, A, B>
562where
563 V: Random,
564 A: Random + Clone,
565 B: Random,
566{
567 fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
569 PairwiseAuthShare {
570 value: V::random(&mut rng),
571 macs: B::random_n(&mut rng, n_parties - 1),
572 keys: PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1),
573 }
574 }
575}
576
577impl<V, A, B> RandomWith<(NParties, V)> for PairwiseAuthShare<V, A, B>
578where
579 V: Clone,
580 A: Random + Clone,
581 B: Random,
582{
583 fn random_with(mut rng: impl CryptoRngCore, (n_parties, value): (NParties, V)) -> Self {
585 PairwiseAuthShare {
586 value,
587 macs: B::random_n(&mut rng, n_parties - 1),
588 keys: PairwiseAuthKey::<A, B>::random_n(&mut rng, n_parties - 1),
589 }
590 }
591}
592
593impl<V, A, B> RandomWith<Vec<GlobalKey<A>>> for PairwiseAuthShare<V, A, B>
594where
595 V: Random + Clone,
596 A: Random + Clone,
597 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
598 for<'a> V: Mul<&'a A, Output = B>,
599{
600 fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalKey<A>>) -> Self {
602 let value = V::random(&mut rng);
603 let keys: Box<[_]> = PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, alphas);
604 let macs: Box<[B]> = keys
605 .iter()
606 .map(|key| Self::compute_mac(value.clone(), key))
607 .collect();
608 PairwiseAuthShare { value, macs, keys }
609 }
610
611 fn random_n_with_each<Container: FromIterator<Self>>(
614 mut rng: impl CryptoRngCore,
615 all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalKey<A>>>,
616 ) -> Container {
617 let all_alphas = all_alphas.into_iter();
618 let all_unauth_shares: Vec<_> = V::random_n(&mut rng, all_alphas.len());
619 let all_keys = all_alphas
620 .into_iter()
621 .map(|my_alphas| PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas))
622 .collect::<Vec<_>>();
623 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
624 izip_eq!(all_unauth_shares, all_macs, all_keys)
625 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
626 .collect()
627 }
628}
629
630impl<V, A, B> RandomWith<(V, Vec<GlobalKey<A>>)> for PairwiseAuthShare<V, A, B>
631where
632 V: Clone,
633 A: Random + Clone,
634 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
635 for<'a> V: Mul<&'a A, Output = B>,
636{
637 fn random_with(mut rng: impl CryptoRngCore, (value, alphas): (V, Vec<GlobalKey<A>>)) -> Self {
639 let keys: Box<[_]> = PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, alphas);
640 let macs: Box<[B]> = keys
641 .iter()
642 .map(|key| Self::compute_mac(value.clone(), key))
643 .collect();
644 PairwiseAuthShare { value, macs, keys }
645 }
646
647 fn random_n_with_each<Container: FromIterator<Self>>(
650 mut rng: impl CryptoRngCore,
651 unauth_shares_and_alphas: impl IntoExactSizeIterator<Item = (V, Vec<GlobalKey<A>>)>,
652 ) -> Container {
653 let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
654 .into_iter()
655 .map(|(value, my_alphas)| {
656 (
657 value,
658 PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas),
659 )
660 })
661 .unzip();
662 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
663 izip_eq!(all_unauth_shares, all_macs, all_keys)
664 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
665 .collect()
666 }
667}
668
669impl<V, A, B> RandomWith<(V, Vec<Vec<GlobalKey<A>>>)> for PairwiseAuthShare<V, A, B>
670where
671 V: AdditiveShares,
672 A: Random + Clone,
673 B: Random + Clone + ConstantTimeEq + SubAssign + for<'b> Add<&'b B, Output = B>,
674 for<'a> V: Mul<&'a A, Output = B>,
675{
676 fn random_with(_rng: impl CryptoRngCore, _: (V, Vec<Vec<GlobalKey<A>>>)) -> Self {
677 unimplemented!(
678 "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
679 )
680 }
681
682 fn random_n_with<Container: FromIterator<Self>>(
684 mut rng: impl CryptoRngCore,
685 n_parties: usize,
686 (secret_value, all_alphas): (V, Vec<Vec<GlobalKey<A>>>),
687 ) -> Container {
688 assert_eq!(
689 all_alphas.len(),
690 n_parties,
691 "Number of alphas must match the number of parties"
692 );
693 let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
694 let all_keys = all_alphas
695 .into_iter()
696 .map(|my_alphas| PairwiseAuthKey::<A, B>::random_n_with_each(&mut rng, my_alphas))
697 .collect::<Vec<_>>();
698 let all_macs = Self::compute_all_pairwise_macs(&all_unauth_shares, &all_keys);
699 izip_eq!(all_unauth_shares, all_macs, all_keys)
700 .map(|(value, macs, keys)| PairwiseAuthShare { value, macs, keys })
701 .collect()
702 }
703}
704
705#[macros::op_variants(owned, borrowed, flipped_commutative)]
712impl<'a, V, A, B> Add<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
713where
714 for<'v> V: Add<&'v V, Output = V>,
715 for<'b> B: Add<&'b B, Output = B>,
716 for<'k> PairwiseAuthKey<A, B>: Add<&'k PairwiseAuthKey<A, B>, Output = PairwiseAuthKey<A, B>>,
717{
718 type Output = PairwiseAuthShare<V, A, B>;
719
720 #[inline]
721 fn add(self, other: &'a PairwiseAuthShare<V, A, B>) -> Self::Output {
722 PairwiseAuthShare {
723 value: self.value + &other.value,
724 macs: izip_eq!(self.macs, &other.macs)
725 .map(|(mac_i, mac_j)| mac_i + mac_j)
726 .collect(),
727 keys: izip_eq!(self.keys, &other.keys)
728 .map(|(key_i, key_j)| key_i + key_j)
729 .collect(),
730 }
731 }
732}
733
734#[macros::op_variants(owned)]
735impl<'a, V, A, B> AddAssign<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
736where
737 for<'v> V: AddAssign<&'v V>,
738 for<'b> B: AddAssign<&'b B>,
739 for<'k> PairwiseAuthKey<A, B>: AddAssign<&'k PairwiseAuthKey<A, B>>,
740{
741 #[inline]
742 fn add_assign(&mut self, other: &'a PairwiseAuthShare<V, A, B>) {
743 self.value += &other.value;
744 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
745 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
746 }
747}
748
749impl<'a, V, A, B> Sum<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
750where
751 PairwiseAuthShare<V, A, B>: Clone + Default + AddAssign<&'a PairwiseAuthShare<V, A, B>>,
752{
753 #[inline]
754 fn sum<I: Iterator<Item = &'a PairwiseAuthShare<V, A, B>>>(mut iter: I) -> Self {
755 let first = iter.next().cloned().unwrap_or_default();
756 iter.fold(first, |mut acc, item| {
757 acc += item;
758 acc
759 })
760 }
761}
762
763impl<V, A, B> Sum for PairwiseAuthShare<V, A, B>
764where
765 for<'v> V: AddAssign<&'v V>,
766 for<'b> B: AddAssign<&'b B>,
767 for<'k> PairwiseAuthKey<A, B>: AddAssign<&'k PairwiseAuthKey<A, B>>,
768 PairwiseAuthShare<V, A, B>: Default,
769{
770 #[inline]
771 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
772 let first = iter.next().unwrap_or_default();
773 iter.fold(first, |mut acc, item| {
774 acc += &item;
775 acc
776 })
777 }
778}
779
780#[macros::op_variants(owned, borrowed, flipped)]
783impl<'a, V, A, B> Sub<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
784where
785 for<'v> V: Sub<&'v V, Output = V>,
786 for<'b> B: Sub<&'b B, Output = B>,
787 for<'k> PairwiseAuthKey<A, B>: Sub<&'k PairwiseAuthKey<A, B>, Output = PairwiseAuthKey<A, B>>,
788{
789 type Output = PairwiseAuthShare<V, A, B>;
790
791 #[inline]
792 fn sub(self, other: &'a PairwiseAuthShare<V, A, B>) -> Self::Output {
793 PairwiseAuthShare {
794 value: self.value - &other.value,
795 macs: izip_eq!(self.macs, &other.macs)
796 .map(|(mac_i, mac_j)| mac_i - mac_j)
797 .collect(),
798 keys: izip_eq!(self.keys, &other.keys)
799 .map(|(key_i, key_j)| key_i - key_j)
800 .collect(),
801 }
802 }
803}
804
805#[macros::op_variants(owned)]
806impl<'a, V, A, B> SubAssign<&'a PairwiseAuthShare<V, A, B>> for PairwiseAuthShare<V, A, B>
807where
808 for<'v> V: SubAssign<&'v V>,
809 for<'b> B: SubAssign<&'b B>,
810 for<'k> PairwiseAuthKey<A, B>: SubAssign<&'k PairwiseAuthKey<A, B>>,
811{
812 #[inline]
813 fn sub_assign(&mut self, other: &'a PairwiseAuthShare<V, A, B>) {
814 self.value -= &other.value;
815 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
816 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
817 }
818}
819
820#[macros::op_variants(borrowed)]
823impl<'a, V, V2, A, B, B2, Const> Mul<&'a Const> for PairwiseAuthShare<V, A, B>
824where
825 for<'v> V: Mul<&'v Const, Output = V2>,
826 for<'b> B: Mul<&'b Const, Output = B2>,
827{
828 type Output = PairwiseAuthShare<V2, A, B2>;
829 #[inline]
830 fn mul(self, other: &'a Const) -> Self::Output {
831 PairwiseAuthShare {
832 value: self.value * other,
833 macs: self
834 .macs
835 .into_vec()
836 .into_iter()
837 .map(|mac| mac * other)
838 .collect(),
839 keys: self
840 .keys
841 .into_vec()
842 .into_iter()
843 .map(|key| key * other)
844 .collect(),
845 }
846 }
847}
848
849impl<'a, V, A, B, Const> MulAssign<&'a Const> for PairwiseAuthShare<V, A, B>
852where
853 for<'v> V: MulAssign<&'v Const>,
854 for<'b> B: MulAssign<&'b Const>,
855{
856 #[inline]
857 fn mul_assign(&mut self, other: &'a Const) {
858 self.value *= other;
859 izip_eq!(&mut self.keys).for_each(|key| *key *= other);
860 izip_eq!(&mut self.macs).for_each(|mac| *mac *= other);
861 }
862}
863
864#[macros::op_variants(borrowed)]
867impl<V, A, B> Neg for PairwiseAuthShare<V, A, B>
868where
869 V: Neg<Output = V>,
870 B: Neg<Output = B>,
871 PairwiseAuthKey<A, B>: Neg<Output = PairwiseAuthKey<A, B>>,
872{
873 type Output = PairwiseAuthShare<V, A, B>;
874
875 #[inline]
876 fn neg(self) -> Self::Output {
877 let PairwiseAuthShare { value, macs, keys } = self;
878 PairwiseAuthShare {
879 value: -value,
880 keys: keys.into_vec().into_iter().map(|key| -key).collect(),
881 macs: macs.into_vec().into_iter().map(|mac| -mac).collect(),
882 }
883 }
884}
885
886impl<V, A, B> PlaintextOps for PairwiseAuthShare<V, A, B>
889where
890 PairwiseAuthShare<V, A, B>: Reconstructible<Value = V>,
891 V: Clone + for<'a> AddAssign<&'a V> + for<'a> SubAssign<&'a V>,
892 A: Clone,
893 B: Clone + for<'b> AddAssign<&'b B> + for<'b> SubAssign<&'b B> + ConstantTimeEq,
894 for<'a> V: Mul<&'a A, Output = B>,
895{
896 #[inline]
899 fn add_plaintext(mut self, ptx: &V, is_first_peer: bool) -> Self {
900 if is_first_peer {
901 self.value += ptx;
902 } else {
903 let key0 = self.keys.get_mut(0).expect("Missing key 0");
904 key0.beta -= &(ptx.to_owned() * &key0.alpha);
905 }
906 self
907 }
908
909 #[inline]
912 fn sub_plaintext(mut self, ptx: &V, is_first_peer: bool) -> Self {
913 if is_first_peer {
914 self.value -= ptx;
915 } else {
916 let key0 = self.keys.get_mut(0).expect("Missing key 0");
917 key0.beta += &(ptx.to_owned() * &key0.alpha);
918 }
919 self
920 }
921}
922
923impl<V, A, B> ConstantTimeEq for PairwiseAuthShare<V, A, B>
928where
929 V: ConstantTimeEq,
930 B: ConstantTimeEq,
931 PairwiseAuthKey<A, B>: ConstantTimeEq,
932{
933 #[inline]
934 fn ct_eq(&self, other: &Self) -> Choice {
935 self.value.ct_eq(&other.value) & self.macs.ct_eq(&other.macs) & self.keys.ct_eq(&other.keys)
936 }
937}
938
939impl<V, A, B> ConditionallySelectable for PairwiseAuthShare<V, A, B>
940where
941 V: ConditionallySelectable,
942 B: ConditionallySelectable,
943 PairwiseAuthKey<A, B>: ConditionallySelectable,
944{
945 #[inline]
946 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
947 PairwiseAuthShare {
948 value: V::conditional_select(&a.value, &b.value, choice),
949 macs: izip_eq!(&a.macs, &b.macs)
950 .map(|(a_mac, b_mac)| B::conditional_select(a_mac, b_mac, choice))
951 .collect(),
952 keys: izip_eq!(&a.keys, &b.keys)
953 .map(|(a_key, b_key)| {
954 PairwiseAuthKey::<A, B>::conditional_select(a_key, b_key, choice)
955 })
956 .collect(),
957 }
958 }
959}
960
961#[derive(Clone, Debug)]
966pub struct BatchedSharesIterator<VIter: Iterator, MacIter: Iterator, A, BIter: Iterator> {
967 remaining: usize,
968 value: VIter,
969 macs: Vec<MacIter>,
970 betas: Vec<BIter>,
971 alphas: Vec<GlobalKey<A>>,
972}
973
974impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator<Item = MacIter::Item>> Iterator
975 for BatchedSharesIterator<VIter, MacIter, A, BIter>
976{
977 type Item = PairwiseAuthShare<VIter::Item, A, MacIter::Item>;
978
979 fn next(&mut self) -> Option<Self::Item> {
980 if self.remaining == 0 {
981 return None;
982 }
983 let value = self.value.next()?;
984 let macs: Box<[_]> = self
985 .macs
986 .iter_mut()
987 .map(|it| it.next())
988 .collect::<Option<_>>()?;
989 let keys: Box<[_]> = izip!(&mut self.betas, &self.alphas)
990 .map(|(beta_iter, alpha)| {
991 beta_iter
992 .next()
993 .map(|beta| PairwiseAuthKey::new(alpha.clone(), beta))
994 })
995 .collect::<Option<_>>()?;
996 self.remaining -= 1;
997 Some(PairwiseAuthShare { value, macs, keys })
998 }
999
1000 fn size_hint(&self) -> (usize, Option<usize>) {
1001 (self.remaining, Some(self.remaining))
1002 }
1003}
1004
1005impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator<Item = MacIter::Item>>
1006 ExactSizeIterator for BatchedSharesIterator<VIter, MacIter, A, BIter>
1007{
1008 fn len(&self) -> usize {
1009 self.remaining
1010 }
1011}
1012
1013impl<V, A, B> IntoIterator for PairwiseAuthShare<V, A, B>
1018where
1019 V: IntoIterator,
1020 V::IntoIter: ExactSizeIterator,
1021 B: IntoIterator,
1022 A: Clone,
1023{
1024 type Item = PairwiseAuthShare<V::Item, A, B::Item>;
1025 type IntoIter = BatchedSharesIterator<V::IntoIter, B::IntoIter, A, B::IntoIter>;
1026
1027 fn into_iter(self) -> Self::IntoIter {
1028 let PairwiseAuthShare { value, macs, keys } = self;
1029 let value_iter = value.into_iter();
1030 let remaining = value_iter.len();
1031 let macs = macs.into_vec().into_iter().map(|m| m.into_iter()).collect();
1032 let (betas, alphas): (Vec<_>, Vec<_>) = keys
1033 .into_vec()
1034 .into_iter()
1035 .map(|k| (k.beta.into_iter(), k.alpha))
1036 .unzip();
1037 BatchedSharesIterator {
1038 remaining,
1039 value: value_iter,
1040 macs,
1041 betas,
1042 alphas,
1043 }
1044 }
1045}
1046
1047impl<V, A, B> IntoIterator for &PairwiseAuthShare<V, A, B>
1048where
1049 V: Clone + IntoIterator,
1050 V::IntoIter: ExactSizeIterator,
1051 B: Clone + IntoIterator,
1052 A: Clone,
1053{
1054 type Item = PairwiseAuthShare<V::Item, A, B::Item>;
1055 type IntoIter = BatchedSharesIterator<V::IntoIter, B::IntoIter, A, B::IntoIter>;
1056
1057 fn into_iter(self) -> Self::IntoIter {
1058 let value_iter = self.value.clone().into_iter();
1059 let remaining = value_iter.len();
1060 let macs = self.macs.iter().map(|m| m.clone().into_iter()).collect();
1061 let (betas, alphas): (Vec<_>, Vec<_>) = self
1062 .keys
1063 .iter()
1064 .map(|k| (k.beta.clone().into_iter(), k.alpha.clone()))
1065 .unzip();
1066 BatchedSharesIterator {
1067 remaining,
1068 value: value_iter,
1069 macs,
1070 betas,
1071 alphas,
1072 }
1073 }
1074}
1075
1076impl<ItemV, A: Clone, ItemB, V, B> FromIterator<PairwiseAuthShare<ItemV, A, ItemB>>
1081 for PairwiseAuthShare<V, A, B>
1082where
1083 V: FromIterator<ItemV>,
1084 B: FromIterator<ItemB>,
1085{
1086 fn from_iter<T: IntoIterator<Item = PairwiseAuthShare<ItemV, A, ItemB>>>(iter: T) -> Self {
1087 let (values, macs, keys): (Vec<_>, Vec<Vec<_>>, Vec<Vec<_>>) = iter
1088 .into_iter()
1089 .map(|s| (s.value, s.macs.into_vec(), s.keys.into_vec()))
1090 .multiunzip();
1091 let macs: Box<[B]> = transpose(macs)
1092 .into_iter()
1093 .map(|pm| pm.into_iter().collect::<B>())
1094 .collect::<Vec<_>>()
1095 .into();
1096 let keys: Box<[PairwiseAuthKey<A, B>]> = transpose(keys)
1097 .into_iter()
1098 .map(|peer_keys: Vec<PairwiseAuthKey<A, ItemB>>| {
1099 let alpha = peer_keys[0].get_alpha().to_owned();
1100 let betas: B = peer_keys.into_iter().map(|k| k.beta).collect();
1101 PairwiseAuthKey::new(alpha.into(), betas)
1102 })
1103 .collect::<Vec<_>>()
1104 .into();
1105 PairwiseAuthShare {
1106 value: values.into_iter().collect::<V>(),
1107 macs,
1108 keys,
1109 }
1110 }
1111}
1112
1113impl<ItemV, A, ItemB> From<PairwiseAuthShare<ItemV, A, ItemB>>
1118 for BatchedShare<ItemV, A, ItemB, U1>
1119{
1120 fn from(share: PairwiseAuthShare<ItemV, A, ItemB>) -> Self {
1121 PairwiseAuthShare {
1122 value: HeapArray::from(share.value),
1123 macs: share
1124 .macs
1125 .into_vec()
1126 .into_iter()
1127 .map(HeapArray::from)
1128 .collect(),
1129 keys: share
1130 .keys
1131 .into_vec()
1132 .into_iter()
1133 .map(PairwiseAuthKey::from)
1134 .collect(),
1135 }
1136 }
1137}
1138
1139impl<ItemV, A: Clone, ItemB, V, B, N: Positive>
1144 From<HeapArray<PairwiseAuthShare<ItemV, A, ItemB>, N>> for PairwiseAuthShare<V, A, B>
1145where
1146 V: FromIterator<ItemV>,
1147 B: FromIterator<ItemB>,
1148{
1149 fn from(shares: HeapArray<PairwiseAuthShare<ItemV, A, ItemB>, N>) -> Self {
1150 shares.into_iter().collect()
1151 }
1152}
1153
1154impl<ItemV: Send, A: Clone + Send, ItemB: Send, M: Positive> IntoParallelIterator
1159 for BatchedShare<ItemV, A, ItemB, M>
1160where
1161 PairwiseAuthShare<ItemV, A, ItemB>: Send,
1162{
1163 type Item = PairwiseAuthShare<ItemV, A, ItemB>;
1164 type Iter = rayon::vec::IntoIter<Self::Item>;
1165
1166 fn into_par_iter(self) -> Self::Iter {
1167 let PairwiseAuthShare { value, macs, keys } = self;
1171 let value_iter = Vec::from(value).into_iter();
1172 let remaining = value_iter.len();
1173 let mac_iters: Vec<_> = macs
1174 .into_vec()
1175 .into_iter()
1176 .map(|m| Vec::from(m).into_iter())
1177 .collect();
1178 let (betas, alphas): (Vec<_>, Vec<_>) = keys
1179 .into_vec()
1180 .into_iter()
1181 .map(|k| (Vec::from(k.beta).into_iter(), k.alpha))
1182 .unzip();
1183 BatchedSharesIterator {
1184 remaining,
1185 value: value_iter,
1186 macs: mac_iters,
1187 betas,
1188 alphas,
1189 }
1190 .collect::<Vec<_>>()
1191 .into_par_iter()
1192 }
1193}
1194
1195impl<V: Copy, A: Clone, B: Copy, M: Positive> BatchedShare<V, A, B, M> {
1200 #[allow(clippy::type_complexity)]
1201 pub fn split<M1, M2>(self) -> (BatchedShare<V, A, B, M1>, BatchedShare<V, A, B, M2>)
1204 where
1205 M1: Positive,
1206 M2: Positive + Add<M1, Output = M>,
1207 {
1208 let PairwiseAuthShare { value, macs, keys } = self;
1209 let (v1, v2) = value.split::<M1, M2>();
1210 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1211 .into_vec()
1212 .into_iter()
1213 .map(|m| m.split::<M1, M2>())
1214 .unzip();
1215 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1216 .into_vec()
1217 .into_iter()
1218 .map(|k| k.split::<M1, M2>())
1219 .unzip();
1220 (
1221 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1222 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1223 )
1224 }
1225
1226 #[allow(clippy::type_complexity)]
1227 pub fn split_halves<MDiv2>(self) -> (BatchedShare<V, A, B, MDiv2>, BatchedShare<V, A, B, MDiv2>)
1230 where
1231 MDiv2: Positive + Mul<U2, Output = M>,
1232 {
1233 let PairwiseAuthShare { value, macs, keys } = self;
1234 let (v1, v2) = value.split_halves::<MDiv2>();
1235 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
1236 .into_vec()
1237 .into_iter()
1238 .map(|m| m.split_halves::<MDiv2>())
1239 .unzip();
1240 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
1241 .into_vec()
1242 .into_iter()
1243 .map(|k| k.split_halves::<MDiv2>())
1244 .unzip();
1245 (
1246 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1247 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1248 )
1249 }
1250
1251 #[allow(clippy::type_complexity)]
1252 pub fn merge_halves(this: Self, other: Self) -> BatchedShare<V, A, B, Prod<M, U2>>
1254 where
1255 M: Mul<U2, Output: Positive>,
1256 A: PartialEq,
1257 {
1258 let PairwiseAuthShare {
1259 value: v1,
1260 macs: m1,
1261 keys: k1,
1262 } = this;
1263 let PairwiseAuthShare {
1264 value: v2,
1265 macs: m2,
1266 keys: k2,
1267 } = other;
1268 let value = HeapArray::merge_halves(v1, v2);
1269 let macs: Box<[_]> = izip_eq!(m1, m2)
1270 .map(|(a, b)| HeapArray::merge_halves(a, b))
1271 .collect();
1272 let keys: Box<[_]> = izip_eq!(k1, k2)
1273 .map(|(a, b)| PairwiseAuthKey::merge_halves(a, b))
1274 .collect();
1275 PairwiseAuthShare::try_new(value, macs, keys).unwrap()
1276 }
1277
1278 #[allow(clippy::type_complexity)]
1279 pub fn split_thirds<MDiv3>(
1282 self,
1283 ) -> (
1284 BatchedShare<V, A, B, MDiv3>,
1285 BatchedShare<V, A, B, MDiv3>,
1286 BatchedShare<V, A, B, MDiv3>,
1287 )
1288 where
1289 MDiv3: Positive + Mul<U3, Output = M>,
1290 {
1291 let PairwiseAuthShare { value, macs, keys } = self;
1292 let (v1, v2, v3) = value.split_thirds::<MDiv3>();
1293 let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
1294 .into_vec()
1295 .into_iter()
1296 .map(|m| m.split_thirds::<MDiv3>())
1297 .multiunzip();
1298 let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
1299 .into_vec()
1300 .into_iter()
1301 .map(|k| k.split_thirds::<MDiv3>())
1302 .multiunzip();
1303 (
1304 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1305 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1306 PairwiseAuthShare::try_new(v3, macs3.into(), keys3.into()).unwrap(),
1307 )
1308 }
1309
1310 #[allow(clippy::type_complexity)]
1311 pub fn merge_thirds(
1313 first: Self,
1314 second: Self,
1315 third: Self,
1316 ) -> BatchedShare<V, A, B, Prod<M, U3>>
1317 where
1318 M: Mul<U3, Output: Positive>,
1319 A: PartialEq,
1320 {
1321 let PairwiseAuthShare {
1322 value: v1,
1323 macs: m1,
1324 keys: k1,
1325 } = first;
1326 let PairwiseAuthShare {
1327 value: v2,
1328 macs: m2,
1329 keys: k2,
1330 } = second;
1331 let PairwiseAuthShare {
1332 value: v3,
1333 macs: m3,
1334 keys: k3,
1335 } = third;
1336 let value = HeapArray::merge_thirds(v1, v2, v3);
1337 let macs: Box<[_]> = izip_eq!(m1, m2, m3)
1338 .map(|(a, b, c)| HeapArray::merge_thirds(a, b, c))
1339 .collect();
1340 let keys: Box<[_]> = izip_eq!(k1, k2, k3)
1341 .map(|(a, b, c)| PairwiseAuthKey::merge_thirds(a, b, c))
1342 .collect();
1343 PairwiseAuthShare::try_new(value, macs, keys).unwrap()
1344 }
1345
1346 #[allow(clippy::type_complexity)]
1347 pub fn chunks<CS: Positive>(
1349 &self,
1350 ) -> BatchedSharesChunks<
1351 <HeapArray<V, M> as IntoIterator>::IntoIter,
1352 <HeapArray<B, M> as IntoIterator>::IntoIter,
1353 A,
1354 <HeapArray<B, M> as IntoIterator>::IntoIter,
1355 CS,
1356 >
1357 where
1358 M: PartialDiv<CS>,
1359 {
1360 BatchedSharesChunks {
1361 inner: self.into_iter(),
1362 remaining_chunks: M::USIZE / CS::USIZE,
1363 _ds: PhantomData,
1364 }
1365 }
1366
1367 pub fn swap(&mut self, i: usize, j: usize) {
1370 self.value.swap(i, j);
1371 for mac in self.macs.iter_mut() {
1372 mac.swap(i, j);
1373 }
1374 for key in self.keys.iter_mut() {
1375 key.beta.swap(i, j);
1376 }
1377 }
1378}
1379
1380pub struct BatchedSharesChunks<VIter: Iterator, MacIter: Iterator, A, BIter: Iterator, DS: Positive>
1386{
1387 inner: BatchedSharesIterator<VIter, MacIter, A, BIter>,
1388 remaining_chunks: usize,
1389 _ds: PhantomData<DS>,
1390}
1391
1392impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator, DS: Positive>
1393 BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1394{
1395 pub fn len(&self) -> usize {
1396 self.remaining_chunks
1397 }
1398
1399 pub fn is_empty(&self) -> bool {
1400 self.remaining_chunks == 0
1401 }
1402}
1403
1404impl<
1405 VIter: Iterator,
1406 MacIter: Iterator,
1407 A: Clone,
1408 BIter: Iterator<Item = MacIter::Item>,
1409 DS: Positive,
1410 > Iterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1411where
1412 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1413 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1414{
1415 type Item = BatchedShare<VIter::Item, A, MacIter::Item, DS>;
1416
1417 fn next(&mut self) -> Option<Self::Item> {
1418 if self.remaining_chunks == 0 {
1419 return None;
1420 }
1421 let chunk: Vec<_> = self.inner.by_ref().take(DS::to_usize()).collect();
1422 if chunk.is_empty() {
1423 return None;
1424 }
1425 self.remaining_chunks -= 1;
1426 Some(chunk.into_iter().collect())
1427 }
1428
1429 fn size_hint(&self) -> (usize, Option<usize>) {
1430 (self.remaining_chunks, Some(self.remaining_chunks))
1431 }
1432}
1433
1434impl<
1435 VIter: Iterator,
1436 MacIter: Iterator,
1437 A: Clone,
1438 BIter: Iterator<Item = MacIter::Item>,
1439 DS: Positive,
1440 > ExactSizeIterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1441where
1442 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1443 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1444{
1445 fn len(&self) -> usize {
1446 self.remaining_chunks
1447 }
1448}
1449
1450impl<V, A, B, N: Positive> Reconstructible for HeapArray<PairwiseAuthShare<V, A, B>, N>
1457where
1458 PairwiseAuthShare<V, A, B>: Reconstructible,
1459 <PairwiseAuthShare<V, A, B> as Reconstructible>::Opening: Clone,
1460{
1461 type Opening = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening, N>;
1462 type Value = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Value, N>;
1463
1464 fn open_to(&self, for_peer: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
1465 self.into_iter()
1466 .map(|s| s.open_to(for_peer))
1467 .collect::<Result<_, _>>()
1468 }
1469
1470 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
1471 let per_share: Vec<Vec<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening>> = self
1472 .into_iter()
1473 .map(|s| s.open_to_all_others().collect())
1474 .collect();
1475 transpose(per_share)
1476 .into_iter()
1477 .map(|col| col.try_into().expect("size mismatch in open_to_all_others"))
1478 }
1479
1480 fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
1481 self.iter()
1482 .enumerate()
1483 .map(|(i, share)| {
1484 let my_openings: Vec<_> = openings
1485 .iter()
1486 .map(|o| o.get(i).cloned())
1487 .collect::<Option<_>>()
1488 .ok_or_else(|| {
1489 PrimitiveError::InvalidParameters(
1490 "Opening is missing for some share.".to_string(),
1491 )
1492 })?;
1493 share.reconstruct(my_openings)
1494 })
1495 .collect::<Result<_, _>>()
1496 }
1497}
1498
1499impl<C: Curve> From<ScalarShare<C>> for PointShare<C> {
1502 #[inline]
1503 fn from(scalar_share: ScalarShare<C>) -> Self {
1504 scalar_share * &Point::<C>::generator()
1505 }
1506}
1507
1508impl<C: Curve, M: Positive> From<ScalarShares<C, M>> for PointShares<C, M> {
1509 #[inline]
1510 fn from(scalar_shares: ScalarShares<C, M>) -> Self {
1511 scalar_shares * &Point::<C>::generator()
1512 }
1513}
1514
1515#[cfg(test)]
1516mod tests {
1517 use std::{fmt::Debug, ops::Div};
1518
1519 use typenum::{U2, U3};
1520
1521 use super::*;
1522 use crate::{random::test_rng, sharing::Verifiable};
1523
1524 pub(super) trait ShareValue<A, B, Const>:
1530 Clone
1531 + PartialEq
1532 + Debug
1533 + Random
1534 + AdditiveShares
1535 + ConstantTimeEq
1536 + ConditionallySelectable
1537 + Neg<Output = Self>
1538 + for<'a> Sub<&'a Self, Output = Self>
1539 + for<'a> AddAssign<&'a Self>
1540 + for<'a> Mul<&'a A, Output = B>
1541 + for<'a> Mul<&'a Const, Output = Self>
1542 + for<'a> MulAssign<&'a Const>
1543 + Send
1544 + Sync
1545 + 'static
1546 + Serialize
1547 + DeserializeOwned
1548 + SchemaWrite<Src = Self>
1549 + for<'de> SchemaRead<'de, Dst = Self>
1550 {
1551 }
1552
1553 impl<V, A, B, Const> ShareValue<A, B, Const> for V where
1554 V: Clone
1555 + PartialEq
1556 + Debug
1557 + Random
1558 + AdditiveShares
1559 + ConstantTimeEq
1560 + ConditionallySelectable
1561 + Neg<Output = V>
1562 + for<'a> Sub<&'a V, Output = V>
1563 + for<'a> AddAssign<&'a V>
1564 + for<'a> Mul<&'a A, Output = B>
1565 + for<'a> Mul<&'a Const, Output = V>
1566 + for<'a> MulAssign<&'a Const>
1567 + Send
1568 + Sync
1569 + 'static
1570 + Serialize
1571 + DeserializeOwned
1572 + SchemaWrite<Src = V>
1573 + for<'de> SchemaRead<'de, Dst = V>
1574 {
1575 }
1576
1577 pub(super) trait ShareKey:
1581 Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1582 {
1583 }
1584
1585 impl<A> ShareKey for A where
1586 A: Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1587 {
1588 }
1589
1590 pub(super) trait ShareMac<V, A, Const>:
1594 Clone
1595 + PartialEq
1596 + Debug
1597 + Random
1598 + ConstantTimeEq
1599 + ConditionallySelectable
1600 + SubAssign
1601 + Neg<Output = Self>
1602 + for<'b> Add<&'b Self, Output = Self>
1603 + for<'b> AddAssign<&'b Self>
1604 + for<'b> Sub<&'b Self, Output = Self>
1605 + for<'b> SubAssign<&'b Self>
1606 + for<'c> Mul<&'c Const, Output = Self>
1607 + for<'c> MulAssign<&'c Const>
1608 + Send
1609 + Sync
1610 + 'static
1611 + Serialize
1612 + DeserializeOwned
1613 + SchemaWrite<Src = Self>
1614 + for<'de> SchemaRead<'de, Dst = Self>
1615 {
1616 }
1617
1618 impl<B, V, A, Const> ShareMac<V, A, Const> for B where
1619 B: Clone
1620 + PartialEq
1621 + Debug
1622 + Random
1623 + ConstantTimeEq
1624 + ConditionallySelectable
1625 + SubAssign
1626 + Neg<Output = B>
1627 + for<'b> Add<&'b B, Output = B>
1628 + for<'b> AddAssign<&'b B>
1629 + for<'b> Sub<&'b B, Output = B>
1630 + for<'b> SubAssign<&'b B>
1631 + for<'c> Mul<&'c Const, Output = B>
1632 + for<'c> MulAssign<&'c Const>
1633 + Send
1634 + Sync
1635 + 'static
1636 + Serialize
1637 + DeserializeOwned
1638 + SchemaWrite<Src = B>
1639 + for<'de> SchemaRead<'de, Dst = B>
1640 {
1641 }
1642
1643 pub(super) trait BatchedShareItem<A, IB>:
1649 Copy
1650 + Clone
1651 + PartialEq
1652 + Debug
1653 + Random
1654 + ConstantTimeEq
1655 + ConditionallySelectable
1656 + for<'a> Mul<&'a A, Output = IB>
1657 {
1658 }
1659
1660 impl<IV, A, IB> BatchedShareItem<A, IB> for IV where
1661 IV: Copy
1662 + Clone
1663 + PartialEq
1664 + Debug
1665 + Random
1666 + ConstantTimeEq
1667 + ConditionallySelectable
1668 + for<'a> Mul<&'a A, Output = IB>
1669 {
1670 }
1671
1672 pub(super) trait BatchedShareMacItem<IV, A>:
1676 Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1677 {
1678 }
1679
1680 impl<IB, IV, A> BatchedShareMacItem<IV, A> for IB where
1681 IB: Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1682 {
1683 }
1684
1685 pub(super) fn test_open_to<V, A, B, Const>(n_parties: usize)
1688 where
1689 V: ShareValue<A, B, Const>,
1690 A: ShareKey,
1691 B: ShareMac<V, A, Const>,
1692 Const: Random,
1693 {
1694 let mut rng = test_rng();
1695 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1696 for i in 0..n_parties - 1 {
1697 let open = share.open_to(i).unwrap();
1698 assert_eq!(open.get_value(), &share.value);
1699 assert_eq!(open.get_mac(), &share.macs[i]);
1700 }
1701 }
1702
1703 pub(super) fn test_random<V, A, B, Const>(n_parties: usize)
1704 where
1705 V: ShareValue<A, B, Const>,
1706 A: ShareKey,
1707 B: ShareMac<V, A, Const>,
1708 Const: Random,
1709 {
1710 let mut rng = test_rng();
1711 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1712 assert_eq!(share.get_macs().len(), n_parties - 1);
1713 assert_eq!(share.get_keys().len(), n_parties - 1);
1714 let value = V::random(&mut rng);
1715 let share_with_value =
1716 PairwiseAuthShare::<V, A, B>::random_with(&mut rng, (n_parties, value.clone()));
1717 assert_eq!(share_with_value.get_value(), &value);
1718 assert_eq!(share_with_value.get_macs().len(), n_parties - 1);
1719 assert_eq!(share_with_value.get_keys().len(), n_parties - 1);
1720 }
1721
1722 pub(super) fn test_random_vec_and_reconstruct<V, A, B, Const>(n_parties: usize)
1723 where
1724 V: ShareValue<A, B, Const>,
1725 A: ShareKey,
1726 B: ShareMac<V, A, Const>,
1727 Const: Random,
1728 {
1729 let mut rng = test_rng();
1730 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
1731 assert_eq!(shares.len(), n_parties);
1732 for share in &shares {
1733 assert_eq!(share.get_macs().len(), n_parties - 1);
1734 assert_eq!(share.get_keys().len(), n_parties - 1);
1735 }
1736 let unauth: Vec<_> = shares.iter().map(|s| s.get_value().clone()).collect();
1737 let expected = V::from_additive_shares(&unauth);
1738 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1739 assert_eq!(reconstructed, expected);
1740
1741 let value = V::random(&mut rng);
1742 let shares: Vec<_> =
1743 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, value.clone());
1744 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1745 assert_eq!(reconstructed, value);
1746 }
1747
1748 pub(super) fn test_random_vec_with_global_key_and_reconstruct<V, A, B, Const>(n_parties: usize)
1749 where
1750 V: ShareValue<A, B, Const>,
1751 A: ShareKey,
1752 B: ShareMac<V, A, Const>,
1753 Const: Random,
1754 {
1755 let mut rng = test_rng();
1756 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1758 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1759 .collect();
1760 let shares_from_alphas: Vec<_> =
1761 PairwiseAuthShare::<V, A, B>::random_n_with_each(&mut rng, alphas.clone());
1762 assert_eq!(shares_from_alphas.len(), n_parties);
1763 for (share, my_alphas) in izip_eq!(&shares_from_alphas, &alphas) {
1764 assert_eq!(share.get_macs().len(), n_parties - 1);
1765 assert_eq!(share.get_keys().len(), n_parties - 1);
1766 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
1767 }
1768 let _ = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_alphas).unwrap();
1769
1770 let value = V::random(&mut rng);
1772 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1773 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1774 .collect();
1775 let shares_from_value_and_alphas: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
1776 &mut rng,
1777 n_parties,
1778 (value.clone(), alphas.clone()),
1779 );
1780 assert_eq!(shares_from_value_and_alphas.len(), n_parties);
1781 for (share, my_alphas) in izip_eq!(&shares_from_value_and_alphas, &alphas) {
1782 assert_eq!(share.get_macs().len(), n_parties - 1);
1783 assert_eq!(share.get_keys().len(), n_parties - 1);
1784 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
1785 }
1786 let reconstructed =
1787 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_value_and_alphas).unwrap();
1788 assert_eq!(reconstructed, value);
1789
1790 let value = V::random(&mut rng);
1792 let unauth = value.to_additive_shares(n_parties, &mut rng);
1793 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1794 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1795 .collect();
1796 let shares_from_unauth: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with_each(
1797 &mut rng,
1798 izip_eq!(unauth, alphas.clone()),
1799 );
1800 assert_eq!(shares_from_unauth.len(), n_parties);
1801 for (share, my_alphas) in izip_eq!(&shares_from_unauth, &alphas) {
1802 assert_eq!(share.get_macs().len(), n_parties - 1);
1803 assert_eq!(share.get_keys().len(), n_parties - 1);
1804 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
1805 }
1806 let reconstructed =
1807 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_unauth).unwrap();
1808 assert_eq!(reconstructed, value);
1809 }
1810
1811 pub(super) fn test_verify_mac<V, A, B, Const>(n_parties: usize)
1812 where
1813 V: ShareValue<A, B, Const>,
1814 A: ShareKey,
1815 B: ShareMac<V, A, Const>,
1816 Const: Random,
1817 {
1818 let mut rng = test_rng();
1819 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
1820 for i in 0..shares.len() {
1821 for j in 0..shares.len() {
1822 if i == j {
1823 continue;
1824 }
1825 let open = shares[j].open_to(i - (i > j) as usize).unwrap();
1826 shares[i].verify_from(open, j - (j > i) as usize).unwrap();
1827 }
1828 }
1829 PairwiseAuthShare::<V, A, B>::verify_all(shares).unwrap();
1830 }
1831
1832 pub(super) fn test_add<V, A, B, Const>(n_parties: usize)
1833 where
1834 V: ShareValue<A, B, Const>,
1835 A: ShareKey,
1836 B: ShareMac<V, A, Const>,
1837 Const: Random,
1838 {
1839 let mut rng = test_rng();
1840 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1841 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1842 .collect();
1843 let a = V::random(&mut rng);
1844 let b = V::random(&mut rng);
1845 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
1846 &mut rng,
1847 n_parties,
1848 (a.clone(), alphas.clone()),
1849 );
1850 let shares_b: Vec<_> =
1851 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
1852 let expected = a.clone() + &b;
1853
1854 let sum: Vec<_> = izip_eq!(&shares_a, &shares_b)
1855 .map(|(sa, sb)| sa + sb)
1856 .collect();
1857 assert_eq!(
1858 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1859 expected
1860 );
1861
1862 let sum: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
1863 .map(|(sa, sb)| sa + sb)
1864 .collect();
1865 assert_eq!(
1866 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1867 expected
1868 );
1869
1870 let sum: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
1871 .map(|(sa, sb)| sa + sb)
1872 .collect();
1873 assert_eq!(
1874 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1875 expected
1876 );
1877
1878 let sum: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
1879 .map(|(sa, sb)| sa + sb)
1880 .collect();
1881 assert_eq!(
1882 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1883 expected
1884 );
1885
1886 let mut shares_a_mut = shares_a.clone();
1887 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa += sb);
1888 assert_eq!(
1889 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
1890 expected
1891 );
1892
1893 let mut shares_a_mut = shares_a;
1894 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa += sb);
1895 assert_eq!(
1896 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
1897 expected
1898 );
1899 }
1900
1901 pub(super) fn test_add_plaintext<V, A, B, Const>(n_parties: usize)
1902 where
1903 V: ShareValue<A, B, Const>,
1904 A: ShareKey,
1905 B: ShareMac<V, A, Const>,
1906 Const: Random,
1907 {
1908 let mut rng = test_rng();
1909 let a = V::random(&mut rng);
1910 let k = V::random(&mut rng);
1911 let shares_a: Vec<_> =
1912 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
1913
1914 let shares_plus_k_ref: Vec<_> = shares_a
1915 .iter()
1916 .enumerate()
1917 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
1918 .collect();
1919 assert_eq!(
1920 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k_ref).unwrap(),
1921 a.clone() + &k,
1922 );
1923
1924 let shares_plus_k: Vec<_> = shares_a
1925 .into_iter()
1926 .enumerate()
1927 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
1928 .collect();
1929 assert_eq!(
1930 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k).unwrap(),
1931 a + &k,
1932 );
1933 }
1934
1935 pub(super) fn test_mul_constant<V, A, B, Const>(n_parties: usize)
1936 where
1937 V: ShareValue<A, B, Const>,
1938 A: ShareKey,
1939 B: ShareMac<V, A, Const>,
1940 Const: Random + PartialEq + Debug,
1941 {
1942 let mut rng = test_rng();
1943 let a = V::random(&mut rng);
1944 let k = Const::random(&mut rng);
1945 let shares_a: Vec<_> =
1946 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
1947
1948 let shares_a_times_k: Vec<_> = izip_eq!(shares_a.clone()).map(|sa| sa * &k).collect();
1949 assert_eq!(
1950 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_times_k).unwrap(),
1951 a.clone() * &k,
1952 );
1953
1954 let mut shares_a_mut = shares_a;
1955 izip_eq!(&mut shares_a_mut).for_each(|sa| *sa *= &k);
1956 assert_eq!(
1957 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
1958 a * &k,
1959 );
1960 }
1961
1962 pub(super) fn test_sub<V, A, B, Const>(n_parties: usize)
1963 where
1964 V: ShareValue<A, B, Const>,
1965 A: ShareKey,
1966 B: ShareMac<V, A, Const>,
1967 Const: Random,
1968 {
1969 let mut rng = test_rng();
1970 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1971 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1972 .collect();
1973 let a = V::random(&mut rng);
1974 let b = V::random(&mut rng);
1975 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
1976 &mut rng,
1977 n_parties,
1978 (a.clone(), alphas.clone()),
1979 );
1980 let shares_b: Vec<_> =
1981 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
1982 let expected = a.clone() - &b;
1983
1984 let diff: Vec<_> = izip_eq!(&shares_a, &shares_b)
1985 .map(|(sa, sb)| sa - sb)
1986 .collect();
1987 assert_eq!(
1988 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
1989 expected
1990 );
1991
1992 let diff: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
1993 .map(|(sa, sb)| sa - sb)
1994 .collect();
1995 assert_eq!(
1996 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
1997 expected
1998 );
1999
2000 let diff: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
2001 .map(|(sa, sb)| sa - sb)
2002 .collect();
2003 assert_eq!(
2004 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2005 expected
2006 );
2007
2008 let diff: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
2009 .map(|(sa, sb)| sa - sb)
2010 .collect();
2011 assert_eq!(
2012 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2013 expected
2014 );
2015
2016 let mut shares_a_mut = shares_a.clone();
2017 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa -= sb);
2018 assert_eq!(
2019 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2020 expected
2021 );
2022
2023 let mut shares_a_mut = shares_a;
2024 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa -= sb);
2025 assert_eq!(
2026 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2027 expected
2028 );
2029 }
2030
2031 pub(super) fn test_neg<V, A, B, Const>(n_parties: usize)
2032 where
2033 V: ShareValue<A, B, Const>,
2034 A: ShareKey,
2035 B: ShareMac<V, A, Const>,
2036 Const: Random,
2037 {
2038 let mut rng = test_rng();
2039 let a = V::random(&mut rng);
2040 let shares_a: Vec<_> =
2041 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2042
2043 let neg_ref: Vec<_> = shares_a.iter().map(|sa| -sa).collect();
2044 assert_eq!(
2045 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg_ref).unwrap(),
2046 -a.clone(),
2047 );
2048 let neg: Vec<_> = shares_a.into_iter().map(|sa| -sa).collect();
2049 assert_eq!(
2050 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg).unwrap(),
2051 -a,
2052 );
2053 }
2054
2055 pub(super) fn test_conditional_select<V, A, B, Const>(n_parties: usize)
2056 where
2057 V: ShareValue<A, B, Const>,
2058 A: ShareKey,
2059 B: ShareMac<V, A, Const>,
2060 Const: Random,
2061 {
2062 let mut rng = test_rng();
2063 let shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2064 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2065 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2066 &shares_a,
2067 &shares_b,
2068 Choice::from(0u8),
2069 );
2070 assert_eq!(selected, shares_a);
2071 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2072 &shares_a,
2073 &shares_b,
2074 Choice::from(1u8),
2075 );
2076 assert_eq!(selected, shares_b);
2077 }
2078
2079 pub(super) fn test_ct_eq<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 shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2088 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2089 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
2090 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
2091 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
2092 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
2093 }
2094
2095 pub(super) fn test_split_halves<IV, A, IB, M, MDiv2>(n_parties: usize)
2098 where
2099 IV: BatchedShareItem<A, IB>,
2100 A: ShareKey,
2101 IB: BatchedShareMacItem<IV, A>,
2102 M: Positive + Div<U2, Output = MDiv2>,
2103 MDiv2: Positive + Mul<U2, Output = M>,
2104 {
2105 let mut rng = test_rng();
2106 let m_div2 = MDiv2::to_usize();
2107 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2108 let (shares1, shares2) = shares.clone().split_halves::<MDiv2>();
2109
2110 assert_eq!(shares1.get_value().len(), m_div2);
2111 assert_eq!(shares2.get_value().len(), m_div2);
2112 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div2]);
2113 assert_eq!(shares2.get_value().as_ref(), &shares.get_value()[m_div2..]);
2114
2115 izip_eq!(&shares1.macs, &shares2.macs, &shares.macs).for_each(|(mac1, mac2, mac)| {
2116 assert_eq!(mac1.as_ref(), &mac[..m_div2]);
2117 assert_eq!(mac2.as_ref(), &mac[m_div2..]);
2118 });
2119 izip_eq!(&shares1.keys, &shares2.keys, &shares.keys).for_each(|(key1, key2, key)| {
2120 assert_eq!(key1.alpha, key.alpha);
2121 assert_eq!(key2.alpha, key.alpha);
2122 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div2]);
2123 assert_eq!(key2.beta.as_ref(), &key.beta[m_div2..]);
2124 });
2125
2126 let merged = BatchedShare::<IV, A, IB, MDiv2>::merge_halves(shares1, shares2);
2127 assert_eq!(merged, shares);
2128 }
2129
2130 pub(super) fn test_split_thirds<IV, A, IB, M, MDiv3>(n_parties: usize)
2131 where
2132 IV: BatchedShareItem<A, IB>,
2133 A: ShareKey,
2134 IB: BatchedShareMacItem<IV, A>,
2135 M: Positive,
2136 MDiv3: Positive + Mul<U3, Output = M>,
2137 M: Mul<U3, Output: Positive>,
2138 {
2139 let mut rng = test_rng();
2140 let m_div3 = MDiv3::to_usize();
2141 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2142 let (shares1, shares2, shares3) = shares.clone().split_thirds::<MDiv3>();
2143
2144 assert_eq!(shares1.get_value().len(), m_div3);
2145 assert_eq!(shares2.get_value().len(), m_div3);
2146 assert_eq!(shares3.get_value().len(), m_div3);
2147 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div3]);
2148 assert_eq!(
2149 shares2.get_value().as_ref(),
2150 &shares.get_value()[m_div3..(2 * m_div3)]
2151 );
2152 assert_eq!(
2153 shares3.get_value().as_ref(),
2154 &shares.get_value()[(2 * m_div3)..]
2155 );
2156
2157 izip_eq!(&shares1.macs, &shares2.macs, &shares3.macs, &shares.macs).for_each(
2158 |(mac1, mac2, mac3, mac)| {
2159 assert_eq!(mac1.as_ref(), &mac[..m_div3]);
2160 assert_eq!(mac2.as_ref(), &mac[m_div3..(2 * m_div3)]);
2161 assert_eq!(mac3.as_ref(), &mac[(2 * m_div3)..(3 * m_div3)]);
2162 },
2163 );
2164 izip_eq!(&shares1.keys, &shares2.keys, &shares3.keys, &shares.keys).for_each(
2165 |(key1, key2, key3, key)| {
2166 assert_eq!(key1.alpha, key.alpha);
2167 assert_eq!(key2.alpha, key.alpha);
2168 assert_eq!(key3.alpha, key.alpha);
2169 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div3]);
2170 assert_eq!(key2.beta.as_ref(), &key.beta[m_div3..(2 * m_div3)]);
2171 assert_eq!(key3.beta.as_ref(), &key.beta[(2 * m_div3)..(3 * m_div3)]);
2172 },
2173 );
2174
2175 let merged = BatchedShare::<IV, A, IB, MDiv3>::merge_thirds(shares1, shares2, shares3);
2176 assert_eq!(merged, shares);
2177 }
2178
2179 pub(super) fn test_into_iter<IV, A, IB, M>(n_parties: usize)
2180 where
2181 IV: BatchedShareItem<A, IB>,
2182 A: ShareKey,
2183 IB: BatchedShareMacItem<IV, A>,
2184 M: Positive,
2185 {
2186 let mut rng = test_rng();
2187 let m = M::to_usize();
2188 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2189 let mut iter = shares.clone().into_iter();
2190 assert_eq!(iter.len(), m);
2191 for i in 0..m {
2192 assert_eq!(iter.len(), m - i);
2193 let share = iter.next().unwrap();
2194 assert_eq!(share.value, shares.get_value()[i]);
2195 for j in 0..n_parties - 1 {
2196 assert_eq!(share.macs[j], shares.macs[j][i]);
2197 assert_eq!(share.keys[j].alpha, shares.keys[j].alpha);
2198 assert_eq!(share.keys[j].beta, shares.keys[j].beta[i]);
2199 }
2200 }
2201 }
2202
2203 pub(super) fn test_from_iterator<IV, A, IB, M>(n_parties: usize)
2204 where
2205 IV: BatchedShareItem<A, IB>,
2206 A: ShareKey,
2207 IB: BatchedShareMacItem<IV, A>,
2208 M: Positive,
2209 {
2210 let mut rng = test_rng();
2211 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2212 let collected: Vec<_> = shares.clone().into_iter().collect();
2213 let from_iterator: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2214 assert_eq!(shares, from_iterator);
2215 }
2216
2217 pub(super) fn test_from_iterator_unequal_sizes<IV, A, IB, M>(n_parties: usize)
2218 where
2219 IV: BatchedShareItem<A, IB>,
2220 A: ShareKey,
2221 IB: BatchedShareMacItem<IV, A>,
2222 M: Positive,
2223 BatchedShare<IV, A, IB, M>: RandomWith<usize>,
2224 {
2225 let mut rng = test_rng();
2226 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2227 let mut collected: Vec<_> = shares.into_iter().collect();
2228 collected.pop();
2229 let _: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2230 }
2231
2232 pub(super) fn test_chunks<IV, A, IB, M, CS>(n_parties: usize)
2233 where
2234 IV: BatchedShareItem<A, IB>,
2235 A: ShareKey,
2236 IB: BatchedShareMacItem<IV, A>,
2237 M: Positive + typenum::PartialDiv<CS>,
2238 CS: Positive,
2239 BatchedShare<IV, A, IB, M>: RandomWith<usize> + Clone + Debug,
2240 {
2241 let mut rng = test_rng();
2242 let m = M::to_usize();
2243 let chunk_size = CS::to_usize();
2244 let n_chunks = m / chunk_size;
2245 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2246 let mut chunks_iter = shares.chunks::<CS>();
2247 assert_eq!(chunks_iter.len(), n_chunks);
2248 for i in 0..n_chunks {
2249 assert_eq!(chunks_iter.len(), n_chunks - i);
2250 let chunk = chunks_iter.next().unwrap();
2251 assert_eq!(chunk.value.len(), chunk_size);
2252 for j in 0..chunk_size {
2253 assert_eq!(chunk.value[j], shares.get_value()[i * chunk_size + j]);
2254 }
2255 for (mac_chunk, macs) in izip_eq!(&chunk.macs, &shares.macs) {
2256 for j in 0..chunk_size {
2257 assert_eq!(mac_chunk[j], macs[i * chunk_size + j]);
2258 }
2259 }
2260 for (key_chunk, keys) in izip_eq!(&chunk.keys, &shares.keys) {
2261 assert_eq!(key_chunk.alpha, keys.alpha);
2262 for j in 0..chunk_size {
2263 assert_eq!(key_chunk.beta[j], keys.beta[i * chunk_size + j]);
2264 }
2265 }
2266 }
2267 assert!(chunks_iter.next().is_none());
2268 }
2269
2270 mod field_share_tests {
2273 use crate::algebra::{
2274 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2275 field::SubfieldElement,
2276 };
2277
2278 type V = SubfieldElement<ScalarField<C>>;
2281 type A = ScalarAsExtension<C>; type B = ScalarAsExtension<C>;
2283 type Const = SubfieldElement<ScalarField<C>>;
2284 const N: usize = 3;
2285
2286 #[test]
2287 fn test_open_to() {
2288 super::test_open_to::<V, A, B, Const>(N);
2289 }
2290 #[test]
2291 fn test_random() {
2292 super::test_random::<V, A, B, Const>(N);
2293 }
2294 #[test]
2295 fn test_random_vec_and_reconstruct() {
2296 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2297 }
2298 #[test]
2299 fn test_random_vec_with_global_key_and_reconstruct() {
2300 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2301 }
2302 #[test]
2303 fn test_verify_mac() {
2304 super::test_verify_mac::<V, A, B, Const>(N);
2305 }
2306 #[test]
2307 fn test_add() {
2308 super::test_add::<V, A, B, Const>(N);
2309 }
2310 #[test]
2311 fn test_add_plaintext() {
2312 super::test_add_plaintext::<V, A, B, Const>(N);
2313 }
2314 #[test]
2315 fn test_mul_constant() {
2316 super::test_mul_constant::<V, A, B, Const>(N);
2317 }
2318 #[test]
2319 fn test_sub() {
2320 super::test_sub::<V, A, B, Const>(N);
2321 }
2322 #[test]
2323 fn test_neg() {
2324 super::test_neg::<V, A, B, Const>(N);
2325 }
2326 #[test]
2327 fn test_conditional_select() {
2328 super::test_conditional_select::<V, A, B, Const>(N);
2329 }
2330 #[test]
2331 fn test_ct_eq() {
2332 super::test_ct_eq::<V, A, B, Const>(N);
2333 }
2334 }
2335
2336 mod point_share_tests {
2337 use crate::algebra::{
2338 elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension, ScalarField},
2339 field::SubfieldElement,
2340 };
2341
2342 type V = Point<C>;
2344 type A = ScalarAsExtension<C>;
2345 type B = Point<C>;
2346 type Const = SubfieldElement<ScalarField<C>>; const N: usize = 3;
2348
2349 #[test]
2350 fn test_open_to() {
2351 super::test_open_to::<V, A, B, Const>(N);
2352 }
2353 #[test]
2354 fn test_random() {
2355 super::test_random::<V, A, B, Const>(N);
2356 }
2357 #[test]
2358 fn test_random_vec_and_reconstruct() {
2359 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2360 }
2361 #[test]
2362 fn test_random_vec_with_global_key_and_reconstruct() {
2363 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2364 }
2365 #[test]
2366 fn test_verify_mac() {
2367 super::test_verify_mac::<V, A, B, Const>(N);
2368 }
2369 #[test]
2370 fn test_add() {
2371 super::test_add::<V, A, B, Const>(N);
2372 }
2373 #[test]
2374 fn test_add_plaintext() {
2375 super::test_add_plaintext::<V, A, B, Const>(N);
2376 }
2377 #[test]
2378 fn test_mul_constant() {
2379 super::test_mul_constant::<V, A, B, Const>(N);
2380 }
2381 #[test]
2382 fn test_sub() {
2383 super::test_sub::<V, A, B, Const>(N);
2384 }
2385 #[test]
2386 fn test_neg() {
2387 super::test_neg::<V, A, B, Const>(N);
2388 }
2389 #[test]
2390 fn test_conditional_select() {
2391 super::test_conditional_select::<V, A, B, Const>(N);
2392 }
2393 #[test]
2394 fn test_ct_eq() {
2395 super::test_ct_eq::<V, A, B, Const>(N);
2396 }
2397 }
2398
2399 mod field_shares_tests {
2400 use std::ops::Div;
2401
2402 use typenum::{U12, U2, U3, U4};
2403
2404 use crate::{
2405 algebra::{
2406 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2407 field::SubfieldElement,
2408 },
2409 types::heap_array::{FieldElements, SubfieldElements},
2410 };
2411
2412 type F = ScalarField<C>;
2415 type M = U12;
2416 type IV = SubfieldElement<F>;
2417 type A = ScalarAsExtension<C>; type IB = ScalarAsExtension<C>; type V = SubfieldElements<F, M>;
2420 type B = FieldElements<F, M>;
2421 type Const = V; const N: usize = 3;
2423
2424 #[test]
2427 fn test_open_to() {
2428 super::test_open_to::<V, A, B, Const>(N);
2429 }
2430 #[test]
2431 fn test_random() {
2432 super::test_random::<V, A, B, Const>(N);
2433 }
2434 #[test]
2435 fn test_random_vec_and_reconstruct() {
2436 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2437 }
2438 #[test]
2439 fn test_random_vec_with_global_key_and_reconstruct() {
2440 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2441 }
2442 #[test]
2443 fn test_verify_mac() {
2444 super::test_verify_mac::<V, A, B, Const>(N);
2445 }
2446 #[test]
2447 fn test_add() {
2448 super::test_add::<V, A, B, Const>(N);
2449 }
2450 #[test]
2451 fn test_add_plaintext() {
2452 super::test_add_plaintext::<V, A, B, Const>(N);
2453 }
2454 #[test]
2455 fn test_mul_constant() {
2456 super::test_mul_constant::<V, A, B, Const>(N);
2457 }
2458 #[test]
2459 fn test_sub() {
2460 super::test_sub::<V, A, B, Const>(N);
2461 }
2462 #[test]
2463 fn test_neg() {
2464 super::test_neg::<V, A, B, Const>(N);
2465 }
2466 #[test]
2467 fn test_conditional_select() {
2468 super::test_conditional_select::<V, A, B, Const>(N);
2469 }
2470 #[test]
2471 fn test_ct_eq() {
2472 super::test_ct_eq::<V, A, B, Const>(N);
2473 }
2474
2475 type MDiv2 = <U12 as Div<U2>>::Output;
2478 type MDiv3 = <U12 as Div<U3>>::Output;
2479
2480 #[test]
2481 fn test_split_halves() {
2482 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2483 }
2484 #[test]
2485 fn test_split_thirds() {
2486 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2487 }
2488 #[test]
2489 fn test_into_iter() {
2490 super::test_into_iter::<IV, A, IB, M>(N);
2491 }
2492 #[test]
2493 fn test_from_iterator() {
2494 super::test_from_iterator::<IV, A, IB, M>(N);
2495 }
2496 #[test]
2497 #[should_panic]
2498 fn test_from_iterator_unequal_sizes() {
2499 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2500 }
2501 #[test]
2502 fn test_chunks() {
2503 super::test_chunks::<IV, A, IB, M, U4>(N);
2504 }
2505 }
2506
2507 mod point_shares_tests {
2508 use std::ops::Div;
2509
2510 use typenum::{U12, U2, U3, U4};
2511
2512 use crate::{
2513 algebra::elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension},
2514 types::heap_array::{CurvePoints, Scalars},
2515 };
2516
2517 type M = U12;
2520 type IV = Point<C>;
2521 type A = ScalarAsExtension<C>;
2522 type IB = Point<C>;
2523 type V = CurvePoints<C, M>;
2524 type B = CurvePoints<C, M>;
2525 type Const = Scalars<C, M>;
2526 const N: usize = 3;
2527
2528 #[test]
2531 fn test_open_to() {
2532 super::test_open_to::<V, A, B, Const>(N);
2533 }
2534 #[test]
2535 fn test_random() {
2536 super::test_random::<V, A, B, Const>(N);
2537 }
2538 #[test]
2539 fn test_random_vec_and_reconstruct() {
2540 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2541 }
2542 #[test]
2543 fn test_random_vec_with_global_key_and_reconstruct() {
2544 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2545 }
2546 #[test]
2547 fn test_verify_mac() {
2548 super::test_verify_mac::<V, A, B, Const>(N);
2549 }
2550 #[test]
2551 fn test_add() {
2552 super::test_add::<V, A, B, Const>(N);
2553 }
2554 #[test]
2555 fn test_add_plaintext() {
2556 super::test_add_plaintext::<V, A, B, Const>(N);
2557 }
2558 #[test]
2559 fn test_mul_constant() {
2560 super::test_mul_constant::<V, A, B, Const>(N);
2561 }
2562 #[test]
2563 fn test_sub() {
2564 super::test_sub::<V, A, B, Const>(N);
2565 }
2566 #[test]
2567 fn test_neg() {
2568 super::test_neg::<V, A, B, Const>(N);
2569 }
2570 #[test]
2571 fn test_conditional_select() {
2572 super::test_conditional_select::<V, A, B, Const>(N);
2573 }
2574 #[test]
2575 fn test_ct_eq() {
2576 super::test_ct_eq::<V, A, B, Const>(N);
2577 }
2578
2579 type MDiv2 = <U12 as Div<U2>>::Output;
2582 type MDiv3 = <U12 as Div<U3>>::Output;
2583
2584 #[test]
2585 fn test_split_halves() {
2586 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2587 }
2588 #[test]
2589 fn test_split_thirds() {
2590 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2591 }
2592 #[test]
2593 fn test_into_iter() {
2594 super::test_into_iter::<IV, A, IB, M>(N);
2595 }
2596 #[test]
2597 fn test_from_iterator() {
2598 super::test_from_iterator::<IV, A, IB, M>(N);
2599 }
2600 #[test]
2601 #[should_panic]
2602 fn test_from_iterator_unequal_sizes() {
2603 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2604 }
2605 #[test]
2606 fn test_chunks() {
2607 super::test_chunks::<IV, A, IB, M, U4>(N);
2608 }
2609 }
2610}