1use std::{
2 fmt::Debug,
3 iter::Sum as IterSum,
4 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5};
6
7use serde::{Deserialize, Serialize};
8use subtle::{Choice, ConstantTimeEq};
9use typenum::{Prod, Sum, U1, U2, U3};
10
11use crate::{
12 algebra::field::{FieldElement, FieldExtension, SubfieldElement},
13 errors::{PrimitiveError, VerificationError},
14 izip_eq,
15 random::{CryptoRngCore, Random, RandomWith},
16 sharing::{FieldShareKey, GlobalFieldKey, OpenFieldShares},
17 types::{
18 heap_array::{FieldElements, SubfieldElements},
19 ConditionallySelectable,
20 HeapArray,
21 Positive,
22 },
23};
24
25#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
28#[serde(bound = "F: FieldExtension, M: Positive")]
29pub struct FieldShareKeys<F, M>
30where
31 F: FieldExtension,
32 M: Positive, {
34 pub(crate) alpha: GlobalFieldKey<F>, pub(crate) betas: FieldElements<F, M>, }
37
38impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
39 #[inline]
40 pub fn new(alpha: GlobalFieldKey<F>, betas: FieldElements<F, M>) -> Self {
41 FieldShareKeys { alpha, betas }
42 }
43
44 #[inline]
45 pub fn get_alpha(&self) -> GlobalFieldKey<F> {
46 self.alpha.clone()
47 }
48
49 #[inline]
50 pub fn get_alpha_value(&self) -> FieldElement<F> {
51 *self.alpha
52 }
53
54 #[inline]
55 pub fn get_betas(&self) -> &FieldElements<F, M> {
56 &self.betas
57 }
58
59 #[inline]
62 pub fn compute_mac(&self, values: &SubfieldElements<F, M>) -> FieldElements<F, M> {
63 izip_eq!(&self.betas, values)
64 .map(|(beta, value)| (*self.alpha * value) + beta)
65 .collect()
66 }
67
68 #[inline]
69 pub fn verify_mac(&self, open_share: &OpenFieldShares<F, M>) -> Result<(), PrimitiveError> {
70 let computed_macs = self.compute_mac(&open_share.value);
71 bool::from(computed_macs.ct_eq(&open_share.mac))
72 .then_some(())
73 .ok_or(
74 VerificationError::InvalidMAC(
75 serde_json::to_string(&computed_macs).unwrap(),
76 serde_json::to_string(&open_share.mac).unwrap(),
77 )
78 .into(),
79 )
80 }
81}
82
83impl<T: FieldExtension, M: Positive> Debug for FieldShareKeys<T, M> {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 f.debug_struct(format!("FieldShareKeys<{}>", M::USIZE).as_str())
86 .field("alpha", &self.alpha)
87 .field("betas", &self.betas)
88 .finish()
89 }
90}
91
92impl<F: FieldExtension, M: Positive> Add for FieldShareKeys<F, M> {
99 type Output = FieldShareKeys<F, M>;
100
101 #[inline]
102 fn add(self, other: FieldShareKeys<F, M>) -> Self::Output {
103 assert_eq!(self.alpha, other.alpha);
104 FieldShareKeys {
105 alpha: self.alpha,
106 betas: self.betas + other.betas,
107 }
108 }
109}
110
111impl<F: FieldExtension, M: Positive> Add<&FieldShareKeys<F, M>> for FieldShareKeys<F, M> {
112 type Output = FieldShareKeys<F, M>;
113
114 #[inline]
115 fn add(self, other: &FieldShareKeys<F, M>) -> Self::Output {
116 assert_eq!(self.alpha, other.alpha);
117 FieldShareKeys {
118 alpha: self.alpha,
119 betas: self.betas + &other.betas,
120 }
121 }
122}
123
124impl<F: FieldExtension, M: Positive> Add<FieldShareKeys<F, M>> for &FieldShareKeys<F, M> {
125 type Output = FieldShareKeys<F, M>;
126
127 #[inline]
128 fn add(self, other: FieldShareKeys<F, M>) -> Self::Output {
129 assert_eq!(self.alpha, other.alpha);
130 FieldShareKeys {
131 alpha: other.alpha,
132 betas: other.betas + &self.betas,
133 }
134 }
135}
136
137impl<F: FieldExtension, M: Positive> AddAssign for FieldShareKeys<F, M> {
140 #[inline]
141 fn add_assign(&mut self, other: Self) {
142 assert_eq!(self.alpha, other.alpha);
143 self.betas += other.betas;
144 }
145}
146
147impl<'a, F: FieldExtension, M: Positive> AddAssign<&'a FieldShareKeys<F, M>>
148 for FieldShareKeys<F, M>
149{
150 #[inline]
151 fn add_assign(&mut self, other: &'a FieldShareKeys<F, M>) {
152 assert_eq!(self.alpha, other.alpha);
153 self.betas += &other.betas;
154 }
155}
156
157impl<F: FieldExtension, M: Positive> Sub for FieldShareKeys<F, M> {
160 type Output = FieldShareKeys<F, M>;
161
162 #[inline]
163 fn sub(self, other: FieldShareKeys<F, M>) -> Self::Output {
164 assert_eq!(self.alpha, other.alpha);
165 FieldShareKeys {
166 alpha: self.alpha,
167 betas: self.betas - other.betas,
168 }
169 }
170}
171
172impl<F: FieldExtension, M: Positive> Sub<&FieldShareKeys<F, M>> for FieldShareKeys<F, M> {
173 type Output = FieldShareKeys<F, M>;
174
175 #[inline]
176 fn sub(self, other: &FieldShareKeys<F, M>) -> Self::Output {
177 assert_eq!(self.alpha, other.alpha);
178 FieldShareKeys {
179 alpha: self.alpha,
180 betas: self.betas - &other.betas,
181 }
182 }
183}
184
185impl<F: FieldExtension, M: Positive> Sub<FieldShareKeys<F, M>> for &FieldShareKeys<F, M> {
186 type Output = FieldShareKeys<F, M>;
187
188 #[inline]
189 fn sub(self, other: FieldShareKeys<F, M>) -> Self::Output {
190 assert_eq!(self.alpha, other.alpha);
191 FieldShareKeys {
192 alpha: other.alpha,
193 betas: &self.betas - other.betas,
194 }
195 }
196}
197
198impl<F: FieldExtension, M: Positive> Sub<&FieldShareKeys<F, M>> for &FieldShareKeys<F, M> {
199 type Output = FieldShareKeys<F, M>;
200
201 #[inline]
202 fn sub(self, other: &FieldShareKeys<F, M>) -> Self::Output {
203 assert_eq!(self.alpha, other.alpha);
204 FieldShareKeys {
205 alpha: self.alpha.clone(),
206 betas: &self.betas - &other.betas,
207 }
208 }
209}
210
211impl<F: FieldExtension, M: Positive> SubAssign for FieldShareKeys<F, M> {
214 #[inline]
215 fn sub_assign(&mut self, other: Self) {
216 assert_eq!(self.alpha, other.alpha);
217 self.betas -= other.betas;
218 }
219}
220
221impl<'a, F: FieldExtension, M: Positive> SubAssign<&'a FieldShareKeys<F, M>>
222 for FieldShareKeys<F, M>
223{
224 #[inline]
225 fn sub_assign(&mut self, other: &'a FieldShareKeys<F, M>) {
226 assert_eq!(self.alpha, other.alpha);
227 self.betas -= &other.betas;
228 }
229}
230
231impl<F: FieldExtension, M: Positive> Mul<FieldElements<F, M>> for FieldShareKeys<F, M> {
234 type Output = FieldShareKeys<F, M>;
235
236 #[inline]
237 fn mul(mut self, other: FieldElements<F, M>) -> Self::Output {
238 izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
239 self
240 }
241}
242
243impl<'a, F: FieldExtension, M: Positive> Mul<&'a FieldElements<F, M>> for FieldShareKeys<F, M> {
244 type Output = FieldShareKeys<F, M>;
245
246 #[inline]
247 fn mul(mut self, other: &'a FieldElements<F, M>) -> Self::Output {
248 izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
249 self
250 }
251}
252
253impl<F: FieldExtension, M: Positive> Mul<SubfieldElements<F, M>> for FieldShareKeys<F, M> {
254 type Output = FieldShareKeys<F, M>;
255
256 #[inline]
257 fn mul(mut self, other: SubfieldElements<F, M>) -> Self::Output {
258 izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
259 self
260 }
261}
262
263impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElements<F, M>> for FieldShareKeys<F, M> {
264 type Output = FieldShareKeys<F, M>;
265
266 #[inline]
267 fn mul(mut self, other: &'a SubfieldElements<F, M>) -> Self::Output {
268 izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
269 self
270 }
271}
272
273impl<F: FieldExtension, M: Positive> Mul<FieldElement<F>> for FieldShareKeys<F, M> {
276 type Output = FieldShareKeys<F, M>;
277
278 #[inline]
279 fn mul(self, other: FieldElement<F>) -> Self::Output {
280 FieldShareKeys {
281 betas: self.betas * other,
282 ..self
283 }
284 }
285}
286
287impl<'a, F: FieldExtension, M: Positive> Mul<&'a FieldElement<F>> for FieldShareKeys<F, M> {
288 type Output = FieldShareKeys<F, M>;
289
290 #[inline]
291 fn mul(self, other: &'a FieldElement<F>) -> Self::Output {
292 FieldShareKeys {
293 betas: self.betas * other,
294 ..self
295 }
296 }
297}
298
299impl<F: FieldExtension, M: Positive> Mul<SubfieldElement<F>> for FieldShareKeys<F, M> {
300 type Output = FieldShareKeys<F, M>;
301
302 #[inline]
303 fn mul(self, other: SubfieldElement<F>) -> Self::Output {
304 FieldShareKeys {
305 betas: self.betas * other,
306 ..self
307 }
308 }
309}
310
311impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElement<F>> for FieldShareKeys<F, M> {
312 type Output = FieldShareKeys<F, M>;
313
314 #[inline]
315 fn mul(self, other: &'a SubfieldElement<F>) -> Self::Output {
316 FieldShareKeys {
317 betas: self.betas * other,
318 ..self
319 }
320 }
321}
322
323impl<F: FieldExtension, M: Positive> MulAssign for FieldShareKeys<F, M> {
326 #[inline]
327 fn mul_assign(&mut self, other: Self) {
328 self.betas *= other.betas;
329 }
330}
331
332impl<F: FieldExtension, M: Positive> MulAssign<FieldElement<F>> for FieldShareKeys<F, M> {
333 #[inline]
334 fn mul_assign(&mut self, other: FieldElement<F>) {
335 izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
336 }
337}
338
339impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a FieldElement<F>> for FieldShareKeys<F, M> {
340 #[inline]
341 fn mul_assign(&mut self, other: &'a FieldElement<F>) {
342 izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
343 }
344}
345
346impl<F: FieldExtension, M: Positive> MulAssign<SubfieldElement<F>> for FieldShareKeys<F, M> {
347 #[inline]
348 fn mul_assign(&mut self, other: SubfieldElement<F>) {
349 izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
350 }
351}
352
353impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElement<F>>
354 for FieldShareKeys<F, M>
355{
356 #[inline]
357 fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
358 izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
359 }
360}
361
362impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElements<F, M>>
365 for FieldShareKeys<F, M>
366{
367 #[inline]
368 fn mul_assign(&mut self, other: &'a SubfieldElements<F, M>) {
369 izip_eq!(&mut self.betas, other).for_each(|(beta, other)| *beta *= other);
370 }
371}
372
373impl<F: FieldExtension, M: Positive> Neg for FieldShareKeys<F, M> {
376 type Output = FieldShareKeys<F, M>;
377
378 #[inline]
379 fn neg(self) -> Self::Output {
380 FieldShareKeys {
381 alpha: self.alpha,
382 betas: -self.betas,
383 }
384 }
385}
386
387impl<F: FieldExtension, M: Positive> Neg for &FieldShareKeys<F, M> {
388 type Output = FieldShareKeys<F, M>;
389
390 #[inline]
391 fn neg(self) -> Self::Output {
392 FieldShareKeys {
393 alpha: self.alpha.clone(),
394 betas: -self.betas.clone(),
395 }
396 }
397}
398
399impl<F: FieldExtension, M: Positive> IterSum for FieldShareKeys<F, M> {
401 fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
402 let first = iter.next().unwrap_or_default();
403 iter.fold(first, |acc, x| acc + x)
404 }
405}
406
407impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
410 #[inline]
411 pub fn add_secret_owned(mut self, constant: SubfieldElement<F>) -> Self {
412 self.betas -= *self.alpha * constant;
413 self
414 }
415
416 #[inline]
417 pub fn add_secret(&self, constant: SubfieldElement<F>) -> Self {
418 let mut result = self.clone();
419 result.betas -= *result.alpha * constant;
420 result
421 }
422
423 #[inline]
424 pub fn add_constant_array(&self, constant: SubfieldElements<F, M>) -> Self {
425 let mut result = self.clone();
426 result.betas -= constant
427 .iter()
428 .map(|c| *result.alpha * c)
429 .collect::<FieldElements<F, M>>();
430 result
431 }
432
433 #[inline]
434 pub fn add_constant_array_owned(&mut self, constant: &SubfieldElements<F, M>) {
435 izip_eq!(&mut self.betas, constant).for_each(|(beta, c)| *beta -= *self.alpha * c);
436 }
437}
438
439impl<F: FieldExtension, M: Positive> Random for FieldShareKeys<F, M> {
444 fn random(mut rng: impl CryptoRngCore) -> Self {
445 FieldShareKeys {
446 alpha: GlobalFieldKey::random(&mut rng),
447 betas: FieldElements::random(&mut rng),
448 }
449 }
450}
451
452impl<F: FieldExtension, M: Positive> RandomWith<GlobalFieldKey<F>> for FieldShareKeys<F, M> {
453 fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalFieldKey<F>) -> Self {
455 FieldShareKeys {
456 alpha,
457 betas: FieldElements::random(&mut rng),
458 }
459 }
460}
461
462impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
467 pub fn split<M1, M2>(self) -> (FieldShareKeys<F, M1>, FieldShareKeys<F, M2>)
469 where
470 M1: Positive,
471 M2: Positive + Add<M1, Output = M>,
472 {
473 let FieldShareKeys { alpha, betas } = self;
474
475 let (betas1, betas2) = betas.split::<M1, M2>();
476 (
477 FieldShareKeys::new(alpha.clone(), betas1),
478 FieldShareKeys::new(alpha, betas2),
479 )
480 }
481
482 pub fn split_halves<MDiv2>(self) -> (FieldShareKeys<F, MDiv2>, FieldShareKeys<F, MDiv2>)
484 where
485 MDiv2: Positive + Mul<U2, Output = M>,
486 {
487 let FieldShareKeys { alpha, betas } = self;
488
489 let (betas1, betas2) = betas.split_halves::<MDiv2>();
490 (
491 FieldShareKeys::new(alpha.clone(), betas1),
492 FieldShareKeys::new(alpha, betas2),
493 )
494 }
495
496 pub fn merge_halves(this: Self, other: Self) -> FieldShareKeys<F, Prod<M, U2>>
498 where
499 M: Positive + Mul<U2, Output: Positive>,
500 {
501 assert_eq!(this.alpha, other.alpha);
502 FieldShareKeys {
503 alpha: this.alpha,
504 betas: FieldElements::merge_halves(this.betas, other.betas),
505 }
506 }
507
508 pub fn split3<M1, M2, M3>(
510 self,
511 ) -> (
512 FieldShareKeys<F, M1>,
513 FieldShareKeys<F, M2>,
514 FieldShareKeys<F, M3>,
515 )
516 where
517 M1: Positive,
518 M2: Positive + Add<M1>,
519 M3: Positive + Add<Sum<M2, M1>, Output = M>,
520 {
521 let FieldShareKeys { alpha, betas } = self;
522
523 let (betas1, betas2, betas3) = betas.split3::<M1, M2, M3>();
524 (
525 FieldShareKeys::new(alpha.clone(), betas1),
526 FieldShareKeys::new(alpha.clone(), betas2),
527 FieldShareKeys::new(alpha, betas3),
528 )
529 }
530
531 pub fn split_thirds<MDiv3>(
533 self,
534 ) -> (
535 FieldShareKeys<F, MDiv3>,
536 FieldShareKeys<F, MDiv3>,
537 FieldShareKeys<F, MDiv3>,
538 )
539 where
540 MDiv3: Positive + Mul<U3, Output = M>,
541 {
542 let FieldShareKeys { alpha, betas } = self;
543
544 let (betas1, betas2, betas3) = betas.split_thirds::<MDiv3>();
545 (
546 FieldShareKeys::new(alpha.clone(), betas1),
547 FieldShareKeys::new(alpha.clone(), betas2),
548 FieldShareKeys::new(alpha, betas3),
549 )
550 }
551
552 pub fn merge_thirds(first: Self, second: Self, third: Self) -> FieldShareKeys<F, Prod<M, U3>>
554 where
555 M: Positive + Mul<U3, Output: Positive>,
556 {
557 assert_eq!(first.alpha, second.alpha);
558 assert_eq!(first.alpha, third.alpha);
559 FieldShareKeys {
560 alpha: first.alpha,
561 betas: FieldElements::merge_thirds(first.betas, second.betas, third.betas),
562 }
563 }
564}
565
566impl<F: FieldExtension, M: Positive> ConstantTimeEq for FieldShareKeys<F, M> {
569 #[inline]
570 fn ct_eq(&self, other: &Self) -> Choice {
571 self.alpha.ct_eq(&other.alpha) & self.betas.ct_eq(&other.betas)
572 }
573}
574
575impl<F: FieldExtension, M: Positive> ConditionallySelectable for FieldShareKeys<F, M> {
576 #[inline]
577 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
578 FieldShareKeys {
579 alpha: GlobalFieldKey::conditional_select(&a.alpha, &b.alpha, choice),
580 betas: HeapArray::conditional_select(&a.betas, &b.betas, choice),
581 }
582 }
583}
584
585impl<F: FieldExtension> From<FieldShareKey<F>> for FieldShareKeys<F, U1> {
592 fn from(key: FieldShareKey<F>) -> Self {
593 FieldShareKeys {
594 alpha: key.alpha,
595 betas: HeapArray::from(key.beta),
596 }
597 }
598}
599
600pub struct FieldShareKeysIterator<F, M>
603where
604 F: FieldExtension,
605 M: Positive,
606{
607 keys: FieldShareKeys<F, M>,
608 index: usize,
609}
610
611impl<F: FieldExtension, M: Positive> Iterator for FieldShareKeysIterator<F, M> {
612 type Item = FieldShareKey<F>;
613
614 fn next(&mut self) -> Option<Self::Item> {
615 if self.index < M::to_usize() {
616 let key = FieldShareKey {
617 alpha: self.keys.alpha.clone(),
618 beta: self.keys.betas[self.index],
619 };
620 self.index += 1;
621 Some(key)
622 } else {
623 None
624 }
625 }
626}
627
628impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldShareKeysIterator<F, M> {
629 fn len(&self) -> usize {
630 M::to_usize()
631 }
632}
633
634impl<F: FieldExtension, M: Positive> IntoIterator for FieldShareKeys<F, M> {
635 type Item = FieldShareKey<F>;
636 type IntoIter = FieldShareKeysIterator<F, M>;
637
638 fn into_iter(self) -> Self::IntoIter {
639 FieldShareKeysIterator::<F, M> {
640 keys: self,
641 index: 0,
642 }
643 }
644}
645
646pub struct FieldShareKeyRef<'a, F>
647where
648 F: FieldExtension,
649{
650 pub alpha: GlobalFieldKey<F>,
651 pub beta: &'a FieldElement<F>,
652}
653
654impl<'a, F> From<FieldShareKeyRef<'a, F>> for FieldShareKey<F>
655where
656 F: FieldExtension,
657{
658 fn from(val: FieldShareKeyRef<'a, F>) -> Self {
659 FieldShareKey {
660 alpha: val.alpha,
661 beta: *val.beta,
662 }
663 }
664}
665
666pub struct FieldShareKeysRefIterator<'a, F, M>
667where
668 F: FieldExtension,
669 M: Positive,
670{
671 keys: &'a FieldShareKeys<F, M>,
672 index: usize,
673}
674
675impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldShareKeysRefIterator<'_, F, M> {
676 fn len(&self) -> usize {
677 M::to_usize()
678 }
679}
680
681impl<'a, F: FieldExtension, M: Positive> Iterator for FieldShareKeysRefIterator<'a, F, M> {
682 type Item = FieldShareKeyRef<'a, F>;
683
684 fn next(&mut self) -> Option<Self::Item> {
685 if self.index < M::to_usize() {
686 let key = FieldShareKeyRef {
687 alpha: self.keys.alpha.clone(),
688 beta: &self.keys.betas[self.index],
689 };
690 self.index += 1;
691 Some(key)
692 } else {
693 None
694 }
695 }
696}
697
698impl<'a, F: FieldExtension, M: Positive> IntoIterator for &'a FieldShareKeys<F, M> {
699 type Item = FieldShareKeyRef<'a, F>;
700 type IntoIter = FieldShareKeysRefIterator<'a, F, M>;
701
702 fn into_iter(self) -> Self::IntoIter {
703 FieldShareKeysRefIterator {
704 keys: self,
705 index: 0,
706 }
707 }
708}
709
710#[cfg(test)]
711mod tests {
712 use typenum::U10;
713
714 use super::*;
715 use crate::algebra::elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension};
716
717 pub type FrExt = ScalarAsExtension<C>;
718
719 #[test]
720 fn test_addition() {
721 let alpha = GlobalFieldKey::new(FrExt::from(3u32));
722 let key1 = FieldShareKeys {
723 alpha: alpha.clone(),
724 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
725 };
726 let key2 = FieldShareKeys {
727 alpha: alpha.clone(),
728 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(7u32)),
729 };
730 let expected_result = FieldShareKeys {
731 alpha,
732 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(17u32)),
733 };
734 assert_eq!(key1 + key2, expected_result);
735 }
736
737 #[test]
738 fn test_subtraction() {
739 let alpha = GlobalFieldKey::new(FrExt::from(3u32));
740 let key1 = FieldShareKeys {
741 alpha: alpha.clone(),
742 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
743 };
744 let key2 = FieldShareKeys {
745 alpha: alpha.clone(),
746 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(7u32)),
747 };
748 let expected_result = FieldShareKeys {
749 alpha,
750 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(3u32)),
751 };
752 assert_eq!(key1 - key2, expected_result);
753 }
754
755 #[test]
756 fn test_multiplication() {
757 let alpha = GlobalFieldKey::new(FrExt::from(3u32));
758 let key = FieldShareKeys {
759 alpha: alpha.clone(),
760 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
761 };
762 let scalar = FrExt::from(3u32);
763 let expected_result = FieldShareKeys {
764 alpha,
765 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(30u32)),
766 };
767 assert_eq!(key * scalar, expected_result);
768 }
769
770 #[test]
771 fn test_negation() {
772 let key = FieldShareKeys {
773 alpha: GlobalFieldKey::new(FrExt::from(5u32)),
774 betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
775 };
776 let expected_result = FieldShareKeys {
777 alpha: GlobalFieldKey::new(FrExt::from(5u32)),
778 betas: -HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
779 };
780 assert_eq!(-key, expected_result);
781 }
782}