Skip to main content

primitives/sharing/authenticated/batched/
field_keys.rs

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