1use serde::{Deserialize, Serialize};
4use starknet_types_core::curve::{AffinePoint, ProjectivePoint};
5use starknet_types_core::felt::Felt;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub struct SerializablePoint {
10 pub x: String,
11 pub y: String,
12}
13
14impl SerializablePoint {
15 pub fn from_affine(point: &AffinePoint) -> Self {
16 Self {
17 x: format!("{:#x}", point.x()),
18 y: format!("{:#x}", point.y()),
19 }
20 }
21
22 pub fn try_from_projective(point: &ProjectivePoint) -> crate::Result<Self> {
27 let affine = point
28 .to_affine()
29 .map_err(|_| crate::KmsError::PointAtInfinity)?;
30 Ok(Self::from_affine(&affine))
31 }
32
33 #[deprecated(
38 since = "0.2.0",
39 note = "Use try_from_projective for fallible conversion"
40 )]
41 pub fn from_projective(point: &ProjectivePoint) -> Self {
42 Self::try_from_projective(point).expect("Point at infinity cannot be serialized")
43 }
44
45 pub fn to_affine(&self) -> crate::Result<AffinePoint> {
46 let x = Felt::from_hex(&self.x)
47 .map_err(|e| crate::KmsError::DeserializationError(e.to_string()))?;
48 let y = Felt::from_hex(&self.y)
49 .map_err(|e| crate::KmsError::DeserializationError(e.to_string()))?;
50
51 AffinePoint::new(x, y)
52 .map_err(|e| crate::KmsError::InvalidPublicKey(format!("Invalid point: {:?}", e)))
53 }
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct PoeProof {
59 #[serde(rename = "A")]
60 pub a: SerializablePoint,
61 pub s: String,
62 pub c: String,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct Poe2Proof {
68 #[serde(rename = "A")]
69 pub a: SerializablePoint,
70 pub s1: String,
71 pub s2: String,
72 pub c: String,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct ElGamalProof {
78 #[serde(rename = "AL")]
79 pub al: SerializablePoint,
80 #[serde(rename = "AR")]
81 pub ar: SerializablePoint,
82 pub sb: String,
83 pub sr: String,
84 pub c: String,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct AuditProof {
91 #[serde(rename = "Ax")]
92 pub ax: SerializablePoint,
93 #[serde(rename = "AL0")]
94 pub al0: SerializablePoint,
95 #[serde(rename = "AL1")]
96 pub al1: SerializablePoint,
97 #[serde(rename = "AR1")]
98 pub ar1: SerializablePoint,
99 pub sx: String,
100 pub sb: String,
101 pub sr: String,
102 pub c: String,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct ElGamalCiphertext {
108 pub l: ProjectivePoint,
109 pub r: ProjectivePoint,
110}
111
112#[derive(Debug, Clone, Default)]
114pub struct AccountState {
115 pub balance: u128,
117 pub pending_balance: u128,
119 pub nonce: u64,
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
125#[serde(rename_all = "lowercase")]
126pub enum TransactionType {
127 Fund,
128 Send,
129 Rollover,
130 Withdraw,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct ProofOfBit {
137 #[serde(rename = "A0")]
138 pub a0: SerializablePoint,
139 #[serde(rename = "A1")]
140 pub a1: SerializablePoint,
141 pub c0: String,
142 pub s0: String,
143 pub s1: String,
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct Range {
150 pub commitments: Vec<SerializablePoint>,
151 pub proofs: Vec<ProofOfBit>,
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct ProofOfTransfer {
163 #[serde(rename = "A_x")]
164 pub a_x: SerializablePoint,
165 #[serde(rename = "A_r")]
166 pub a_r: SerializablePoint,
167 #[serde(rename = "A_r2")]
168 pub a_r2: SerializablePoint,
169 #[serde(rename = "A_b")]
170 pub a_b: SerializablePoint,
171 #[serde(rename = "A_b2")]
172 pub a_b2: SerializablePoint,
173 #[serde(rename = "A_v")]
174 pub a_v: SerializablePoint,
175 #[serde(rename = "A_v2")]
176 pub a_v2: SerializablePoint,
177 #[serde(rename = "A_bar")]
178 pub a_bar: SerializablePoint,
179 pub s_x: String,
180 pub s_r: String,
181 pub s_b: String,
182 pub s_b2: String,
183 pub s_r2: String,
184 pub range: Range,
185 pub range2: Range,
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191
192 #[test]
193 fn test_serializable_point_from_affine() {
194 let x = Felt::from_hex("0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca")
196 .unwrap();
197 let y = Felt::from_hex("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f")
198 .unwrap();
199 let affine = AffinePoint::new(x, y).unwrap();
200 let point = SerializablePoint::from_affine(&affine);
201 assert!(point.x.starts_with("0x"));
202 assert!(point.y.starts_with("0x"));
203 }
204
205 #[test]
206 fn test_serializable_point_try_from_projective() {
207 let g_x =
209 Felt::from_hex("0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca")
210 .unwrap();
211 let g_y =
212 Felt::from_hex("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f")
213 .unwrap();
214 let projective = ProjectivePoint::from_affine(g_x, g_y).unwrap();
215
216 let result = SerializablePoint::try_from_projective(&projective);
217 assert!(result.is_ok());
218 let point = result.unwrap();
219 assert!(point.x.starts_with("0x"));
220 assert!(point.y.starts_with("0x"));
221 }
222
223 #[test]
224 fn test_serializable_point_try_from_projective_identity() {
225 let identity = ProjectivePoint::identity();
227 let result = SerializablePoint::try_from_projective(&identity);
228 assert!(result.is_err());
229 }
230
231 #[test]
232 fn test_serializable_point_to_affine() {
233 let point = SerializablePoint {
235 x: "0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca".to_string(),
236 y: "0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f".to_string(),
237 };
238 let affine = point.to_affine().unwrap();
239 assert_eq!(
240 affine.x(),
241 Felt::from_hex("0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca")
242 .unwrap()
243 );
244 }
245
246 #[test]
247 fn test_serializable_point_to_affine_invalid_hex() {
248 let point = SerializablePoint {
249 x: "invalid_hex".to_string(),
250 y: "0x2".to_string(),
251 };
252 let result = point.to_affine();
253 assert!(result.is_err());
254 }
255
256 #[test]
257 fn test_serializable_point_roundtrip() {
258 let g_x =
260 Felt::from_hex("0x1ef15c18599971b7beced415a40f0c7deacfd9b0d1819e03d723d8bc943cfca")
261 .unwrap();
262 let g_y =
263 Felt::from_hex("0x5668060aa49730b7be4801df46ec62de53ecd11abe43a32873000c36e8dc1f")
264 .unwrap();
265 let original = AffinePoint::new(g_x, g_y).unwrap();
266
267 let serialized = SerializablePoint::from_affine(&original);
268 let recovered = serialized.to_affine().unwrap();
269
270 assert_eq!(original.x(), recovered.x());
271 assert_eq!(original.y(), recovered.y());
272 }
273}