multiversx_sdk/crypto/edwards25519/
extended_group_element.rs1use super::{
2 completed_group_element::CompletedGroupElement, field_element::FieldElement,
3 pre_computed_group_element::PreComputedGroupElement,
4 projective_group_element::ProjectiveGroupElement,
5};
6
7#[derive(Default, Copy, Clone, Debug)]
8pub struct ExtendedGroupElement {
9 pub x: FieldElement,
10 pub y: FieldElement,
11 pub z: FieldElement,
12 pub t: FieldElement,
13}
14
15impl ExtendedGroupElement {
16 pub fn to_projective(self, r: &mut ProjectiveGroupElement) {
17 r.x.fe_copy(&self.x);
18 r.y.fe_copy(&self.y);
19 r.z.fe_copy(&self.z);
20 }
21
22 pub fn double(&self, r: &mut CompletedGroupElement) {
23 let mut q = ProjectiveGroupElement::default();
24
25 self.to_projective(&mut q);
26 q.double(r);
27 }
28
29 pub fn zero(&mut self) {
30 self.x.fe_zero();
31 self.y.fe_one();
32 self.z.fe_one();
33 self.t.fe_zero();
34 }
35
36 #[allow(clippy::needless_range_loop)]
43 pub fn ge_scalar_mult_base(&mut self, a: [u8; 32]) {
44 let mut e = [0i8; 64];
45 for (i, v) in a.iter().enumerate() {
46 e[2 * i] = (v & 15) as i8;
47 e[2 * i + 1] = ((v >> 4) & 15) as i8;
48 }
49
50 let mut carry: i8 = 0;
53 for i in 0..63 {
54 e[i] += carry;
55 carry = (e[i] + 8) >> 4;
56 e[i] -= carry << 4;
57 }
58
59 e[63] += carry;
60 self.zero();
63 let mut t = PreComputedGroupElement::default();
64 let mut r = CompletedGroupElement::default();
65 for i in (1..64).step_by(2) {
66 t.select_point(i / 2, e[i as usize] as i32);
67 r.ge_mixed_add(self, &t);
68 r.to_extended(self);
69 }
70
71 let mut s = ProjectiveGroupElement::default();
72
73 self.double(&mut r);
74 r.to_projective(&mut s);
75 s.double(&mut r);
76 r.to_projective(&mut s);
77 s.double(&mut r);
78 r.to_projective(&mut s);
79 s.double(&mut r);
80 r.to_extended(self);
81
82 for i in (0..64).step_by(2) {
83 t.select_point(i / 2, e[i as usize] as i32);
84 r.ge_mixed_add(self, &t);
85 r.to_extended(self);
86 }
87 }
88
89 pub fn to_bytes(self) -> [u8; 32] {
90 let mut recip = FieldElement::default();
91 let mut x = FieldElement::default();
92 let mut y = FieldElement::default();
93
94 recip.fe_invert(&self.z);
95 x.fe_mul(&self.x, &recip);
96 y.fe_mul(&self.y, &recip);
97 let mut s = y.to_bytes();
98
99 s[31] ^= x.fe_is_negative() << 7;
100
101 s
102 }
103}