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