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, 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// α 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(
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
92// --------------
93// | Arithmetic |
94// --------------
95
96// === Addition === //
97
98impl<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
137// === AddAssign === //
138
139impl<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
157// === Subtraction === //
158
159impl<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
211// === SubAssign === //
212
213impl<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
231// === FieldElements/SubfieldElements multiplication === //
232
233impl<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
273// === One-to-many FieldElement/SubfieldElement multiplication === //
274
275impl<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
323// === MulAssign === //
324
325impl<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
362// === MulAssign with vectors === //
363
364impl<'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
373// === Negation === //
374
375impl<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
399// === Sum === //
400impl<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
407// === Constant addition / subtraction === //
408
409impl<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
439// -------------------------
440// |   Random Generation   |
441// -------------------------
442
443impl<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    /// Generates a random set of field share keys with the given global key `alpha`.
454    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
462// -----------------------
463// |   Split and Merge   |
464// -----------------------
465
466impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
467    // Split into two keys with batch sizes M1 and M2
468    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    // Split batch of M keys into two key batches of equal size (M/2)
483    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    // Merge two sets of keys with M keys each into a single set of keys with 2M keys.
497    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    // Split into three keys with batch sizes M1, M2, and M3
509    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    // Split into three keys with batches of equal size (M/3)
532    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    // Merge three sets of keys with M keys each into a single set of keys with 3M keys.
553    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
566// === Constant time equality / selection === //
567
568impl<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
585// ------------------------
586// |   Iterate and Cast   |
587// ------------------------
588
589// === Single key === //
590
591impl<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
600// === Iterators === //
601
602pub 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}