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