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