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, U5};
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 split_fifths<MDiv5>(
1313 self,
1314 ) -> (
1315 BatchedShare<V, A, B, MDiv5>,
1316 BatchedShare<V, A, B, MDiv5>,
1317 BatchedShare<V, A, B, MDiv5>,
1318 BatchedShare<V, A, B, MDiv5>,
1319 BatchedShare<V, A, B, MDiv5>,
1320 )
1321 where
1322 MDiv5: Positive + Mul<U5, Output = M>,
1323 {
1324 fn split_array<T: Copy, M: Positive, MDiv5: Positive + Mul<U5, Output = M>>(
1325 arr: HeapArray<T, M>,
1326 ) -> (
1327 HeapArray<T, MDiv5>,
1328 HeapArray<T, MDiv5>,
1329 HeapArray<T, MDiv5>,
1330 HeapArray<T, MDiv5>,
1331 HeapArray<T, MDiv5>,
1332 ) {
1333 let n = MDiv5::USIZE;
1334 let (a, rest) = arr.split_at(n);
1335 let (b, rest) = rest.split_at(n);
1336 let (c, rest) = rest.split_at(n);
1337 let (d, e) = rest.split_at(n);
1338 (
1339 HeapArray::<T, MDiv5>::try_from(a.to_vec()).unwrap(),
1340 HeapArray::<T, MDiv5>::try_from(b.to_vec()).unwrap(),
1341 HeapArray::<T, MDiv5>::try_from(c.to_vec()).unwrap(),
1342 HeapArray::<T, MDiv5>::try_from(d.to_vec()).unwrap(),
1343 HeapArray::<T, MDiv5>::try_from(e.to_vec()).unwrap(),
1344 )
1345 }
1346
1347 let PairwiseAuthShare { value, macs, keys } = self;
1348 let (v1, v2, v3, v4, v5) = split_array::<V, M, MDiv5>(value);
1349 let (macs1, macs2, macs3, macs4, macs5): (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = macs
1350 .into_vec()
1351 .into_iter()
1352 .map(split_array::<B, M, MDiv5>)
1353 .multiunzip();
1354 let (keys1, keys2, keys3, keys4, keys5): (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = keys
1355 .into_vec()
1356 .into_iter()
1357 .map(|k| {
1358 let PairwiseAuthKey { alpha, beta } = k;
1359 let (b1, b2, b3, b4, b5) = split_array::<B, M, MDiv5>(beta);
1360 (
1361 PairwiseAuthKey::new(alpha.clone(), b1),
1362 PairwiseAuthKey::new(alpha.clone(), b2),
1363 PairwiseAuthKey::new(alpha.clone(), b3),
1364 PairwiseAuthKey::new(alpha.clone(), b4),
1365 PairwiseAuthKey::new(alpha, b5),
1366 )
1367 })
1368 .multiunzip();
1369 (
1370 PairwiseAuthShare::try_new(v1, macs1.into(), keys1.into()).unwrap(),
1371 PairwiseAuthShare::try_new(v2, macs2.into(), keys2.into()).unwrap(),
1372 PairwiseAuthShare::try_new(v3, macs3.into(), keys3.into()).unwrap(),
1373 PairwiseAuthShare::try_new(v4, macs4.into(), keys4.into()).unwrap(),
1374 PairwiseAuthShare::try_new(v5, macs5.into(), keys5.into()).unwrap(),
1375 )
1376 }
1377
1378 #[allow(clippy::type_complexity)]
1379 pub fn merge_thirds(
1381 first: Self,
1382 second: Self,
1383 third: Self,
1384 ) -> BatchedShare<V, A, B, Prod<M, U3>>
1385 where
1386 M: Mul<U3, Output: Positive>,
1387 A: PartialEq,
1388 {
1389 let PairwiseAuthShare {
1390 value: v1,
1391 macs: m1,
1392 keys: k1,
1393 } = first;
1394 let PairwiseAuthShare {
1395 value: v2,
1396 macs: m2,
1397 keys: k2,
1398 } = second;
1399 let PairwiseAuthShare {
1400 value: v3,
1401 macs: m3,
1402 keys: k3,
1403 } = third;
1404 let value = HeapArray::merge_thirds(v1, v2, v3);
1405 let macs: Box<[_]> = izip_eq!(m1, m2, m3)
1406 .map(|(a, b, c)| HeapArray::merge_thirds(a, b, c))
1407 .collect();
1408 let keys: Box<[_]> = izip_eq!(k1, k2, k3)
1409 .map(|(a, b, c)| PairwiseAuthKey::merge_thirds(a, b, c))
1410 .collect();
1411 PairwiseAuthShare::try_new(value, macs, keys).unwrap()
1412 }
1413
1414 #[allow(clippy::type_complexity)]
1415 pub fn chunks<CS: Positive>(
1417 &self,
1418 ) -> BatchedSharesChunks<
1419 <HeapArray<V, M> as IntoIterator>::IntoIter,
1420 <HeapArray<B, M> as IntoIterator>::IntoIter,
1421 A,
1422 <HeapArray<B, M> as IntoIterator>::IntoIter,
1423 CS,
1424 >
1425 where
1426 M: PartialDiv<CS>,
1427 {
1428 BatchedSharesChunks {
1429 inner: self.into_iter(),
1430 remaining_chunks: M::USIZE / CS::USIZE,
1431 _ds: PhantomData,
1432 }
1433 }
1434
1435 pub fn swap(&mut self, i: usize, j: usize) {
1438 self.value.swap(i, j);
1439 for mac in self.macs.iter_mut() {
1440 mac.swap(i, j);
1441 }
1442 for key in self.keys.iter_mut() {
1443 key.beta.swap(i, j);
1444 }
1445 }
1446}
1447
1448pub struct BatchedSharesChunks<VIter: Iterator, MacIter: Iterator, A, BIter: Iterator, DS: Positive>
1454{
1455 inner: BatchedSharesIterator<VIter, MacIter, A, BIter>,
1456 remaining_chunks: usize,
1457 _ds: PhantomData<DS>,
1458}
1459
1460impl<VIter: Iterator, MacIter: Iterator, A: Clone, BIter: Iterator, DS: Positive>
1461 BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1462{
1463 pub fn len(&self) -> usize {
1464 self.remaining_chunks
1465 }
1466
1467 pub fn is_empty(&self) -> bool {
1468 self.remaining_chunks == 0
1469 }
1470}
1471
1472impl<
1473 VIter: Iterator,
1474 MacIter: Iterator,
1475 A: Clone,
1476 BIter: Iterator<Item = MacIter::Item>,
1477 DS: Positive,
1478 > Iterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1479where
1480 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1481 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1482{
1483 type Item = BatchedShare<VIter::Item, A, MacIter::Item, DS>;
1484
1485 fn next(&mut self) -> Option<Self::Item> {
1486 if self.remaining_chunks == 0 {
1487 return None;
1488 }
1489 let chunk: Vec<_> = self.inner.by_ref().take(DS::to_usize()).collect();
1490 if chunk.is_empty() {
1491 return None;
1492 }
1493 self.remaining_chunks -= 1;
1494 Some(chunk.into_iter().collect())
1495 }
1496
1497 fn size_hint(&self) -> (usize, Option<usize>) {
1498 (self.remaining_chunks, Some(self.remaining_chunks))
1499 }
1500}
1501
1502impl<
1503 VIter: Iterator,
1504 MacIter: Iterator,
1505 A: Clone,
1506 BIter: Iterator<Item = MacIter::Item>,
1507 DS: Positive,
1508 > ExactSizeIterator for BatchedSharesChunks<VIter, MacIter, A, BIter, DS>
1509where
1510 HeapArray<VIter::Item, DS>: FromIterator<VIter::Item>,
1511 HeapArray<MacIter::Item, DS>: FromIterator<MacIter::Item>,
1512{
1513 fn len(&self) -> usize {
1514 self.remaining_chunks
1515 }
1516}
1517
1518impl<V, A, B, N: Positive> Reconstructible for HeapArray<PairwiseAuthShare<V, A, B>, N>
1525where
1526 PairwiseAuthShare<V, A, B>: Reconstructible,
1527 <PairwiseAuthShare<V, A, B> as Reconstructible>::Opening: Clone,
1528{
1529 type Opening = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening, N>;
1530 type Value = HeapArray<<PairwiseAuthShare<V, A, B> as Reconstructible>::Value, N>;
1531
1532 fn open_to(&self, for_peer: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
1533 self.into_iter()
1534 .map(|s| s.open_to(for_peer))
1535 .collect::<Result<_, _>>()
1536 }
1537
1538 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
1539 let per_share: Vec<Vec<<PairwiseAuthShare<V, A, B> as Reconstructible>::Opening>> = self
1540 .into_iter()
1541 .map(|s| s.open_to_all_others().collect())
1542 .collect();
1543 transpose(per_share)
1544 .into_iter()
1545 .map(|col| col.try_into().expect("size mismatch in open_to_all_others"))
1546 }
1547
1548 fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
1549 self.iter()
1550 .enumerate()
1551 .map(|(i, share)| {
1552 let my_openings: Vec<_> = openings
1553 .iter()
1554 .map(|o| o.get(i).cloned())
1555 .collect::<Option<_>>()
1556 .ok_or_else(|| {
1557 PrimitiveError::InvalidParameters(
1558 "Opening is missing for some share.".to_string(),
1559 )
1560 })?;
1561 share.reconstruct(my_openings)
1562 })
1563 .collect::<Result<_, _>>()
1564 }
1565}
1566
1567impl<C: Curve> From<ScalarShare<C>> for PointShare<C> {
1570 #[inline]
1571 fn from(scalar_share: ScalarShare<C>) -> Self {
1572 scalar_share * &Point::<C>::generator()
1573 }
1574}
1575
1576impl<C: Curve, M: Positive> From<ScalarShares<C, M>> for PointShares<C, M> {
1577 #[inline]
1578 fn from(scalar_shares: ScalarShares<C, M>) -> Self {
1579 scalar_shares * &Point::<C>::generator()
1580 }
1581}
1582
1583#[cfg(test)]
1584mod tests {
1585 use std::{fmt::Debug, ops::Div};
1586
1587 use typenum::{U2, U3};
1588
1589 use super::*;
1590 use crate::{random::test_rng, sharing::Verifiable};
1591
1592 pub(super) trait ShareValue<A, B, Const>:
1598 Clone
1599 + PartialEq
1600 + Debug
1601 + Random
1602 + AdditiveShares
1603 + ConstantTimeEq
1604 + ConditionallySelectable
1605 + Neg<Output = Self>
1606 + for<'a> Sub<&'a Self, Output = Self>
1607 + for<'a> AddAssign<&'a Self>
1608 + for<'a> Mul<&'a A, Output = B>
1609 + for<'a> Mul<&'a Const, Output = Self>
1610 + for<'a> MulAssign<&'a Const>
1611 + Send
1612 + Sync
1613 + 'static
1614 + Serialize
1615 + DeserializeOwned
1616 + SchemaWrite<Src = Self>
1617 + for<'de> SchemaRead<'de, Dst = Self>
1618 {
1619 }
1620
1621 impl<V, A, B, Const> ShareValue<A, B, Const> for V where
1622 V: Clone
1623 + PartialEq
1624 + Debug
1625 + Random
1626 + AdditiveShares
1627 + ConstantTimeEq
1628 + ConditionallySelectable
1629 + Neg<Output = V>
1630 + for<'a> Sub<&'a V, Output = V>
1631 + for<'a> AddAssign<&'a V>
1632 + for<'a> Mul<&'a A, Output = B>
1633 + for<'a> Mul<&'a Const, Output = V>
1634 + for<'a> MulAssign<&'a Const>
1635 + Send
1636 + Sync
1637 + 'static
1638 + Serialize
1639 + DeserializeOwned
1640 + SchemaWrite<Src = V>
1641 + for<'de> SchemaRead<'de, Dst = V>
1642 {
1643 }
1644
1645 pub(super) trait ShareKey:
1649 Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1650 {
1651 }
1652
1653 impl<A> ShareKey for A where
1654 A: Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1655 {
1656 }
1657
1658 pub(super) trait ShareMac<V, A, Const>:
1662 Clone
1663 + PartialEq
1664 + Debug
1665 + Random
1666 + ConstantTimeEq
1667 + ConditionallySelectable
1668 + SubAssign
1669 + Neg<Output = Self>
1670 + for<'b> Add<&'b Self, Output = Self>
1671 + for<'b> AddAssign<&'b Self>
1672 + for<'b> Sub<&'b Self, Output = Self>
1673 + for<'b> SubAssign<&'b Self>
1674 + for<'c> Mul<&'c Const, Output = Self>
1675 + for<'c> MulAssign<&'c Const>
1676 + Send
1677 + Sync
1678 + 'static
1679 + Serialize
1680 + DeserializeOwned
1681 + SchemaWrite<Src = Self>
1682 + for<'de> SchemaRead<'de, Dst = Self>
1683 {
1684 }
1685
1686 impl<B, V, A, Const> ShareMac<V, A, Const> for B where
1687 B: Clone
1688 + PartialEq
1689 + Debug
1690 + Random
1691 + ConstantTimeEq
1692 + ConditionallySelectable
1693 + SubAssign
1694 + Neg<Output = B>
1695 + for<'b> Add<&'b B, Output = B>
1696 + for<'b> AddAssign<&'b B>
1697 + for<'b> Sub<&'b B, Output = B>
1698 + for<'b> SubAssign<&'b B>
1699 + for<'c> Mul<&'c Const, Output = B>
1700 + for<'c> MulAssign<&'c Const>
1701 + Send
1702 + Sync
1703 + 'static
1704 + Serialize
1705 + DeserializeOwned
1706 + SchemaWrite<Src = B>
1707 + for<'de> SchemaRead<'de, Dst = B>
1708 {
1709 }
1710
1711 pub(super) trait BatchedShareItem<A, IB>:
1717 Copy
1718 + Clone
1719 + PartialEq
1720 + Debug
1721 + Random
1722 + ConstantTimeEq
1723 + ConditionallySelectable
1724 + for<'a> Mul<&'a A, Output = IB>
1725 {
1726 }
1727
1728 impl<IV, A, IB> BatchedShareItem<A, IB> for IV where
1729 IV: Copy
1730 + Clone
1731 + PartialEq
1732 + Debug
1733 + Random
1734 + ConstantTimeEq
1735 + ConditionallySelectable
1736 + for<'a> Mul<&'a A, Output = IB>
1737 {
1738 }
1739
1740 pub(super) trait BatchedShareMacItem<IV, A>:
1744 Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1745 {
1746 }
1747
1748 impl<IB, IV, A> BatchedShareMacItem<IV, A> for IB where
1749 IB: Copy + Clone + PartialEq + Debug + Random + ConstantTimeEq + ConditionallySelectable
1750 {
1751 }
1752
1753 pub(super) fn test_open_to<V, A, B, Const>(n_parties: usize)
1756 where
1757 V: ShareValue<A, B, Const>,
1758 A: ShareKey,
1759 B: ShareMac<V, A, Const>,
1760 Const: Random,
1761 {
1762 let mut rng = test_rng();
1763 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1764 for i in 0..n_parties - 1 {
1765 let open = share.open_to(i).unwrap();
1766 assert_eq!(open.get_value(), &share.value);
1767 assert_eq!(open.get_mac(), &share.macs[i]);
1768 }
1769 }
1770
1771 pub(super) fn test_random<V, A, B, Const>(n_parties: usize)
1772 where
1773 V: ShareValue<A, B, Const>,
1774 A: ShareKey,
1775 B: ShareMac<V, A, Const>,
1776 Const: Random,
1777 {
1778 let mut rng = test_rng();
1779 let share = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
1780 assert_eq!(share.get_macs().len(), n_parties - 1);
1781 assert_eq!(share.get_keys().len(), n_parties - 1);
1782 let value = V::random(&mut rng);
1783 let share_with_value =
1784 PairwiseAuthShare::<V, A, B>::random_with(&mut rng, (n_parties, value.clone()));
1785 assert_eq!(share_with_value.get_value(), &value);
1786 assert_eq!(share_with_value.get_macs().len(), n_parties - 1);
1787 assert_eq!(share_with_value.get_keys().len(), n_parties - 1);
1788 }
1789
1790 pub(super) fn test_random_vec_and_reconstruct<V, A, B, Const>(n_parties: usize)
1791 where
1792 V: ShareValue<A, B, Const>,
1793 A: ShareKey,
1794 B: ShareMac<V, A, Const>,
1795 Const: Random,
1796 {
1797 let mut rng = test_rng();
1798 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
1799 assert_eq!(shares.len(), n_parties);
1800 for share in &shares {
1801 assert_eq!(share.get_macs().len(), n_parties - 1);
1802 assert_eq!(share.get_keys().len(), n_parties - 1);
1803 }
1804 let unauth: Vec<_> = shares.iter().map(|s| s.get_value().clone()).collect();
1805 let expected = V::from_additive_shares(&unauth);
1806 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1807 assert_eq!(reconstructed, expected);
1808
1809 let value = V::random(&mut rng);
1810 let shares: Vec<_> =
1811 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, value.clone());
1812 let reconstructed = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares).unwrap();
1813 assert_eq!(reconstructed, value);
1814 }
1815
1816 pub(super) fn test_random_vec_with_global_key_and_reconstruct<V, A, B, Const>(n_parties: usize)
1817 where
1818 V: ShareValue<A, B, Const>,
1819 A: ShareKey,
1820 B: ShareMac<V, A, Const>,
1821 Const: Random,
1822 {
1823 let mut rng = test_rng();
1824 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1826 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1827 .collect();
1828 let shares_from_alphas: Vec<_> =
1829 PairwiseAuthShare::<V, A, B>::random_n_with_each(&mut rng, alphas.clone());
1830 assert_eq!(shares_from_alphas.len(), n_parties);
1831 for (share, my_alphas) in izip_eq!(&shares_from_alphas, &alphas) {
1832 assert_eq!(share.get_macs().len(), n_parties - 1);
1833 assert_eq!(share.get_keys().len(), n_parties - 1);
1834 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
1835 }
1836 let _ = PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_alphas).unwrap();
1837
1838 let value = V::random(&mut 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 shares_from_value_and_alphas: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
1844 &mut rng,
1845 n_parties,
1846 (value.clone(), alphas.clone()),
1847 );
1848 assert_eq!(shares_from_value_and_alphas.len(), n_parties);
1849 for (share, my_alphas) in izip_eq!(&shares_from_value_and_alphas, &alphas) {
1850 assert_eq!(share.get_macs().len(), n_parties - 1);
1851 assert_eq!(share.get_keys().len(), n_parties - 1);
1852 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
1853 }
1854 let reconstructed =
1855 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_value_and_alphas).unwrap();
1856 assert_eq!(reconstructed, value);
1857
1858 let value = V::random(&mut rng);
1860 let unauth = value.to_additive_shares(n_parties, &mut rng);
1861 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1862 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1863 .collect();
1864 let shares_from_unauth: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with_each(
1865 &mut rng,
1866 izip_eq!(unauth, alphas.clone()),
1867 );
1868 assert_eq!(shares_from_unauth.len(), n_parties);
1869 for (share, my_alphas) in izip_eq!(&shares_from_unauth, &alphas) {
1870 assert_eq!(share.get_macs().len(), n_parties - 1);
1871 assert_eq!(share.get_keys().len(), n_parties - 1);
1872 assert_eq!(share.get_alphas().collect::<Vec<_>>(), *my_alphas);
1873 }
1874 let reconstructed =
1875 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_from_unauth).unwrap();
1876 assert_eq!(reconstructed, value);
1877 }
1878
1879 pub(super) fn test_verify_mac<V, A, B, Const>(n_parties: usize)
1880 where
1881 V: ShareValue<A, B, Const>,
1882 A: ShareKey,
1883 B: ShareMac<V, A, Const>,
1884 Const: Random,
1885 {
1886 let mut rng = test_rng();
1887 let shares: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n(&mut rng, n_parties);
1888 for i in 0..shares.len() {
1889 for j in 0..shares.len() {
1890 if i == j {
1891 continue;
1892 }
1893 let open = shares[j].open_to(i - (i > j) as usize).unwrap();
1894 shares[i].verify_from(open, j - (j > i) as usize).unwrap();
1895 }
1896 }
1897 PairwiseAuthShare::<V, A, B>::verify_all(shares).unwrap();
1898 }
1899
1900 pub(super) fn test_add<V, A, B, Const>(n_parties: usize)
1901 where
1902 V: ShareValue<A, B, Const>,
1903 A: ShareKey,
1904 B: ShareMac<V, A, Const>,
1905 Const: Random,
1906 {
1907 let mut rng = test_rng();
1908 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
1909 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
1910 .collect();
1911 let a = V::random(&mut rng);
1912 let b = V::random(&mut rng);
1913 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
1914 &mut rng,
1915 n_parties,
1916 (a.clone(), alphas.clone()),
1917 );
1918 let shares_b: Vec<_> =
1919 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
1920 let expected = a.clone() + &b;
1921
1922 let sum: Vec<_> = izip_eq!(&shares_a, &shares_b)
1923 .map(|(sa, sb)| sa + sb)
1924 .collect();
1925 assert_eq!(
1926 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1927 expected
1928 );
1929
1930 let sum: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
1931 .map(|(sa, sb)| sa + sb)
1932 .collect();
1933 assert_eq!(
1934 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1935 expected
1936 );
1937
1938 let sum: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
1939 .map(|(sa, sb)| sa + sb)
1940 .collect();
1941 assert_eq!(
1942 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1943 expected
1944 );
1945
1946 let sum: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
1947 .map(|(sa, sb)| sa + sb)
1948 .collect();
1949 assert_eq!(
1950 PairwiseAuthShare::<V, A, B>::reconstruct_all(sum).unwrap(),
1951 expected
1952 );
1953
1954 let mut shares_a_mut = shares_a.clone();
1955 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa += sb);
1956 assert_eq!(
1957 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
1958 expected
1959 );
1960
1961 let mut shares_a_mut = shares_a;
1962 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa += sb);
1963 assert_eq!(
1964 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
1965 expected
1966 );
1967 }
1968
1969 pub(super) fn test_add_plaintext<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 a = V::random(&mut rng);
1978 let k = V::random(&mut rng);
1979 let shares_a: Vec<_> =
1980 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
1981
1982 let shares_plus_k_ref: Vec<_> = shares_a
1983 .iter()
1984 .enumerate()
1985 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
1986 .collect();
1987 assert_eq!(
1988 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k_ref).unwrap(),
1989 a.clone() + &k,
1990 );
1991
1992 let shares_plus_k: Vec<_> = shares_a
1993 .into_iter()
1994 .enumerate()
1995 .map(|(i, share_a)| share_a.to_owned().add_plaintext(&k, i == 0))
1996 .collect();
1997 assert_eq!(
1998 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_plus_k).unwrap(),
1999 a + &k,
2000 );
2001 }
2002
2003 pub(super) fn test_mul_constant<V, A, B, Const>(n_parties: usize)
2004 where
2005 V: ShareValue<A, B, Const>,
2006 A: ShareKey,
2007 B: ShareMac<V, A, Const>,
2008 Const: Random + PartialEq + Debug,
2009 {
2010 let mut rng = test_rng();
2011 let a = V::random(&mut rng);
2012 let k = Const::random(&mut rng);
2013 let shares_a: Vec<_> =
2014 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2015
2016 let shares_a_times_k: Vec<_> = izip_eq!(shares_a.clone()).map(|sa| sa * &k).collect();
2017 assert_eq!(
2018 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_times_k).unwrap(),
2019 a.clone() * &k,
2020 );
2021
2022 let mut shares_a_mut = shares_a;
2023 izip_eq!(&mut shares_a_mut).for_each(|sa| *sa *= &k);
2024 assert_eq!(
2025 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2026 a * &k,
2027 );
2028 }
2029
2030 pub(super) fn test_sub<V, A, B, Const>(n_parties: usize)
2031 where
2032 V: ShareValue<A, B, Const>,
2033 A: ShareKey,
2034 B: ShareMac<V, A, Const>,
2035 Const: Random,
2036 {
2037 let mut rng = test_rng();
2038 let alphas: Vec<Vec<GlobalKey<A>>> = (0..n_parties)
2039 .map(|_| GlobalKey::<A>::random_n::<Vec<_>>(&mut rng, n_parties - 1))
2040 .collect();
2041 let a = V::random(&mut rng);
2042 let b = V::random(&mut rng);
2043 let shares_a: Vec<_> = PairwiseAuthShare::<V, A, B>::random_n_with(
2044 &mut rng,
2045 n_parties,
2046 (a.clone(), alphas.clone()),
2047 );
2048 let shares_b: Vec<_> =
2049 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, (b.clone(), alphas));
2050 let expected = a.clone() - &b;
2051
2052 let diff: Vec<_> = izip_eq!(&shares_a, &shares_b)
2053 .map(|(sa, sb)| sa - sb)
2054 .collect();
2055 assert_eq!(
2056 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2057 expected
2058 );
2059
2060 let diff: Vec<_> = izip_eq!(&shares_a, shares_b.clone())
2061 .map(|(sa, sb)| sa - sb)
2062 .collect();
2063 assert_eq!(
2064 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2065 expected
2066 );
2067
2068 let diff: Vec<_> = izip_eq!(shares_a.clone(), &shares_b)
2069 .map(|(sa, sb)| sa - sb)
2070 .collect();
2071 assert_eq!(
2072 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2073 expected
2074 );
2075
2076 let diff: Vec<_> = izip_eq!(shares_a.clone(), shares_b.clone())
2077 .map(|(sa, sb)| sa - sb)
2078 .collect();
2079 assert_eq!(
2080 PairwiseAuthShare::<V, A, B>::reconstruct_all(diff).unwrap(),
2081 expected
2082 );
2083
2084 let mut shares_a_mut = shares_a.clone();
2085 izip_eq!(&mut shares_a_mut, &shares_b).for_each(|(sa, sb)| *sa -= sb);
2086 assert_eq!(
2087 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2088 expected
2089 );
2090
2091 let mut shares_a_mut = shares_a;
2092 izip_eq!(&mut shares_a_mut, shares_b).for_each(|(sa, sb)| *sa -= sb);
2093 assert_eq!(
2094 PairwiseAuthShare::<V, A, B>::reconstruct_all(shares_a_mut).unwrap(),
2095 expected
2096 );
2097 }
2098
2099 pub(super) fn test_neg<V, A, B, Const>(n_parties: usize)
2100 where
2101 V: ShareValue<A, B, Const>,
2102 A: ShareKey,
2103 B: ShareMac<V, A, Const>,
2104 Const: Random,
2105 {
2106 let mut rng = test_rng();
2107 let a = V::random(&mut rng);
2108 let shares_a: Vec<_> =
2109 PairwiseAuthShare::<V, A, B>::random_n_with(&mut rng, n_parties, a.clone());
2110
2111 let neg_ref: Vec<_> = shares_a.iter().map(|sa| -sa).collect();
2112 assert_eq!(
2113 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg_ref).unwrap(),
2114 -a.clone(),
2115 );
2116 let neg: Vec<_> = shares_a.into_iter().map(|sa| -sa).collect();
2117 assert_eq!(
2118 PairwiseAuthShare::<V, A, B>::reconstruct_all(neg).unwrap(),
2119 -a,
2120 );
2121 }
2122
2123 pub(super) fn test_conditional_select<V, A, B, Const>(n_parties: usize)
2124 where
2125 V: ShareValue<A, B, Const>,
2126 A: ShareKey,
2127 B: ShareMac<V, A, Const>,
2128 Const: Random,
2129 {
2130 let mut rng = test_rng();
2131 let shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2132 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2133 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2134 &shares_a,
2135 &shares_b,
2136 Choice::from(0u8),
2137 );
2138 assert_eq!(selected, shares_a);
2139 let selected = PairwiseAuthShare::<V, A, B>::conditional_select(
2140 &shares_a,
2141 &shares_b,
2142 Choice::from(1u8),
2143 );
2144 assert_eq!(selected, shares_b);
2145 }
2146
2147 pub(super) fn test_ct_eq<V, A, B, Const>(n_parties: usize)
2148 where
2149 V: ShareValue<A, B, Const>,
2150 A: ShareKey,
2151 B: ShareMac<V, A, Const>,
2152 Const: Random,
2153 {
2154 let mut rng = test_rng();
2155 let shares_a = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2156 let shares_b = PairwiseAuthShare::<V, A, B>::random_with(&mut rng, n_parties);
2157 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
2158 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
2159 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
2160 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
2161 }
2162
2163 pub(super) fn test_split_halves<IV, A, IB, M, MDiv2>(n_parties: usize)
2166 where
2167 IV: BatchedShareItem<A, IB>,
2168 A: ShareKey,
2169 IB: BatchedShareMacItem<IV, A>,
2170 M: Positive + Div<U2, Output = MDiv2>,
2171 MDiv2: Positive + Mul<U2, Output = M>,
2172 {
2173 let mut rng = test_rng();
2174 let m_div2 = MDiv2::to_usize();
2175 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2176 let (shares1, shares2) = shares.clone().split_halves::<MDiv2>();
2177
2178 assert_eq!(shares1.get_value().len(), m_div2);
2179 assert_eq!(shares2.get_value().len(), m_div2);
2180 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div2]);
2181 assert_eq!(shares2.get_value().as_ref(), &shares.get_value()[m_div2..]);
2182
2183 izip_eq!(&shares1.macs, &shares2.macs, &shares.macs).for_each(|(mac1, mac2, mac)| {
2184 assert_eq!(mac1.as_ref(), &mac[..m_div2]);
2185 assert_eq!(mac2.as_ref(), &mac[m_div2..]);
2186 });
2187 izip_eq!(&shares1.keys, &shares2.keys, &shares.keys).for_each(|(key1, key2, key)| {
2188 assert_eq!(key1.alpha, key.alpha);
2189 assert_eq!(key2.alpha, key.alpha);
2190 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div2]);
2191 assert_eq!(key2.beta.as_ref(), &key.beta[m_div2..]);
2192 });
2193
2194 let merged = BatchedShare::<IV, A, IB, MDiv2>::merge_halves(shares1, shares2);
2195 assert_eq!(merged, shares);
2196 }
2197
2198 pub(super) fn test_split_thirds<IV, A, IB, M, MDiv3>(n_parties: usize)
2199 where
2200 IV: BatchedShareItem<A, IB>,
2201 A: ShareKey,
2202 IB: BatchedShareMacItem<IV, A>,
2203 M: Positive,
2204 MDiv3: Positive + Mul<U3, Output = M>,
2205 M: Mul<U3, Output: Positive>,
2206 {
2207 let mut rng = test_rng();
2208 let m_div3 = MDiv3::to_usize();
2209 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2210 let (shares1, shares2, shares3) = shares.clone().split_thirds::<MDiv3>();
2211
2212 assert_eq!(shares1.get_value().len(), m_div3);
2213 assert_eq!(shares2.get_value().len(), m_div3);
2214 assert_eq!(shares3.get_value().len(), m_div3);
2215 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div3]);
2216 assert_eq!(
2217 shares2.get_value().as_ref(),
2218 &shares.get_value()[m_div3..(2 * m_div3)]
2219 );
2220 assert_eq!(
2221 shares3.get_value().as_ref(),
2222 &shares.get_value()[(2 * m_div3)..]
2223 );
2224
2225 izip_eq!(&shares1.macs, &shares2.macs, &shares3.macs, &shares.macs).for_each(
2226 |(mac1, mac2, mac3, mac)| {
2227 assert_eq!(mac1.as_ref(), &mac[..m_div3]);
2228 assert_eq!(mac2.as_ref(), &mac[m_div3..(2 * m_div3)]);
2229 assert_eq!(mac3.as_ref(), &mac[(2 * m_div3)..(3 * m_div3)]);
2230 },
2231 );
2232 izip_eq!(&shares1.keys, &shares2.keys, &shares3.keys, &shares.keys).for_each(
2233 |(key1, key2, key3, key)| {
2234 assert_eq!(key1.alpha, key.alpha);
2235 assert_eq!(key2.alpha, key.alpha);
2236 assert_eq!(key3.alpha, key.alpha);
2237 assert_eq!(key1.beta.as_ref(), &key.beta[..m_div3]);
2238 assert_eq!(key2.beta.as_ref(), &key.beta[m_div3..(2 * m_div3)]);
2239 assert_eq!(key3.beta.as_ref(), &key.beta[(2 * m_div3)..(3 * m_div3)]);
2240 },
2241 );
2242
2243 let merged = BatchedShare::<IV, A, IB, MDiv3>::merge_thirds(shares1, shares2, shares3);
2244 assert_eq!(merged, shares);
2245 }
2246
2247 pub(super) fn test_into_iter<IV, A, IB, M>(n_parties: usize)
2248 where
2249 IV: BatchedShareItem<A, IB>,
2250 A: ShareKey,
2251 IB: BatchedShareMacItem<IV, A>,
2252 M: Positive,
2253 {
2254 let mut rng = test_rng();
2255 let m = M::to_usize();
2256 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2257 let mut iter = shares.clone().into_iter();
2258 assert_eq!(iter.len(), m);
2259 for i in 0..m {
2260 assert_eq!(iter.len(), m - i);
2261 let share = iter.next().unwrap();
2262 assert_eq!(share.value, shares.get_value()[i]);
2263 for j in 0..n_parties - 1 {
2264 assert_eq!(share.macs[j], shares.macs[j][i]);
2265 assert_eq!(share.keys[j].alpha, shares.keys[j].alpha);
2266 assert_eq!(share.keys[j].beta, shares.keys[j].beta[i]);
2267 }
2268 }
2269 }
2270
2271 pub(super) fn test_from_iterator<IV, A, IB, M>(n_parties: usize)
2272 where
2273 IV: BatchedShareItem<A, IB>,
2274 A: ShareKey,
2275 IB: BatchedShareMacItem<IV, A>,
2276 M: Positive,
2277 {
2278 let mut rng = test_rng();
2279 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2280 let collected: Vec<_> = shares.clone().into_iter().collect();
2281 let from_iterator: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2282 assert_eq!(shares, from_iterator);
2283 }
2284
2285 pub(super) fn test_from_iterator_unequal_sizes<IV, A, IB, M>(n_parties: usize)
2286 where
2287 IV: BatchedShareItem<A, IB>,
2288 A: ShareKey,
2289 IB: BatchedShareMacItem<IV, A>,
2290 M: Positive,
2291 BatchedShare<IV, A, IB, M>: RandomWith<usize>,
2292 {
2293 let mut rng = test_rng();
2294 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2295 let mut collected: Vec<_> = shares.into_iter().collect();
2296 collected.pop();
2297 let _: BatchedShare<IV, A, IB, M> = collected.into_iter().collect();
2298 }
2299
2300 pub(super) fn test_chunks<IV, A, IB, M, CS>(n_parties: usize)
2301 where
2302 IV: BatchedShareItem<A, IB>,
2303 A: ShareKey,
2304 IB: BatchedShareMacItem<IV, A>,
2305 M: Positive + typenum::PartialDiv<CS>,
2306 CS: Positive,
2307 BatchedShare<IV, A, IB, M>: RandomWith<usize> + Clone + Debug,
2308 {
2309 let mut rng = test_rng();
2310 let m = M::to_usize();
2311 let chunk_size = CS::to_usize();
2312 let n_chunks = m / chunk_size;
2313 let shares = BatchedShare::<IV, A, IB, M>::random_with(&mut rng, n_parties);
2314 let mut chunks_iter = shares.chunks::<CS>();
2315 assert_eq!(chunks_iter.len(), n_chunks);
2316 for i in 0..n_chunks {
2317 assert_eq!(chunks_iter.len(), n_chunks - i);
2318 let chunk = chunks_iter.next().unwrap();
2319 assert_eq!(chunk.value.len(), chunk_size);
2320 for j in 0..chunk_size {
2321 assert_eq!(chunk.value[j], shares.get_value()[i * chunk_size + j]);
2322 }
2323 for (mac_chunk, macs) in izip_eq!(&chunk.macs, &shares.macs) {
2324 for j in 0..chunk_size {
2325 assert_eq!(mac_chunk[j], macs[i * chunk_size + j]);
2326 }
2327 }
2328 for (key_chunk, keys) in izip_eq!(&chunk.keys, &shares.keys) {
2329 assert_eq!(key_chunk.alpha, keys.alpha);
2330 for j in 0..chunk_size {
2331 assert_eq!(key_chunk.beta[j], keys.beta[i * chunk_size + j]);
2332 }
2333 }
2334 }
2335 assert!(chunks_iter.next().is_none());
2336 }
2337
2338 mod field_share_tests {
2341 use crate::algebra::{
2342 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2343 field::SubfieldElement,
2344 };
2345
2346 type V = SubfieldElement<ScalarField<C>>;
2349 type A = ScalarAsExtension<C>; type B = ScalarAsExtension<C>;
2351 type Const = SubfieldElement<ScalarField<C>>;
2352 const N: usize = 3;
2353
2354 #[test]
2355 fn test_open_to() {
2356 super::test_open_to::<V, A, B, Const>(N);
2357 }
2358 #[test]
2359 fn test_random() {
2360 super::test_random::<V, A, B, Const>(N);
2361 }
2362 #[test]
2363 fn test_random_vec_and_reconstruct() {
2364 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2365 }
2366 #[test]
2367 fn test_random_vec_with_global_key_and_reconstruct() {
2368 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2369 }
2370 #[test]
2371 fn test_verify_mac() {
2372 super::test_verify_mac::<V, A, B, Const>(N);
2373 }
2374 #[test]
2375 fn test_add() {
2376 super::test_add::<V, A, B, Const>(N);
2377 }
2378 #[test]
2379 fn test_add_plaintext() {
2380 super::test_add_plaintext::<V, A, B, Const>(N);
2381 }
2382 #[test]
2383 fn test_mul_constant() {
2384 super::test_mul_constant::<V, A, B, Const>(N);
2385 }
2386 #[test]
2387 fn test_sub() {
2388 super::test_sub::<V, A, B, Const>(N);
2389 }
2390 #[test]
2391 fn test_neg() {
2392 super::test_neg::<V, A, B, Const>(N);
2393 }
2394 #[test]
2395 fn test_conditional_select() {
2396 super::test_conditional_select::<V, A, B, Const>(N);
2397 }
2398 #[test]
2399 fn test_ct_eq() {
2400 super::test_ct_eq::<V, A, B, Const>(N);
2401 }
2402 }
2403
2404 mod point_share_tests {
2405 use crate::algebra::{
2406 elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension, ScalarField},
2407 field::SubfieldElement,
2408 };
2409
2410 type V = Point<C>;
2412 type A = ScalarAsExtension<C>;
2413 type B = Point<C>;
2414 type Const = SubfieldElement<ScalarField<C>>; const N: usize = 3;
2416
2417 #[test]
2418 fn test_open_to() {
2419 super::test_open_to::<V, A, B, Const>(N);
2420 }
2421 #[test]
2422 fn test_random() {
2423 super::test_random::<V, A, B, Const>(N);
2424 }
2425 #[test]
2426 fn test_random_vec_and_reconstruct() {
2427 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2428 }
2429 #[test]
2430 fn test_random_vec_with_global_key_and_reconstruct() {
2431 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2432 }
2433 #[test]
2434 fn test_verify_mac() {
2435 super::test_verify_mac::<V, A, B, Const>(N);
2436 }
2437 #[test]
2438 fn test_add() {
2439 super::test_add::<V, A, B, Const>(N);
2440 }
2441 #[test]
2442 fn test_add_plaintext() {
2443 super::test_add_plaintext::<V, A, B, Const>(N);
2444 }
2445 #[test]
2446 fn test_mul_constant() {
2447 super::test_mul_constant::<V, A, B, Const>(N);
2448 }
2449 #[test]
2450 fn test_sub() {
2451 super::test_sub::<V, A, B, Const>(N);
2452 }
2453 #[test]
2454 fn test_neg() {
2455 super::test_neg::<V, A, B, Const>(N);
2456 }
2457 #[test]
2458 fn test_conditional_select() {
2459 super::test_conditional_select::<V, A, B, Const>(N);
2460 }
2461 #[test]
2462 fn test_ct_eq() {
2463 super::test_ct_eq::<V, A, B, Const>(N);
2464 }
2465 }
2466
2467 mod field_shares_tests {
2468 use std::ops::Div;
2469
2470 use typenum::{U12, U2, U3, U4};
2471
2472 use crate::{
2473 algebra::{
2474 elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension, ScalarField},
2475 field::SubfieldElement,
2476 },
2477 types::heap_array::{FieldElements, SubfieldElements},
2478 };
2479
2480 type F = ScalarField<C>;
2483 type M = U12;
2484 type IV = SubfieldElement<F>;
2485 type A = ScalarAsExtension<C>; type IB = ScalarAsExtension<C>; type V = SubfieldElements<F, M>;
2488 type B = FieldElements<F, M>;
2489 type Const = V; const N: usize = 3;
2491
2492 #[test]
2495 fn test_open_to() {
2496 super::test_open_to::<V, A, B, Const>(N);
2497 }
2498 #[test]
2499 fn test_random() {
2500 super::test_random::<V, A, B, Const>(N);
2501 }
2502 #[test]
2503 fn test_random_vec_and_reconstruct() {
2504 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2505 }
2506 #[test]
2507 fn test_random_vec_with_global_key_and_reconstruct() {
2508 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2509 }
2510 #[test]
2511 fn test_verify_mac() {
2512 super::test_verify_mac::<V, A, B, Const>(N);
2513 }
2514 #[test]
2515 fn test_add() {
2516 super::test_add::<V, A, B, Const>(N);
2517 }
2518 #[test]
2519 fn test_add_plaintext() {
2520 super::test_add_plaintext::<V, A, B, Const>(N);
2521 }
2522 #[test]
2523 fn test_mul_constant() {
2524 super::test_mul_constant::<V, A, B, Const>(N);
2525 }
2526 #[test]
2527 fn test_sub() {
2528 super::test_sub::<V, A, B, Const>(N);
2529 }
2530 #[test]
2531 fn test_neg() {
2532 super::test_neg::<V, A, B, Const>(N);
2533 }
2534 #[test]
2535 fn test_conditional_select() {
2536 super::test_conditional_select::<V, A, B, Const>(N);
2537 }
2538 #[test]
2539 fn test_ct_eq() {
2540 super::test_ct_eq::<V, A, B, Const>(N);
2541 }
2542
2543 type MDiv2 = <U12 as Div<U2>>::Output;
2546 type MDiv3 = <U12 as Div<U3>>::Output;
2547
2548 #[test]
2549 fn test_split_halves() {
2550 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2551 }
2552 #[test]
2553 fn test_split_thirds() {
2554 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2555 }
2556 #[test]
2557 fn test_into_iter() {
2558 super::test_into_iter::<IV, A, IB, M>(N);
2559 }
2560 #[test]
2561 fn test_from_iterator() {
2562 super::test_from_iterator::<IV, A, IB, M>(N);
2563 }
2564 #[test]
2565 #[should_panic]
2566 fn test_from_iterator_unequal_sizes() {
2567 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2568 }
2569 #[test]
2570 fn test_chunks() {
2571 super::test_chunks::<IV, A, IB, M, U4>(N);
2572 }
2573 }
2574
2575 mod point_shares_tests {
2576 use std::ops::Div;
2577
2578 use typenum::{U12, U2, U3, U4};
2579
2580 use crate::{
2581 algebra::elliptic_curve::{Curve25519Ristretto as C, Point, ScalarAsExtension},
2582 types::heap_array::{CurvePoints, Scalars},
2583 };
2584
2585 type M = U12;
2588 type IV = Point<C>;
2589 type A = ScalarAsExtension<C>;
2590 type IB = Point<C>;
2591 type V = CurvePoints<C, M>;
2592 type B = CurvePoints<C, M>;
2593 type Const = Scalars<C, M>;
2594 const N: usize = 3;
2595
2596 #[test]
2599 fn test_open_to() {
2600 super::test_open_to::<V, A, B, Const>(N);
2601 }
2602 #[test]
2603 fn test_random() {
2604 super::test_random::<V, A, B, Const>(N);
2605 }
2606 #[test]
2607 fn test_random_vec_and_reconstruct() {
2608 super::test_random_vec_and_reconstruct::<V, A, B, Const>(N);
2609 }
2610 #[test]
2611 fn test_random_vec_with_global_key_and_reconstruct() {
2612 super::test_random_vec_with_global_key_and_reconstruct::<V, A, B, Const>(N);
2613 }
2614 #[test]
2615 fn test_verify_mac() {
2616 super::test_verify_mac::<V, A, B, Const>(N);
2617 }
2618 #[test]
2619 fn test_add() {
2620 super::test_add::<V, A, B, Const>(N);
2621 }
2622 #[test]
2623 fn test_add_plaintext() {
2624 super::test_add_plaintext::<V, A, B, Const>(N);
2625 }
2626 #[test]
2627 fn test_mul_constant() {
2628 super::test_mul_constant::<V, A, B, Const>(N);
2629 }
2630 #[test]
2631 fn test_sub() {
2632 super::test_sub::<V, A, B, Const>(N);
2633 }
2634 #[test]
2635 fn test_neg() {
2636 super::test_neg::<V, A, B, Const>(N);
2637 }
2638 #[test]
2639 fn test_conditional_select() {
2640 super::test_conditional_select::<V, A, B, Const>(N);
2641 }
2642 #[test]
2643 fn test_ct_eq() {
2644 super::test_ct_eq::<V, A, B, Const>(N);
2645 }
2646
2647 type MDiv2 = <U12 as Div<U2>>::Output;
2650 type MDiv3 = <U12 as Div<U3>>::Output;
2651
2652 #[test]
2653 fn test_split_halves() {
2654 super::test_split_halves::<IV, A, IB, M, MDiv2>(N);
2655 }
2656 #[test]
2657 fn test_split_thirds() {
2658 super::test_split_thirds::<IV, A, IB, M, MDiv3>(N);
2659 }
2660 #[test]
2661 fn test_into_iter() {
2662 super::test_into_iter::<IV, A, IB, M>(N);
2663 }
2664 #[test]
2665 fn test_from_iterator() {
2666 super::test_from_iterator::<IV, A, IB, M>(N);
2667 }
2668 #[test]
2669 #[should_panic]
2670 fn test_from_iterator_unequal_sizes() {
2671 super::test_from_iterator_unequal_sizes::<IV, A, IB, M>(N);
2672 }
2673 #[test]
2674 fn test_chunks() {
2675 super::test_chunks::<IV, A, IB, M, U4>(N);
2676 }
2677 }
2678}