1use std::{
2 fmt::Debug,
3 iter::Sum as IterSum,
4 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5};
6
7use itertools::{enumerate, izip, Itertools};
8use rayon::prelude::IntoParallelIterator;
9use serde::{Deserialize, Serialize};
10use subtle::{Choice, ConstantTimeEq};
11use typenum::{PartialDiv, Prod, Sum, U1, U2, U3};
12use wincode::{SchemaRead, SchemaWrite};
13
14use super::FieldShareKeys;
15use crate::{
16 algebra::{
17 field::{FieldExtension, SubfieldElement},
18 ops::transpose::transpose,
19 },
20 errors::PrimitiveError,
21 izip_eq,
22 random::{CryptoRngCore, Random, RandomWith},
23 sharing::{
24 authenticated::NParties,
25 unauthenticated::AdditiveShares,
26 FieldShare,
27 FieldShareKey,
28 GlobalFieldKey,
29 Reconstructible,
30 VerifiableWith,
31 },
32 types::{
33 heap_array::{FieldElements, SubfieldElements},
34 identifiers::PeerIndex,
35 Batched,
36 CollectAll,
37 ConditionallySelectable,
38 HeapArray,
39 Positive,
40 },
41 utils::IntoExactSizeIterator,
42};
43
44#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize, SchemaRead, SchemaWrite)]
45#[serde(bound = "F: FieldExtension, M: Positive")]
46#[repr(C)]
47pub struct OpenFieldShares<F: FieldExtension, M: Positive> {
48 pub(crate) value: SubfieldElements<F, M>,
49 pub(crate) mac: FieldElements<F, M>,
50}
51
52impl<F: FieldExtension, M: Positive> OpenFieldShares<F, M> {
53 pub fn new(value: SubfieldElements<F, M>, mac: FieldElements<F, M>) -> Self {
54 Self { value, mac }
55 }
56
57 pub fn get_value(&self) -> &SubfieldElements<F, M> {
58 &self.value
59 }
60
61 pub fn get_mac(&self) -> &FieldElements<F, M> {
62 &self.mac
63 }
64}
65
66impl<T: FieldExtension, M: Positive> Debug for OpenFieldShares<T, M> {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.debug_struct(format!("OpenFieldShares<{}>", M::USIZE).as_str())
69 .field("value", &self.value)
70 .field("mac", &self.mac)
71 .finish()
72 }
73}
74
75#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, SchemaRead, SchemaWrite)]
89#[serde(bound = "F: FieldExtension, M: Positive")]
90#[repr(C)]
91pub struct FieldShares<F: FieldExtension, M: Positive> {
92 pub(crate) value: SubfieldElements<F, M>,
94 pub(crate) macs: Box<[FieldElements<F, M>]>,
96 pub(crate) keys: Box<[FieldShareKeys<F, M>]>,
98}
99
100impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
101 pub fn try_new(
102 value: SubfieldElements<F, M>,
103 macs: Box<[FieldElements<F, M>]>,
104 keys: Box<[FieldShareKeys<F, M>]>,
105 ) -> Result<Self, PrimitiveError> {
106 if macs.is_empty() {
107 return Err(PrimitiveError::MinimumLength(2, 0));
108 }
109 if macs.len() != keys.len() {
110 return Err(PrimitiveError::InvalidSize(keys.len(), macs.len()));
111 }
112 Ok(Self { value, macs, keys })
114 }
115
116 fn new(
117 value: SubfieldElements<F, M>,
118 macs: Box<[FieldElements<F, M>]>,
119 keys: Box<[FieldShareKeys<F, M>]>,
120 ) -> Self {
121 Self { value, macs, keys }
122 }
123
124 pub fn get_value(&self) -> &SubfieldElements<F, M> {
125 &self.value
126 }
127
128 pub fn get_value_mut(&mut self) -> &mut SubfieldElements<F, M> {
129 &mut self.value
130 }
131
132 #[inline]
133 pub fn value(self) -> SubfieldElements<F, M> {
134 self.value
135 }
136
137 pub fn get_keys(&self) -> &[FieldShareKeys<F, M>] {
138 &self.keys
139 }
140
141 pub fn get_keys_mut(&mut self) -> &mut [FieldShareKeys<F, M>] {
142 &mut self.keys
143 }
144
145 pub fn get_key(&self, peer: PeerIndex) -> Option<&FieldShareKeys<F, M>> {
146 self.keys.get(peer)
147 }
148
149 pub fn get_macs(&self) -> &[FieldElements<F, M>] {
150 &self.macs
151 }
152
153 pub fn get_mac(&self, index: PeerIndex) -> Option<&FieldElements<F, M>> {
154 self.macs.get(index)
155 }
156
157 pub fn get_alphas(&self) -> impl ExactSizeIterator<Item = GlobalFieldKey<F>> + '_ {
158 self.keys.iter().map(|key| key.get_alpha())
159 }
160
161 pub fn n_parties(&self) -> usize {
162 self.get_macs().len() + 1 }
164
165 pub fn iter(&self) -> FieldSharesIterator<F, M> {
166 self.into_iter()
167 }
168
169 pub fn len(&self) -> usize {
170 self.value.len()
171 }
172
173 pub fn is_empty(&self) -> bool {
174 self.len() == 0
175 }
176}
177
178impl<F: FieldExtension, M: Positive> VerifiableWith for FieldShares<F, M> {
182 type VerificationData = ();
183 #[inline]
185 fn verify_from_peer_with(
186 &self,
187 open_share: &OpenFieldShares<F, M>,
188 peer: PeerIndex,
189 _verification_data: (),
190 ) -> Result<(), PrimitiveError> {
191 self.get_key(peer)
192 .ok_or(PrimitiveError::InvalidPeerIndex(peer, self.keys.len()))?
193 .verify_mac(open_share)
194 .map_err(|e| e.blame(peer))
195 }
196
197 #[inline]
199 fn verify_with(
200 &self,
201 open_shares: &[OpenFieldShares<F, M>],
202 _verification_data: (),
203 ) -> Result<(), PrimitiveError> {
204 enumerate(izip_eq!(open_shares, &self.keys))
205 .map(|(from_peer, (open_share, key))| {
206 key.verify_mac(open_share).map_err(|e| e.blame(from_peer))
207 })
208 .collect_errors()?;
209 Ok(())
210 }
211}
212
213impl<F: FieldExtension, M: Positive> Reconstructible for FieldShares<F, M> {
218 type Opening = OpenFieldShares<F, M>;
219 type Secret = SubfieldElements<F, M>;
220
221 fn open_to(&self, for_peer: PeerIndex) -> Result<OpenFieldShares<F, M>, PrimitiveError> {
223 let mac = self
224 .get_mac(for_peer)
225 .ok_or(PrimitiveError::InvalidPeerIndex(for_peer, self.macs.len()))?
226 .to_owned();
227 Ok(OpenFieldShares::new(self.get_value().to_owned(), mac))
228 }
229
230 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenFieldShares<F, M>> {
232 self.get_macs()
233 .iter()
234 .map(|mac| OpenFieldShares::new(self.get_value().to_owned(), mac.to_owned()))
235 }
236
237 fn reconstruct(
239 &self,
240 openings: &[OpenFieldShares<F, M>],
241 ) -> Result<Self::Secret, PrimitiveError> {
242 if openings.len() != self.get_keys().len() {
243 return Err(PrimitiveError::InvalidSize(
244 self.get_keys().len(),
245 openings.len(),
246 ));
247 }
248 self.verify_with(openings, ())?;
249 Ok(openings
250 .iter()
251 .fold(self.get_value().to_owned(), |acc, open_share| {
252 acc + open_share.get_value()
253 }))
254 }
255}
256
257impl<F: FieldExtension, M: Positive, N: Positive> Reconstructible
258 for HeapArray<FieldShares<F, M>, N>
259{
260 type Opening = HeapArray<OpenFieldShares<F, M>, N>;
261 type Secret = HeapArray<SubfieldElements<F, M>, N>;
262
263 fn open_to(&self, for_peer: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
265 self.into_iter()
266 .map(|s| s.open_to(for_peer))
267 .collect::<Result<_, _>>()
268 }
269
270 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
272 let openings = self
273 .into_iter()
274 .map(|s| s.open_to_all_others().collect::<Vec<_>>())
275 .collect::<Vec<Vec<OpenFieldShares<_, _>>>>();
276 transpose(openings)
277 .into_iter()
278 .map(|o| o.try_into().unwrap())
279 }
280
281 fn reconstruct(&self, openings: &[Self::Opening]) -> Result<Self::Secret, PrimitiveError> {
283 self.iter()
285 .enumerate()
286 .map(|(i, share)| {
287 let my_openings: Vec<_> = openings
288 .iter()
289 .map(|opening: &HeapArray<OpenFieldShares<F, M>, N>| opening.get(i).cloned())
290 .collect::<Option<Vec<_>>>()
291 .ok_or_else(|| {
292 PrimitiveError::InvalidParameters(
293 "Opening is missing for some share.".to_string(),
294 )
295 })?;
296 share.reconstruct(my_openings.as_slice())
297 })
298 .collect::<Result<Self::Secret, PrimitiveError>>()
299 }
300}
301
302fn compute_macs<F: FieldExtension, M: Positive>(
307 all_unauth_shares: &[SubfieldElements<F, M>],
308 all_keys: &[Box<[FieldShareKeys<F, M>]>],
309) -> Vec<Box<[FieldElements<F, M>]>> {
310 let mut all_key_iters = all_keys.iter().map(|k| k.iter()).collect::<Vec<_>>();
311 enumerate(all_unauth_shares.iter())
312 .map(|(i, my_unauth_share)| {
313 enumerate(all_key_iters.iter_mut())
314 .filter(|(j, _)| *j != i)
315 .map(|(_, keys_iter)| keys_iter.next().unwrap().compute_mac(my_unauth_share))
316 .collect()
317 })
318 .collect()
319}
320
321impl<F: FieldExtension, M: Positive> Random for FieldShares<F, M> {
322 fn random(_rng: impl CryptoRngCore) -> Self {
323 unimplemented!(
324 "Type {} does not support `random` since it needs to know `n_parties`. Use `random_with(..., n_parties)` instead.",
325 std::any::type_name::<Self>()
326 )
327 }
328
329 fn random_n<Container: FromIterator<Self>>(
331 mut rng: impl CryptoRngCore,
332 n_parties: NParties,
333 ) -> Container {
334 let all_unauth_shares: Vec<_> = SubfieldElements::random_n(&mut rng, n_parties);
335 let all_keys = (0..n_parties)
336 .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
337 .collect::<Vec<_>>();
338 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
339 izip_eq!(all_unauth_shares, all_macs, all_keys)
340 .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
341 .collect()
342 }
343}
344
345impl<F: FieldExtension, M: Positive> RandomWith<NParties> for FieldShares<F, M> {
346 fn random_with(mut rng: impl CryptoRngCore, n_parties: NParties) -> Self {
348 FieldShares::new(
349 SubfieldElements::<F, M>::random(&mut rng),
350 FieldElements::<F, M>::random_n(&mut rng, n_parties - 1),
351 FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1),
352 )
353 }
354}
355
356impl<F: FieldExtension, M: Positive> RandomWith<(NParties, SubfieldElements<F, M>)>
357 for FieldShares<F, M>
358{
359 fn random_with(
361 mut rng: impl CryptoRngCore,
362 n_parties_value: (NParties, SubfieldElements<F, M>),
363 ) -> Self {
364 let (n_parties, value) = n_parties_value;
365 FieldShares::new(
366 value,
367 FieldElements::<F, M>::random_n(&mut rng, n_parties - 1),
368 FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1),
369 )
370 }
371}
372
373impl<F: FieldExtension, M: Positive> RandomWith<SubfieldElements<F, M>> for FieldShares<F, M> {
374 fn random_with(_rng: impl CryptoRngCore, _data: SubfieldElements<F, M>) -> Self {
375 unimplemented!(
376 "Type {} does not support `random_with` since it needs to know `n_parties`. Use `random_n_with` instead.",
377 std::any::type_name::<Self>()
378 )
379 }
380
381 fn random_n_with<Container: FromIterator<Self>>(
384 mut rng: impl CryptoRngCore,
385 n_parties: usize,
386 value: SubfieldElements<F, M>,
387 ) -> Container {
388 let all_unauth_shares = value.to_additive_shares(n_parties, &mut rng);
389 let all_keys = (0..n_parties)
390 .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
391 .collect::<Vec<_>>();
392 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
393 izip_eq!(all_unauth_shares, all_macs, all_keys)
394 .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
395 .collect()
396 }
397
398 fn random_n_with_each<Container: FromIterator<Self>>(
401 mut rng: impl CryptoRngCore,
402 unauth_shares: impl IntoExactSizeIterator<Item = SubfieldElements<F, M>>,
403 ) -> Container {
404 let all_unauth_shares = unauth_shares.into_iter().collect::<Vec<_>>();
405 let n_parties = all_unauth_shares.len();
406 let all_keys = (0..n_parties)
407 .map(|_| FieldShareKeys::<F, M>::random_n(&mut rng, n_parties - 1))
408 .collect::<Vec<_>>();
409 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
410 izip_eq!(all_unauth_shares, all_macs, all_keys)
411 .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
412 .collect()
413 }
414}
415
416impl<F: FieldExtension, M: Positive> RandomWith<Vec<GlobalFieldKey<F>>> for FieldShares<F, M> {
417 fn random_with(mut rng: impl CryptoRngCore, alphas: Vec<GlobalFieldKey<F>>) -> Self {
419 let n_other_parties = alphas.len();
420 FieldShares::new(
421 SubfieldElements::random(&mut rng),
422 FieldElements::<F, M>::random_n(&mut rng, n_other_parties),
423 FieldShareKeys::<F, M>::random_n_with_each(&mut rng, alphas),
424 )
425 }
426
427 fn random_n_with_each<Container: FromIterator<Self>>(
429 mut rng: impl CryptoRngCore,
430 all_alphas: impl IntoExactSizeIterator<Item = Vec<GlobalFieldKey<F>>>,
431 ) -> Container {
432 let all_alphas = all_alphas.into_iter();
433 let all_unauth_shares: Vec<_> = SubfieldElements::random_n(&mut rng, all_alphas.len());
434 let all_keys = all_alphas
435 .into_iter()
436 .map(|my_alphas| FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas))
437 .collect::<Vec<_>>();
438 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
439 izip_eq!(all_unauth_shares, all_macs, all_keys)
440 .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
441 .collect()
442 }
443}
444
445impl<F: FieldExtension, M: Positive> RandomWith<(SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>)>
446 for FieldShares<F, M>
447{
448 fn random_with(
450 mut rng: impl CryptoRngCore,
451 value_alphas: (SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>),
452 ) -> Self {
453 let (value, alphas) = value_alphas;
454 let n_other_parties = alphas.len();
455 FieldShares::new(
456 value,
457 FieldElements::<F, M>::random_n(&mut rng, n_other_parties),
458 FieldShareKeys::<F, M>::random_n_with_each(&mut rng, alphas),
459 )
460 }
461
462 fn random_n_with_each<Container: FromIterator<Self>>(
464 mut rng: impl CryptoRngCore,
465 unauth_shares_and_alphas: impl IntoIterator<
466 Item = (SubfieldElements<F, M>, Vec<GlobalFieldKey<F>>),
467 >,
468 ) -> Container {
469 let (all_unauth_shares, all_keys): (Vec<_>, Vec<_>) = unauth_shares_and_alphas
470 .into_iter()
471 .map(|(value, my_alphas)| {
472 (
473 value,
474 FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas),
475 )
476 })
477 .unzip();
478 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
479 izip_eq!(all_unauth_shares, all_macs, all_keys)
480 .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
481 .collect()
482 }
483}
484
485impl<F: FieldExtension, M: Positive>
486 RandomWith<(SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>)> for FieldShares<F, M>
487{
488 fn random_with(
489 _rng: impl CryptoRngCore,
490 _data: (SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>),
491 ) -> Self {
492 unimplemented!(
493 "Cannot discern what alpha/global key to use for this peer. Use `random_n_with` instead."
494 );
495 }
496
497 fn random_n_with<Container: FromIterator<Self>>(
500 mut rng: impl CryptoRngCore,
501 n_parties: usize,
502 secret_value_and_alphas: (SubfieldElements<F, M>, Vec<Vec<GlobalFieldKey<F>>>),
503 ) -> Container {
504 let (secret_value, all_alphas) = secret_value_and_alphas;
505 assert_eq!(
506 all_alphas.len(),
507 n_parties,
508 "Number of alphas must match the number of parties"
509 );
510 let all_unauth_shares = secret_value.to_additive_shares(all_alphas.len(), &mut rng);
511 let all_keys = all_alphas
512 .into_iter()
513 .map(|my_alphas| FieldShareKeys::<F, M>::random_n_with_each(&mut rng, my_alphas))
514 .collect::<Vec<_>>();
515 let all_macs = compute_macs(&all_unauth_shares, &all_keys);
516 izip_eq!(all_unauth_shares, all_macs, all_keys)
517 .map(|(value, macs, keys)| FieldShares::new(value, macs, keys))
518 .collect()
519 }
520}
521
522#[macros::op_variants(owned, borrowed, flipped_commutative)]
529impl<'a, F: FieldExtension, M: Positive> Add<&'a FieldShares<F, M>> for FieldShares<F, M> {
530 type Output = FieldShares<F, M>;
531
532 #[inline]
533 fn add(mut self, other: &'a FieldShares<F, M>) -> Self::Output {
534 self.value += &other.value;
535 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
536 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
537 self
538 }
539}
540
541#[macros::op_variants(owned)]
542impl<'a, F: FieldExtension, M: Positive> AddAssign<&'a FieldShares<F, M>> for FieldShares<F, M> {
543 #[inline]
544 fn add_assign(&mut self, other: &'a FieldShares<F, M>) {
545 self.value += &other.value;
546 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i += mac_j);
547 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i += key_j);
548 }
549}
550
551#[macros::op_variants(owned, borrowed, flipped)]
554impl<'a, F: FieldExtension, M: Positive> Sub<&'a FieldShares<F, M>> for FieldShares<F, M> {
555 type Output = FieldShares<F, M>;
556
557 #[inline]
558 fn sub(mut self, other: &'a FieldShares<F, M>) -> Self::Output {
559 self.value -= &other.value;
560 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
561 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
562 self
563 }
564}
565
566#[macros::op_variants(owned)]
567impl<'a, F: FieldExtension, M: Positive> SubAssign<&'a FieldShares<F, M>> for FieldShares<F, M> {
568 #[inline]
569 fn sub_assign(&mut self, other: &'a FieldShares<F, M>) {
570 self.value -= &other.value;
571 izip_eq!(&mut self.macs, &other.macs).for_each(|(mac_i, mac_j)| *mac_i -= mac_j);
572 izip_eq!(&mut self.keys, &other.keys).for_each(|(key_i, key_j)| *key_i -= key_j);
573 }
574}
575
576#[macros::op_variants(owned, borrowed, flipped)]
579impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElement<F>> for FieldShares<F, M> {
580 type Output = FieldShares<F, M>;
581
582 #[inline]
583 fn mul(mut self, other: &'a SubfieldElement<F>) -> FieldShares<F, M> {
584 self.value *= other;
585 izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
586 izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
587 self
588 }
589}
590
591#[macros::op_variants(owned, borrowed, flipped)]
592impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElements<F, M>> for FieldShares<F, M> {
593 type Output = FieldShares<F, M>;
594
595 #[inline]
596 fn mul(mut self, other: &'a SubfieldElements<F, M>) -> FieldShares<F, M> {
597 self.value *= other;
598 izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
599 izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
600 self
601 }
602}
603
604#[macros::op_variants(owned)]
607impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElement<F>> for FieldShares<F, M> {
608 #[inline]
609 fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
610 self.value *= other;
611 izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
612 izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
613 }
614}
615
616#[macros::op_variants(owned)]
617impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElements<F, M>>
618 for FieldShares<F, M>
619{
620 #[inline]
621 fn mul_assign(&mut self, other: &'a SubfieldElements<F, M>) {
622 self.value *= other;
623 izip_eq!(&mut self.macs).for_each(|mac_i| *mac_i *= other);
624 izip_eq!(&mut self.keys).for_each(|key_i| *key_i *= other);
625 }
626}
627
628#[macros::op_variants(borrowed)]
631impl<F: FieldExtension, M: Positive> Neg for FieldShares<F, M> {
632 type Output = FieldShares<F, M>;
633
634 #[inline]
635 fn neg(self) -> Self::Output {
636 FieldShares {
637 value: -self.value,
638 macs: izip_eq!(&self.macs).map(|mac_i| -mac_i).collect(),
639 keys: izip_eq!(&self.keys).map(|key_i| -key_i).collect(),
640 }
641 }
642}
643
644impl<F: FieldExtension, M: Positive> IterSum for FieldShares<F, M> {
647 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
648 let first = iter.next().unwrap_or_default();
649 iter.fold(first, |acc, x| acc + x)
650 }
651}
652
653impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
656 #[inline]
659 pub fn add_secret_owned(
660 mut self,
661 constant: &SubfieldElements<F, M>,
662 is_peer_zero: bool,
663 ) -> Self {
664 if is_peer_zero {
665 self.value += constant;
666 } else {
667 let key0 = self.keys.get_mut(0).expect("Missing key 0");
668 key0.betas -= constant.clone() * *key0.alpha;
669 }
670 self
671 }
672
673 #[inline]
676 pub fn add_secret(&self, constant: &SubfieldElements<F, M>, is_peer_zero: bool) -> Self {
677 let result = self.clone();
678 result.add_secret_owned(constant, is_peer_zero)
679 }
680
681 #[inline]
685 pub fn sub_constant_array_owned(
686 mut self,
687 arr: &SubfieldElements<F, M>,
688 is_peer_zero: bool,
689 ) -> Self {
690 if is_peer_zero {
691 self.value -= arr;
692 } else {
693 let key0 = self.keys.get_mut(0).expect("Missing key 0");
694 let alpha = *key0.alpha;
695 izip_eq!(&mut key0.betas, arr).for_each(|(beta, val)| *beta += alpha * val);
696 }
697 self
698 }
699}
700
701impl<F: FieldExtension, M: Positive> ConditionallySelectable for FieldShares<F, M> {
704 #[inline]
705 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
706 FieldShares {
707 value: HeapArray::conditional_select(&a.value, &b.value, choice),
708 macs: izip_eq!(&a.macs, &b.macs)
709 .map(|(a_mac, b_mac)| HeapArray::conditional_select(a_mac, b_mac, choice))
710 .collect::<Vec<_>>()
711 .into(),
712 keys: izip_eq!(&a.keys, &b.keys)
713 .map(|(a_key, b_key)| FieldShareKeys::conditional_select(a_key, b_key, choice))
714 .collect::<Vec<_>>()
715 .into(),
716 }
717 }
718}
719
720impl<F: FieldExtension, M: Positive> ConstantTimeEq for FieldShares<F, M> {
721 #[inline]
722 fn ct_eq(&self, other: &Self) -> Choice {
723 self.value.ct_eq(&other.value) & self.keys.ct_eq(&other.keys) & self.macs.ct_eq(&other.macs)
724 }
725}
726
727impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
730 pub fn dot_product(&self, other: &SubfieldElements<F, M>) -> FieldShare<F> {
732 FieldShare {
733 value: izip_eq!(&self.value, other)
734 .map(|(value_i, other_i)| *value_i * other_i)
735 .sum(),
736 macs: izip_eq!(&self.macs)
737 .map(|mac_i| {
738 izip_eq!(mac_i, other)
739 .map(|(mac_ij, other_i)| *mac_ij * other_i)
740 .sum()
741 })
742 .collect(),
743 keys: izip_eq!(&self.keys)
744 .map(|key_i| {
745 let beta = izip_eq!(&key_i.betas, other)
746 .map(|(key_ij, other_i)| key_ij * other_i)
747 .sum();
748 FieldShareKey {
749 alpha: key_i.alpha.clone(),
750 beta,
751 }
752 })
753 .collect(),
754 }
755 }
756}
757
758impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
763 pub fn split<M1, M2>(self) -> (FieldShares<F, M1>, FieldShares<F, M2>)
765 where
766 M1: Positive,
767 M2: Positive + Add<M1, Output = M>,
768 {
769 let FieldShares { value, macs, keys } = self;
770
771 let (value1, value2) = value.split::<M1, M2>();
772 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
773 .into_vec()
774 .into_iter()
775 .map(|mac| mac.split::<M1, M2>())
776 .collect();
777
778 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
779 .into_vec()
780 .into_iter()
781 .map(|key| key.split::<M1, M2>())
782 .collect();
783
784 (
785 FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
786 FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
787 )
788 }
789
790 pub fn split_halves<MDiv2>(self) -> (FieldShares<F, MDiv2>, FieldShares<F, MDiv2>)
792 where
793 MDiv2: Positive + Mul<U2, Output = M>,
794 {
795 let FieldShares { value, macs, keys } = self;
796
797 let (value1, value2) = value.split_halves::<MDiv2>();
798 let (macs1, macs2): (Vec<_>, Vec<_>) = macs
799 .into_vec()
800 .into_iter()
801 .map(|mac| mac.split_halves::<MDiv2>())
802 .collect();
803
804 let (keys1, keys2): (Vec<_>, Vec<_>) = keys
805 .into_vec()
806 .into_iter()
807 .map(|key| key.split_halves::<MDiv2>())
808 .collect();
809
810 (
811 FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
812 FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
813 )
814 }
815
816 pub fn merge_halves(this: Self, other: Self) -> FieldShares<F, Prod<M, U2>>
818 where
819 M: Positive + Mul<U2, Output: Positive>,
820 {
821 let FieldShares { value, macs, keys } = this;
822 let FieldShares {
823 value: other_value,
824 macs: other_macs,
825 keys: other_keys,
826 } = other;
827
828 let value = SubfieldElements::merge_halves(value, other_value);
829 let macs = izip_eq!(macs, other_macs)
830 .map(|(mac, other_mac)| FieldElements::merge_halves(mac, other_mac))
831 .collect::<Vec<_>>();
832 let keys = izip_eq!(keys, other_keys)
833 .map(|(key, other_key)| FieldShareKeys::merge_halves(key, other_key))
834 .collect::<Vec<_>>();
835
836 FieldShares::try_new(value, macs.into(), keys.into()).unwrap()
837 }
838
839 pub fn split3<M1, M2, M3>(self) -> (FieldShares<F, M1>, FieldShares<F, M2>, FieldShares<F, M3>)
841 where
842 M1: Positive,
843 M2: Positive + Add<M1>,
844 M3: Positive + Add<Sum<M2, M1>, Output = M>,
845 {
846 let FieldShares { value, macs, keys } = self;
847
848 let (value1, value2, value3) = value.split3::<M1, M2, M3>();
849 let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
850 .into_vec()
851 .into_iter()
852 .map(|mac| mac.split3::<M1, M2, M3>())
853 .multiunzip();
854
855 let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
856 .into_vec()
857 .into_iter()
858 .map(|key| key.split3::<M1, M2, M3>())
859 .multiunzip();
860
861 (
862 FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
863 FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
864 FieldShares::try_new(value3, macs3.into(), keys3.into()).unwrap(),
865 )
866 }
867
868 pub fn split_thirds<MDiv3>(
870 self,
871 ) -> (
872 FieldShares<F, MDiv3>,
873 FieldShares<F, MDiv3>,
874 FieldShares<F, MDiv3>,
875 )
876 where
877 MDiv3: Positive + Mul<U3, Output = M>,
878 {
879 let FieldShares { value, macs, keys } = self;
880
881 let (value1, value2, value3) = value.split_thirds::<MDiv3>();
882 let (macs1, macs2, macs3): (Vec<_>, Vec<_>, Vec<_>) = macs
883 .into_vec()
884 .into_iter()
885 .map(|mac| mac.split_thirds::<MDiv3>())
886 .multiunzip();
887
888 let (keys1, keys2, keys3): (Vec<_>, Vec<_>, Vec<_>) = keys
889 .into_vec()
890 .into_iter()
891 .map(|key| key.split_thirds::<MDiv3>())
892 .multiunzip();
893
894 (
895 FieldShares::try_new(value1, macs1.into(), keys1.into()).unwrap(),
896 FieldShares::try_new(value2, macs2.into(), keys2.into()).unwrap(),
897 FieldShares::try_new(value3, macs3.into(), keys3.into()).unwrap(),
898 )
899 }
900
901 pub fn merge_thirds(this: Self, other1: Self, other2: Self) -> FieldShares<F, Prod<M, U3>>
903 where
904 M: Positive + Mul<U3, Output: Positive>,
905 {
906 let FieldShares {
907 value: v1,
908 macs: m1,
909 keys: k1,
910 } = this;
911 let FieldShares {
912 value: v2,
913 macs: m2,
914 keys: k2,
915 } = other1;
916 let FieldShares {
917 value: v3,
918 macs: m3,
919 keys: k3,
920 } = other2;
921
922 let value = SubfieldElements::merge_thirds(v1, v2, v3);
923 let macs = izip_eq!(m1, m2, m3)
924 .map(|(mac1, mac2, mac3)| FieldElements::merge_thirds(mac1, mac2, mac3))
925 .collect::<Vec<_>>();
926 let keys = izip_eq!(k1, k2, k3)
927 .map(|(key1, key2, key3)| FieldShareKeys::merge_thirds(key1, key2, key3))
928 .collect::<Vec<_>>();
929
930 FieldShares::try_new(value, macs.into(), keys.into()).unwrap()
931 }
932}
933
934impl<F: FieldExtension> From<FieldShare<F>> for FieldShares<F, U1> {
941 fn from(share: FieldShare<F>) -> Self {
942 FieldShares {
943 value: HeapArray::from(share.value),
944 macs: share
945 .macs
946 .into_vec()
947 .into_iter()
948 .map(HeapArray::from)
949 .collect(),
950 keys: share
951 .keys
952 .into_vec()
953 .into_iter()
954 .map(FieldShareKeys::from)
955 .collect(),
956 }
957 }
958}
959
960impl<F: FieldExtension, M: Positive> From<HeapArray<FieldShare<F>, M>> for FieldShares<F, M> {
963 fn from(shares: HeapArray<FieldShare<F>, M>) -> Self {
964 let (values, macs, keys): (Vec<_>, Vec<_>, Vec<_>) = shares
965 .into_iter()
966 .map(|share| (share.value, share.macs, share.keys))
967 .multiunzip();
968 let macs = transpose(macs)
969 .into_iter()
970 .map(HeapArray::from_iter)
971 .collect::<Box<[_]>>();
972 let keys = transpose(keys)
973 .into_iter()
974 .map(|peer_keys| {
975 let alpha = peer_keys[0].get_alpha();
976 let betas = peer_keys
977 .into_iter()
978 .map(|key| {
979 let FieldShareKey { alpha: _, beta } = key;
980 beta
981 })
982 .collect::<HeapArray<_, M>>();
983 FieldShareKeys::new(alpha, betas)
984 })
985 .collect::<Box<[_]>>();
986
987 FieldShares {
988 value: HeapArray::from_iter(values),
989 macs,
990 keys,
991 }
992 }
993}
994
995type SubfieldElementsIterator<F, M> = <SubfieldElements<F, M> as IntoIterator>::IntoIter;
998type FieldElementsIterator<F, M> = <FieldElements<F, M> as IntoIterator>::IntoIter;
999
1000#[derive(Default, Clone, Debug)]
1001pub struct FieldSharesIterator<F: FieldExtension, M: Positive> {
1002 index: usize,
1003
1004 value: SubfieldElementsIterator<F, M>,
1005 macs: Vec<FieldElementsIterator<F, M>>,
1006 betas: Vec<FieldElementsIterator<F, M>>,
1007 alphas: Vec<GlobalFieldKey<F>>,
1008}
1009
1010impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldSharesIterator<F, M> {
1011 fn len(&self) -> usize {
1012 M::to_usize() - self.index
1013 }
1014}
1015
1016impl<F: FieldExtension, M: Positive> Iterator for FieldSharesIterator<F, M> {
1017 type Item = FieldShare<F>;
1018
1019 fn next(&mut self) -> Option<Self::Item> {
1020 if self.index < M::to_usize() {
1021 let value = self.value.next()?;
1022 let macs = self
1023 .macs
1024 .iter_mut()
1025 .map(|mac| mac.next())
1026 .collect::<Option<_>>()?;
1027 let keys = izip!(&mut self.betas, &self.alphas)
1028 .map(|(beta, alpha)| {
1029 beta.next().map(|beta| FieldShareKey {
1030 alpha: alpha.clone(),
1031 beta,
1032 })
1033 })
1034 .collect::<Option<_>>()?;
1035 self.index += 1;
1036 Some(FieldShare::new(value, macs, keys))
1037 } else {
1038 None
1039 }
1040 }
1041}
1042
1043impl<F: FieldExtension, M: Positive> IntoIterator for FieldShares<F, M> {
1044 type Item = FieldShare<F>;
1045 type IntoIter = FieldSharesIterator<F, M>;
1046
1047 fn into_iter(self) -> Self::IntoIter {
1048 let FieldShares { value, macs, keys } = self;
1049 let value = value.into_iter();
1050 let macs = macs
1051 .into_vec()
1052 .into_iter()
1053 .map(|mac| mac.into_iter())
1054 .collect();
1055 let (betas, alphas): (Vec<_>, Vec<_>) = keys
1056 .into_vec()
1057 .into_iter()
1058 .map(|key| (key.betas.into_iter(), key.alpha))
1059 .unzip();
1060
1061 FieldSharesIterator {
1062 index: 0,
1063 value,
1064 macs,
1065 betas,
1066 alphas,
1067 }
1068 }
1069}
1070
1071impl<F: FieldExtension, M: Positive> IntoIterator for &FieldShares<F, M> {
1072 type Item = FieldShare<F>;
1073 type IntoIter = FieldSharesIterator<F, M>;
1074
1075 fn into_iter(self) -> Self::IntoIter {
1076 let value = self.value.clone().into_iter();
1077 let macs = self
1078 .macs
1079 .iter()
1080 .map(|mac| mac.clone().into_iter())
1081 .collect();
1082 let (betas, alphas): (Vec<_>, Vec<_>) = self
1083 .keys
1084 .iter()
1085 .map(|key| (key.betas.clone().into_iter(), key.alpha.clone()))
1086 .unzip();
1087
1088 FieldSharesIterator {
1089 index: 0,
1090 value,
1091 macs,
1092 betas,
1093 alphas,
1094 }
1095 }
1096}
1097
1098impl<F: FieldExtension, N: Positive> FromIterator<FieldShare<F>> for FieldShares<F, N> {
1099 fn from_iter<T: IntoIterator<Item = FieldShare<F>>>(iter: T) -> Self {
1100 let (values, macs, keys): (Vec<_>, Vec<_>, Vec<_>) = iter
1101 .into_iter()
1102 .map(|share| (share.value, share.macs, share.keys))
1103 .multiunzip();
1104 let macs = transpose(macs)
1105 .into_iter()
1106 .map(HeapArray::from_iter)
1107 .collect::<Box<[_]>>();
1108 let keys = transpose(keys)
1109 .into_iter()
1110 .map(|peer_keys| {
1111 let alpha = peer_keys[0].get_alpha();
1112 let betas = peer_keys
1113 .into_iter()
1114 .map(|key| {
1115 let FieldShareKey { alpha: _, beta } = key;
1116 beta
1117 })
1118 .collect::<HeapArray<_, N>>();
1119 FieldShareKeys::new(alpha, betas)
1120 })
1121 .collect::<Box<[_]>>();
1122
1123 FieldShares {
1124 value: HeapArray::from_iter(values),
1125 macs,
1126 keys,
1127 }
1128 }
1129}
1130
1131impl<F: FieldExtension, N: Positive> IntoParallelIterator for FieldShares<F, N> {
1132 type Item = FieldShare<F>;
1133 type Iter = rayon::vec::IntoIter<FieldShare<F>>;
1134
1135 fn into_par_iter(self) -> Self::Iter {
1136 self.into_iter().collect::<Vec<_>>().into_par_iter()
1137 }
1138}
1139
1140impl<F: FieldExtension, N: Positive> Batched for FieldShares<F, N> {
1141 type Item = FieldShare<F>;
1142 type Size = N;
1143}
1144
1145pub struct FieldSharesChunks<F: FieldExtension, M: Positive + PartialDiv<CS>, CS: Positive> {
1147 field_shares: FieldSharesIterator<F, M>,
1148 current_chunk: usize,
1149 _chunk_size: std::marker::PhantomData<CS>,
1150}
1151
1152impl<F: FieldExtension, M: Positive + PartialDiv<CS>, CS: Positive> FieldSharesChunks<F, M, CS> {
1153 #[allow(clippy::len_without_is_empty)]
1154 pub fn len(&self) -> usize {
1155 M::USIZE / CS::USIZE - self.current_chunk
1158 }
1159}
1160
1161impl<F: FieldExtension, M: Positive + PartialDiv<CS>, CS: Positive> Iterator
1162 for FieldSharesChunks<F, M, CS>
1163{
1164 type Item = FieldShares<F, CS>;
1165
1166 fn next(&mut self) -> Option<Self::Item> {
1167 if self.current_chunk * CS::to_usize() >= M::to_usize() {
1168 return None;
1169 }
1170
1171 let chunk_shares = self
1172 .field_shares
1173 .by_ref()
1174 .take(CS::to_usize())
1175 .collect::<Vec<_>>();
1176
1177 self.current_chunk += 1;
1178
1179 Some(chunk_shares.into_iter().collect())
1180 }
1181}
1182
1183impl<F: FieldExtension, M: Positive> FieldShares<F, M> {
1184 pub fn chunks<CS: Positive>(&self) -> FieldSharesChunks<F, M, CS>
1187 where
1188 M: PartialDiv<CS>,
1189 {
1190 FieldSharesChunks {
1191 field_shares: self.into_iter(),
1192 current_chunk: 0,
1193 _chunk_size: std::marker::PhantomData,
1194 }
1195 }
1196}
1197
1198#[cfg(test)]
1199mod tests {
1200 use std::ops::Div;
1201
1202 use itertools::enumerate;
1203 use typenum::{Unsigned, U12};
1204
1205 use super::*;
1206 use crate::{
1207 algebra::elliptic_curve::Curve25519Ristretto as C,
1208 random::{self},
1209 sharing::{GlobalScalarKey, ScalarShares, Verifiable},
1210 types::heap_array::curve_arrays::Scalars,
1211 };
1212
1213 pub type M = U12;
1218 pub type Value = Scalars<C, M>;
1219 pub type Constant = Scalars<C, M>;
1220 pub type Share = ScalarShares<C, M>;
1221 pub type GlobalKey = GlobalScalarKey<C>;
1222
1223 pub type Mdiv2 = <M as Div<U2>>::Output;
1225 pub type ShareMdiv2 = ScalarShares<C, Mdiv2>;
1226 pub type Mdiv3 = <M as Div<U3>>::Output;
1227 pub type ShareMdiv3 = ScalarShares<C, Mdiv3>;
1228 pub const N_PARTIES: usize = 3;
1231
1232 #[test]
1233 fn test_open_to() {
1234 let mut rng = random::test_rng();
1235 let local_share = Share::random_with(&mut rng, N_PARTIES);
1236
1237 for i in 0..N_PARTIES - 1 {
1238 let open_share = local_share.open_to(i).unwrap();
1239 assert_eq!(open_share.get_value(), &local_share.value);
1240 assert_eq!(open_share.get_mac(), &local_share.macs[i]);
1241 }
1242 }
1243
1244 #[test]
1245 fn test_random() {
1246 let mut rng = random::test_rng();
1247
1248 let share = Share::random_with(&mut rng, N_PARTIES);
1250 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1251 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1252
1253 let value = &Value::random(&mut rng);
1255 let share_with_value = Share::random_with(&mut rng, (N_PARTIES, value.to_owned()));
1256 assert_eq!(share_with_value.get_value(), value);
1257 assert_eq!(share_with_value.get_macs().len(), N_PARTIES - 1);
1258 assert_eq!(share_with_value.get_keys().len(), N_PARTIES - 1);
1259 }
1260
1261 #[test]
1262 fn test_random_vec_and_reconstruct() {
1263 let mut rng = random::test_rng();
1264
1265 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
1267 assert_eq!(shares.len(), N_PARTIES);
1268 for share in &shares {
1269 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1270 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1271 }
1272 let unauthenticated_shares = shares
1273 .iter()
1274 .map(|s| s.get_value().to_owned())
1275 .collect::<Vec<_>>();
1276 let expected = Value::from_additive_shares(&unauthenticated_shares);
1277 let reconstructed = Share::reconstruct_all(&shares).unwrap();
1278 assert_eq!(reconstructed, expected);
1279
1280 let value = &Value::random(&mut rng);
1282 let shares: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, value.to_owned());
1283 assert_eq!(shares.len(), N_PARTIES);
1284 for share in &shares {
1285 assert_eq!(share.get_macs().len(), N_PARTIES - 1);
1286 assert_eq!(share.get_keys().len(), N_PARTIES - 1);
1287 }
1288 let reconstructed = Share::reconstruct_all(&shares).unwrap();
1289 assert_eq!(reconstructed, value.to_owned());
1290 }
1291
1292 #[test]
1293 fn test_random_vec_with_global_key_and_reconstruct() {
1294 let mut rng = random::test_rng();
1295
1296 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1298 let shares_from_alphas: Vec<_> = Share::random_n_with_each(&mut rng, alphas.clone());
1299 assert_eq!(shares_from_alphas.len(), N_PARTIES);
1300 for (share_a, my_alphas) in izip_eq!(&shares_from_alphas, alphas) {
1301 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1302 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1303 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1304 }
1305 let _ = Share::reconstruct_all(&shares_from_alphas).unwrap(); let value = &Value::random(&mut rng);
1309 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1310 let shares_from_value_and_alphas: Vec<_> =
1311 Share::random_n_with(&mut rng, N_PARTIES, (value.to_owned(), alphas.clone()));
1312 assert_eq!(shares_from_value_and_alphas.len(), N_PARTIES);
1313 for (share_a, my_alphas) in izip_eq!(&shares_from_value_and_alphas, alphas) {
1314 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1315 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1316 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1317 }
1318 let reconstructed = Share::reconstruct_all(&shares_from_value_and_alphas).unwrap();
1319 assert_eq!(&reconstructed, value);
1320
1321 let value = Value::random(&mut rng);
1323 let unauth_shares = value.to_additive_shares(N_PARTIES, &mut rng);
1324 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1325 let shares_from_unauth_and_alphas: Vec<_> =
1326 Share::random_n_with_each(&mut rng, izip_eq!(unauth_shares.clone(), alphas.clone()));
1327 assert_eq!(shares_from_unauth_and_alphas.len(), N_PARTIES);
1328 for (share_a, my_alphas) in izip_eq!(&shares_from_unauth_and_alphas, alphas) {
1329 assert_eq!(share_a.get_macs().len(), N_PARTIES - 1);
1330 assert_eq!(share_a.get_keys().len(), N_PARTIES - 1);
1331 assert_eq!(share_a.get_alphas().collect::<Vec<_>>(), my_alphas);
1332 }
1333 let reconstructed = Share::reconstruct_all(&shares_from_unauth_and_alphas).unwrap();
1334 assert_eq!(reconstructed, value);
1335 }
1336
1337 #[test]
1338 fn test_verify_mac() {
1339 let mut rng = random::test_rng();
1340
1341 let shares: Vec<_> = Share::random_n(&mut rng, N_PARTIES);
1342
1343 enumerate(shares.iter()).for_each(|(i, s_i)| {
1345 enumerate(shares.iter())
1346 .filter(|(j, _)| i != *j)
1347 .for_each(|(j, s_j)| {
1348 let open_share = s_j.open_to(i - (i > j) as usize).unwrap();
1349 s_i.verify_from(&open_share, j - (j > i) as usize).unwrap();
1350 });
1351 });
1352
1353 Share::verify_all(&shares).unwrap();
1355 }
1356
1357 #[test]
1358 fn test_add() {
1359 let mut rng = random::test_rng();
1360
1361 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1362 let a = &Value::random(&mut rng);
1363 let b = &Value::random(&mut rng);
1364
1365 let shares_a: Vec<_> =
1366 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
1367 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
1368
1369 let shares_a_ref_plus_b_ref = izip_eq!(&shares_a, &shares_b)
1371 .map(|(share_a, share_b)| share_a + share_b)
1372 .collect::<Vec<_>>();
1373 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b_ref).unwrap();
1374 assert_eq!(reconstructed, a + b);
1375
1376 let shares_a_ref_plus_b = izip_eq!(&shares_a, shares_b.clone())
1378 .map(|(share_a, share_b)| share_a + share_b)
1379 .collect::<Vec<_>>();
1380 let reconstructed = Share::reconstruct_all(&shares_a_ref_plus_b).unwrap();
1381 assert_eq!(reconstructed, a + b);
1382
1383 let shares_a_plus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
1385 .map(|(share_a, share_b)| share_a + share_b)
1386 .collect::<Vec<_>>();
1387 let reconstructed = Share::reconstruct_all(&shares_a_plus_b_ref).unwrap();
1388 assert_eq!(reconstructed, a + b);
1389
1390 let shares_a_plus_b = izip_eq!(shares_a.clone(), shares_b.clone())
1392 .map(|(share_a, share_b)| share_a + share_b)
1393 .collect::<Vec<_>>();
1394 let reconstructed = Share::reconstruct_all(&shares_a_plus_b).unwrap();
1395 assert_eq!(reconstructed, a + b);
1396
1397 let mut shares_a_add_assign_b_ref = shares_a.clone();
1399 izip_eq!(&mut shares_a_add_assign_b_ref, &shares_b)
1400 .for_each(|(share_a, share_b)| *share_a += share_b);
1401 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b_ref).unwrap();
1402 assert_eq!(reconstructed, a + b);
1403
1404 let mut shares_a_add_assign_b = shares_a.clone();
1406 izip_eq!(&mut shares_a_add_assign_b, shares_b)
1407 .for_each(|(share_a, share_b)| *share_a += share_b);
1408 let reconstructed = Share::reconstruct_all(&shares_a_add_assign_b).unwrap();
1409 assert_eq!(reconstructed, a + b);
1410 }
1411
1412 #[test]
1413 fn test_add_secret() {
1414 let mut rng = random::test_rng();
1415
1416 let a = &Value::random(&mut rng);
1417 let k = &Value::random(&mut rng);
1418
1419 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1420
1421 let shares_a_plus_k_ref = enumerate(shares_a.iter())
1423 .map(|(i, share_a)| share_a.add_secret(k, i == 0))
1424 .collect::<Vec<_>>();
1425 let reconstructed = Share::reconstruct_all(&shares_a_plus_k_ref).unwrap();
1426 assert_eq!(reconstructed, a + k);
1427
1428 let shares_a_plus_k = enumerate(shares_a)
1430 .map(|(i, share_a)| share_a.add_secret_owned(k, i == 0))
1431 .collect::<Vec<_>>();
1432 let reconstructed = Share::reconstruct_all(&shares_a_plus_k).unwrap();
1433 assert_eq!(reconstructed, a + k);
1434 }
1435
1436 #[test]
1437 fn test_mul_constant() {
1438 let mut rng = random::test_rng();
1439
1440 let a = &Value::random(&mut rng);
1441 let k = &Constant::random(&mut rng);
1442
1443 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1444
1445 let shares_a_times_k_ref = izip_eq!(&shares_a)
1447 .map(|share_a| share_a * k.to_owned())
1448 .collect::<Vec<_>>();
1449 let reconstructed = Share::reconstruct_all(&shares_a_times_k_ref).unwrap();
1450 assert_eq!(reconstructed, a.to_owned() * k);
1451
1452 let shares_a_times_k = izip_eq!(shares_a.clone())
1454 .map(|share_a| share_a * k)
1455 .collect::<Vec<_>>();
1456 let reconstructed = Share::reconstruct_all(&shares_a_times_k).unwrap();
1457 assert_eq!(reconstructed, a * k);
1458
1459 let mut shares_a_times_k_assign = shares_a.clone();
1461 izip_eq!(&mut shares_a_times_k_assign).for_each(|share_a| *share_a *= k);
1462 let reconstructed = Share::reconstruct_all(&shares_a_times_k_assign).unwrap();
1463 assert_eq!(reconstructed, a * k);
1464 }
1465
1466 #[test]
1467 fn test_sub() {
1468 let mut rng = random::test_rng();
1469 let alphas = Vec::<Vec<GlobalKey>>::random_with(&mut rng, N_PARTIES);
1470
1471 let a = &Value::random(&mut rng);
1472 let b = &Value::random(&mut rng);
1473
1474 let shares_a: Vec<_> =
1475 Share::random_n_with(&mut rng, N_PARTIES, (a.to_owned(), alphas.clone()));
1476 let shares_b: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, (b.to_owned(), alphas));
1477
1478 let shares_a_ref_minus_b_ref = izip_eq!(&shares_a, &shares_b)
1480 .map(|(share_a, share_b)| share_a - share_b)
1481 .collect::<Vec<_>>();
1482
1483 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b_ref).unwrap();
1484 assert_eq!(reconstructed, a - b);
1485
1486 let shares_a_ref_minus_b = izip_eq!(&shares_a, shares_b.clone())
1488 .map(|(share_a, share_b)| share_a - share_b)
1489 .collect::<Vec<_>>();
1490 let reconstructed = Share::reconstruct_all(&shares_a_ref_minus_b).unwrap();
1491 assert_eq!(reconstructed, a - b);
1492
1493 let shares_a_minus_b_ref = izip_eq!(shares_a.clone(), &shares_b)
1495 .map(|(share_a, share_b)| share_a - share_b)
1496 .collect::<Vec<_>>();
1497 let reconstructed = Share::reconstruct_all(&shares_a_minus_b_ref).unwrap();
1498 assert_eq!(reconstructed, a - b);
1499
1500 let shares_a_minus_b = izip_eq!(shares_a.clone(), shares_b.clone())
1502 .map(|(share_a, share_b)| share_a - share_b)
1503 .collect::<Vec<_>>();
1504 let reconstructed = Share::reconstruct_all(&shares_a_minus_b).unwrap();
1505 assert_eq!(reconstructed, a - b);
1506
1507 let mut shares_a_sub_assign_b_ref = shares_a.clone();
1509 izip_eq!(&mut shares_a_sub_assign_b_ref, &shares_b)
1510 .for_each(|(share_a, share_b)| *share_a -= share_b);
1511 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b_ref).unwrap();
1512 assert_eq!(reconstructed, a - b);
1513
1514 let mut shares_a_sub_assign_b = shares_a.clone();
1516 izip_eq!(&mut shares_a_sub_assign_b, shares_b)
1517 .for_each(|(share_a, share_b)| *share_a -= share_b);
1518 let reconstructed = Share::reconstruct_all(&shares_a_sub_assign_b).unwrap();
1519 assert_eq!(reconstructed, a - b);
1520 }
1521
1522 #[test]
1523 fn test_neg() {
1524 let mut rng = random::test_rng();
1525
1526 let a = Value::random(&mut rng);
1527
1528 let shares_a: Vec<_> = Share::random_n_with(&mut rng, N_PARTIES, a.to_owned());
1529
1530 let shares_a_neg_ref = shares_a.iter().map(|share_a| -share_a).collect::<Vec<_>>();
1532 let reconstructed = Share::reconstruct_all(&shares_a_neg_ref).unwrap();
1533 assert_eq!(reconstructed, -a.to_owned());
1534
1535 let shares_a_neg = shares_a
1537 .into_iter()
1538 .map(|share_a| -share_a)
1539 .collect::<Vec<_>>();
1540 let reconstructed = Share::reconstruct_all(&shares_a_neg).unwrap();
1541 assert_eq!(reconstructed, -a.to_owned());
1542 }
1543
1544 #[test]
1545 fn test_conditional_select() {
1546 let mut rng = random::test_rng();
1547
1548 let shares_a = Share::random_with(&mut rng, N_PARTIES);
1549 let shares_b = Share::random_with(&mut rng, N_PARTIES);
1550
1551 let choice = Choice::from(0u8);
1553 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1554 assert_eq!(selected, shares_a);
1555
1556 let choice = Choice::from(1u8);
1558 let selected = Share::conditional_select(&shares_a, &shares_b, choice);
1559 assert_eq!(selected, shares_b);
1560 }
1561
1562 #[test]
1563 fn test_ct_eq() {
1564 let mut rng = random::test_rng();
1565
1566 let shares_a = Share::random_with(&mut rng, N_PARTIES);
1567 let shares_b = Share::random_with(&mut rng, N_PARTIES);
1568
1569 assert!(Into::<bool>::into(shares_a.ct_eq(&shares_a.clone())));
1571 assert!(Into::<bool>::into(shares_b.ct_eq(&shares_b.clone())));
1572 assert!(!Into::<bool>::into(shares_a.ct_eq(&shares_b)));
1573 assert!(!Into::<bool>::into(shares_b.ct_eq(&shares_a)));
1574 }
1575
1576 #[test]
1577 fn test_split_halves() {
1578 let m_div2 = Mdiv2::to_usize();
1579
1580 let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1581
1582 let (shares1, shares2) = shares.clone().split_halves::<Mdiv2>();
1583
1584 assert_eq!(shares1.get_value().len(), m_div2);
1586 assert_eq!(shares2.get_value().len(), m_div2);
1587
1588 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div2]);
1589 assert_eq!(shares2.get_value().as_ref(), &shares.get_value()[m_div2..]);
1590
1591 izip_eq!(&shares1.macs, &shares2.macs, &shares.macs).for_each(|(mac1, mac2, mac)| {
1592 assert_eq!(mac1.as_ref(), &mac[..m_div2]);
1593 assert_eq!(mac2.as_ref(), &mac[m_div2..]);
1594 });
1595 izip_eq!(&shares1.keys, &shares2.keys, &shares.keys).for_each(|(key1, key2, key)| {
1596 assert_eq!(key1.alpha, key.alpha);
1597 assert_eq!(key2.alpha, key.alpha);
1598 assert_eq!(key1.betas.as_ref(), &key.betas[..m_div2]);
1599 assert_eq!(key2.betas.as_ref(), &key.betas[m_div2..]);
1600 });
1601
1602 let merged_shares = ShareMdiv2::merge_halves(shares1, shares2);
1604 assert_eq!(merged_shares, shares);
1605 }
1606
1607 #[test]
1608 fn test_split_thirds() {
1609 let m_div3 = Mdiv3::to_usize();
1610
1611 let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1612
1613 let (shares1, shares2, shares3) = shares.clone().split_thirds::<Mdiv3>();
1614
1615 assert_eq!(shares1.get_value().len(), m_div3);
1617 assert_eq!(shares2.get_value().len(), m_div3);
1618 assert_eq!(shares3.get_value().len(), m_div3);
1619
1620 assert_eq!(shares1.get_value().as_ref(), &shares.get_value()[..m_div3]);
1621 assert_eq!(
1622 shares2.get_value().as_ref(),
1623 &shares.get_value()[m_div3..(2 * m_div3)]
1624 );
1625 assert_eq!(
1626 shares3.get_value().as_ref(),
1627 &shares.get_value()[(2 * m_div3)..]
1628 );
1629
1630 izip_eq!(&shares1.macs, &shares2.macs, &shares3.macs, &shares.macs).for_each(
1631 |(mac1, mac2, mac3, mac)| {
1632 assert_eq!(mac1.as_ref(), &mac[..m_div3]);
1633 assert_eq!(mac2.as_ref(), &mac[m_div3..(2 * m_div3)]);
1634 assert_eq!(mac3.as_ref(), &mac[(2 * m_div3)..(3 * m_div3)]);
1635 },
1636 );
1637
1638 izip_eq!(&shares1.keys, &shares2.keys, &shares3.keys, &shares.keys).for_each(
1639 |(key1, key2, key3, key)| {
1640 assert_eq!(key1.alpha, key.alpha);
1641 assert_eq!(key2.alpha, key.alpha);
1642 assert_eq!(key3.alpha, key.alpha);
1643
1644 assert_eq!(key1.betas.as_ref(), &key.betas[..m_div3]);
1645 assert_eq!(key2.betas.as_ref(), &key.betas[m_div3..(2 * m_div3)]);
1646 assert_eq!(key3.betas.as_ref(), &key.betas[(2 * m_div3)..(3 * m_div3)]);
1647 },
1648 );
1649
1650 let merged_shares = ShareMdiv3::merge_thirds(shares1, shares2, shares3);
1652 assert_eq!(merged_shares, shares);
1653 }
1654
1655 #[test]
1656 fn test_into_iter() {
1657 let m = M::to_usize();
1658
1659 let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1660
1661 let mut iter = shares.clone().into_iter();
1662 assert_eq!(iter.len(), m);
1663
1664 for i in 0..m {
1665 assert_eq!(iter.len(), m - i);
1666 let share = iter.next().unwrap();
1667 assert_eq!(share.value, shares.get_value()[i]);
1668
1669 for j in 0..N_PARTIES - 1 {
1670 assert_eq!(share.macs[j], shares.macs[j][i]);
1671 assert_eq!(share.keys[j].alpha, shares.keys[j].alpha);
1672 assert_eq!(share.keys[j].beta, shares.keys[j].betas[i]);
1673 }
1674 }
1675 }
1676
1677 #[test]
1678 fn test_from_iterator() {
1679 let mut rng = random::test_rng();
1680 let shares = Share::random_with(&mut rng, N_PARTIES);
1681
1682 let collected: Vec<_> = shares.clone().into_iter().collect();
1683 let from_iterator: Share = collected.into_iter().collect();
1684
1685 assert_eq!(shares, from_iterator);
1686 }
1687
1688 #[test]
1689 #[should_panic]
1690 fn test_from_iterator_unequal_sizes() {
1691 let mut rng = random::test_rng();
1692 let shares = Share::random_with(&mut rng, N_PARTIES);
1693
1694 let mut collected: Vec<_> = shares.clone().into_iter().collect();
1695 collected.pop(); let _ = collected.into_iter().collect::<Share>();
1697 }
1698
1699 #[test]
1700 fn test_chunks() {
1701 type ChunkSize = typenum::U4;
1702 let m = M::to_usize();
1703 let chunk_size = ChunkSize::to_usize();
1704 let n_chunks = m / chunk_size;
1705
1706 let shares = Share::random_with(&mut random::test_rng(), N_PARTIES);
1707 let mut chunks_iter = shares.chunks::<ChunkSize>();
1708
1709 assert_eq!(chunks_iter.len(), n_chunks);
1710
1711 for i in 0..n_chunks {
1712 assert_eq!(chunks_iter.len(), n_chunks - i);
1714 let chunk = chunks_iter.next().unwrap();
1715 assert_eq!(chunk.value.len(), chunk_size);
1716
1717 for j in 0..chunk_size {
1718 assert_eq!(chunk.value[j], shares.get_value()[i * chunk_size + j]);
1719 }
1720
1721 for (mac_chunk, macs) in izip_eq!(&chunk.macs, &shares.macs) {
1722 for j in 0..chunk_size {
1723 assert_eq!(mac_chunk[j], macs[i * chunk_size + j]);
1724 }
1725 }
1726
1727 for (key_chunk, keys) in izip_eq!(&chunk.keys, &shares.keys) {
1728 assert_eq!(key_chunk.alpha, keys.alpha);
1729 for j in 0..chunk_size {
1730 assert_eq!(key_chunk.betas[j], keys.betas[i * chunk_size + j]);
1731 }
1732 }
1733 }
1734
1735 assert!(chunks_iter.next().is_none());
1736 }
1737}