1use crate::{
2 convert::{decode, encode},
3 error::DecodeError,
4 version,
5};
6
7use alloc::{format, string::String, vec, vec::Vec};
8use core::{
9 fmt::{Debug, Display},
10 str::FromStr,
11};
12
13#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
14#[cfg_attr(
15 feature = "serde",
16 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
17)]
18pub struct PrivateKey(pub [u8; 32]);
19
20impl Debug for PrivateKey {
21 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22 write!(f, "PrivateKey(")?;
23 write!(
24 f,
25 "{}",
26 &self
27 .0
28 .iter()
29 .map(|b| format!("{b:02x}"))
30 .collect::<String>()
31 )?;
32 write!(f, ")")?;
33 Ok(())
34 }
35}
36
37impl PrivateKey {
38 pub fn to_string(&self) -> String {
39 encode(version::PRIVATE_KEY_ED25519, &self.0)
40 }
41
42 pub fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
43 match payload.try_into() {
44 Ok(ed25519) => Ok(Self(ed25519)),
45 Err(_) => Err(DecodeError::Invalid),
46 }
47 }
48
49 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
50 let (ver, payload) = decode(s)?;
51 match ver {
52 version::PRIVATE_KEY_ED25519 => Self::from_payload(&payload),
53 _ => Err(DecodeError::Invalid),
54 }
55 }
56}
57
58impl Display for PrivateKey {
59 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60 write!(f, "{}", self.to_string())
61 }
62}
63
64impl FromStr for PrivateKey {
65 type Err = DecodeError;
66
67 fn from_str(s: &str) -> Result<Self, Self::Err> {
68 PrivateKey::from_string(s)
69 }
70}
71
72#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
73#[cfg_attr(
74 feature = "serde",
75 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
76)]
77pub struct PublicKey(pub [u8; 32]);
78
79impl Debug for PublicKey {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81 write!(f, "PublicKey(")?;
82 write!(
83 f,
84 "{}",
85 &self
86 .0
87 .iter()
88 .map(|b| format!("{b:02x}"))
89 .collect::<String>()
90 )?;
91 write!(f, ")")?;
92 Ok(())
93 }
94}
95
96impl PublicKey {
97 pub fn to_string(&self) -> String {
98 encode(version::PUBLIC_KEY_ED25519, &self.0)
99 }
100
101 pub fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
102 match payload.try_into() {
103 Ok(ed25519) => Ok(Self(ed25519)),
104 Err(_) => Err(DecodeError::Invalid),
105 }
106 }
107
108 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
109 let (ver, payload) = decode(s)?;
110 match ver {
111 version::PUBLIC_KEY_ED25519 => Self::from_payload(&payload),
112 _ => Err(DecodeError::Invalid),
113 }
114 }
115}
116
117impl Display for PublicKey {
118 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119 write!(f, "{}", self.to_string())
120 }
121}
122
123impl FromStr for PublicKey {
124 type Err = DecodeError;
125
126 fn from_str(s: &str) -> Result<Self, Self::Err> {
127 PublicKey::from_string(s)
128 }
129}
130
131#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
132#[cfg_attr(
133 feature = "serde",
134 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
135)]
136pub struct MuxedAccount {
137 pub ed25519: [u8; 32],
138 pub id: u64,
139}
140
141impl Debug for MuxedAccount {
142 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
143 write!(f, "MuxedAccount(")?;
144 write!(
145 f,
146 "{}",
147 &self
148 .ed25519
149 .iter()
150 .map(|b| format!("{b:02x}"))
151 .collect::<String>()
152 )?;
153 write!(f, ", ")?;
154 write!(f, "{}", self.id)?;
155 write!(f, ")")?;
156 Ok(())
157 }
158}
159
160impl MuxedAccount {
161 pub fn to_string(&self) -> String {
162 let mut payload: [u8; 40] = [0; 40];
163 let (ed25519, id) = payload.split_at_mut(32);
164 ed25519.copy_from_slice(&self.ed25519);
165 id.copy_from_slice(&self.id.to_be_bytes());
166 encode(version::MUXED_ACCOUNT_ED25519, &payload)
167 }
168
169 pub fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
170 if payload.len() < 40 {
171 return Err(DecodeError::Invalid);
172 }
173 let (ed25519, id) = payload.split_at(32);
174 Ok(Self {
175 ed25519: ed25519.try_into().map_err(|_| DecodeError::Invalid)?,
176 id: u64::from_be_bytes(id.try_into().map_err(|_| DecodeError::Invalid)?),
177 })
178 }
179
180 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
181 let (ver, payload) = decode(s)?;
182 match ver {
183 version::MUXED_ACCOUNT_ED25519 => Self::from_payload(&payload),
184 _ => Err(DecodeError::Invalid),
185 }
186 }
187}
188
189impl Display for MuxedAccount {
190 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
191 write!(f, "{}", self.to_string())
192 }
193}
194
195impl FromStr for MuxedAccount {
196 type Err = DecodeError;
197
198 fn from_str(s: &str) -> Result<Self, Self::Err> {
199 MuxedAccount::from_string(s)
200 }
201}
202
203#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
207#[cfg_attr(
208 feature = "serde",
209 derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
210)]
211pub struct SignedPayload {
212 pub ed25519: [u8; 32],
213 pub payload: Vec<u8>,
214}
215
216impl Debug for SignedPayload {
217 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
218 write!(f, "MuxedAccount(")?;
219 write!(
220 f,
221 "{}",
222 &self
223 .ed25519
224 .iter()
225 .map(|b| format!("{b:02x}"))
226 .collect::<String>()
227 )?;
228 write!(f, ", ")?;
229 write!(
230 f,
231 "{}",
232 &self
233 .payload
234 .iter()
235 .map(|b| format!("{b:02x}"))
236 .collect::<String>()
237 )?;
238 write!(f, ")")?;
239 Ok(())
240 }
241}
242
243impl SignedPayload {
244 pub fn to_string(&self) -> String {
250 let inner_payload_len = self.payload.len();
251 let payload_len = 32 + 4 + inner_payload_len + (4 - inner_payload_len % 4) % 4;
252
253 let inner_payload_len_u32: u32 = inner_payload_len
254 .try_into()
255 .expect("payload length larger than u32::MAX");
256
257 let mut payload = vec![0; payload_len];
258 payload[..32].copy_from_slice(&self.ed25519);
259 payload[32..32 + 4].copy_from_slice(&(inner_payload_len_u32).to_be_bytes());
260 payload[32 + 4..32 + 4 + inner_payload_len].copy_from_slice(&self.payload);
261
262 encode(version::SIGNED_PAYLOAD_ED25519, &payload)
263 }
264
265 pub fn from_payload(payload: &[u8]) -> Result<Self, DecodeError> {
266 const MAX_INNER_PAYLOAD_LENGTH: u32 = 64;
269 const MIN_LENGTH: usize = 32 + 4 + 4;
270 const MAX_LENGTH: usize = 32 + 4 + (MAX_INNER_PAYLOAD_LENGTH as usize);
271 let payload_len = payload.len();
272 if !(MIN_LENGTH..=MAX_LENGTH).contains(&payload_len) {
273 return Err(DecodeError::Invalid);
274 }
275
276 let mut offset = 0;
278 let ed25519: [u8; 32] = payload
279 .get(offset..offset + 32)
280 .ok_or(DecodeError::Invalid)?
281 .try_into()
282 .map_err(|_| DecodeError::Invalid)?;
283 offset += 32;
284
285 let inner_payload_len = u32::from_be_bytes(
287 payload
288 .get(offset..offset + 4)
289 .ok_or(DecodeError::Invalid)?
290 .try_into()
291 .map_err(|_| DecodeError::Invalid)?,
292 );
293 offset += 4;
294
295 if inner_payload_len > MAX_INNER_PAYLOAD_LENGTH {
297 return Err(DecodeError::Invalid);
298 }
299
300 let inner_payload = payload
302 .get(offset..offset + inner_payload_len as usize)
303 .ok_or(DecodeError::Invalid)?;
304 offset += inner_payload_len as usize;
305
306 let padding_len = (4 - inner_payload_len % 4) % 4;
308
309 let padding = payload
311 .get(offset..offset + padding_len as usize)
312 .ok_or(DecodeError::Invalid)?;
313 offset += padding_len as usize;
314
315 if padding.iter().any(|b| *b != 0) {
317 return Err(DecodeError::Invalid);
318 }
319
320 if offset != payload_len {
322 return Err(DecodeError::Invalid);
323 }
324
325 Ok(Self {
326 ed25519,
327 payload: inner_payload.to_vec(),
328 })
329 }
330
331 pub fn from_string(s: &str) -> Result<Self, DecodeError> {
332 let (ver, payload) = decode(s)?;
333 match ver {
334 version::SIGNED_PAYLOAD_ED25519 => Self::from_payload(&payload),
335 _ => Err(DecodeError::Invalid),
336 }
337 }
338}
339
340impl Display for SignedPayload {
341 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
342 write!(f, "{}", self.to_string())
343 }
344}
345
346impl FromStr for SignedPayload {
347 type Err = DecodeError;
348
349 fn from_str(s: &str) -> Result<Self, Self::Err> {
350 SignedPayload::from_string(s)
351 }
352}