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