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};
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// α and β, such that MAC(x) = α · x + β
26// In the context of VOLE, this corresponds to w = Δ · u + v
27#[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, // M is the number of shares
33{
34    pub(crate) alpha: GlobalFieldKey<F>,   // α, global key
35    pub(crate) betas: FieldElements<F, M>, // β, a local key per shared value.
36}
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    /* === Verification === */
60
61    #[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
91// --------------
92// | Arithmetic |
93// --------------
94
95// === Addition === //
96
97impl<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
136// === AddAssign === //
137
138impl<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
156// === Subtraction === //
157
158impl<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
210// === SubAssign === //
211
212impl<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
230// === FieldElements/SubfieldElements multiplication === //
231
232impl<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
272// === One-to-many FieldElement/SubfieldElement multiplication === //
273
274impl<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
322// === MulAssign === //
323
324impl<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
361// === MulAssign with vectors === //
362
363impl<'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
372// === Negation === //
373
374impl<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
398// === Sum === //
399impl<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
406// === Constant addition / subtraction === //
407
408impl<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
438// -------------------------
439// |   Random Generation   |
440// -------------------------
441
442impl<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    /// Generates a random set of field share keys with the given global key `alpha`.
453    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
461// -----------------------
462// |   Split and Merge   |
463// -----------------------
464
465impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
466    // Split into two keys with batch sizes M1 and M2
467    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    // Split batch of M keys into two key batches of equal size (M/2)
482    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    // Merge two sets of keys with M keys each into a single set of keys with 2M keys.
496    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    // Split into three keys with batch sizes M1, M2, and M3
508    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    // Split into three keys with batches of equal size (M/3)
531    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    // Merge three sets of keys with M keys each into a single set of keys with 3M keys.
552    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
565// === Constant time equality / selection === //
566
567impl<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
584// ------------------------
585// |   Iterate and Cast   |
586// ------------------------
587
588// === Single key === //
589
590impl<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
599// === Iterators === //
600
601pub 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}