movement_sdk/account/
ed25519.rs1#[cfg(feature = "mnemonic")]
15use crate::account::Mnemonic;
16use crate::account::account::{Account, AuthenticationKey};
17use crate::crypto::{
18 ED25519_SCHEME, Ed25519PrivateKey, Ed25519PublicKey, SINGLE_KEY_SCHEME,
19 derive_authentication_key,
20};
21use crate::error::MovementResult;
22use crate::types::AccountAddress;
23use std::fmt;
24
25#[derive(Clone)]
39pub struct Ed25519Account {
40 private_key: Ed25519PrivateKey,
41 public_key: Ed25519PublicKey,
42 address: AccountAddress,
43}
44
45impl Ed25519Account {
46 pub fn generate() -> Self {
48 let private_key = Ed25519PrivateKey::generate();
49 Self::from_private_key(private_key)
50 }
51
52 pub fn from_private_key(private_key: Ed25519PrivateKey) -> Self {
54 let public_key = private_key.public_key();
55 let address = public_key.to_address();
56 Self {
57 private_key,
58 public_key,
59 address,
60 }
61 }
62
63 pub fn from_private_key_bytes(bytes: &[u8]) -> MovementResult<Self> {
69 let private_key = Ed25519PrivateKey::from_bytes(bytes)?;
70 Ok(Self::from_private_key(private_key))
71 }
72
73 pub fn from_private_key_hex(hex_str: &str) -> MovementResult<Self> {
81 let private_key = Ed25519PrivateKey::from_hex(hex_str)?;
82 Ok(Self::from_private_key(private_key))
83 }
84
85 #[must_use]
91 pub fn with_address(mut self, address: AccountAddress) -> Self {
92 self.address = address;
93 self
94 }
95
96 #[cfg(feature = "mnemonic")]
118 pub fn from_mnemonic(mnemonic: &str, index: u32) -> MovementResult<Self> {
119 let mnemonic = Mnemonic::from_phrase(mnemonic)?;
120 let private_key = mnemonic.derive_ed25519_key(index)?;
121 Ok(Self::from_private_key(private_key))
122 }
123
124 #[cfg(feature = "mnemonic")]
132 pub fn generate_with_mnemonic() -> MovementResult<(Self, String)> {
133 let mnemonic = Mnemonic::generate(24)?;
134 let phrase = mnemonic.phrase().to_string();
135 let private_key = mnemonic.derive_ed25519_key(0)?;
136 let account = Self::from_private_key(private_key);
137 Ok((account, phrase))
138 }
139
140 pub fn address(&self) -> AccountAddress {
142 self.address
143 }
144
145 pub fn public_key(&self) -> &Ed25519PublicKey {
147 &self.public_key
148 }
149
150 pub fn private_key(&self) -> &Ed25519PrivateKey {
154 &self.private_key
155 }
156
157 pub fn sign_message(&self, message: &[u8]) -> crate::crypto::Ed25519Signature {
159 self.private_key.sign(message)
160 }
161}
162
163impl Account for Ed25519Account {
164 fn address(&self) -> AccountAddress {
165 self.address
166 }
167
168 fn authentication_key(&self) -> AuthenticationKey {
169 AuthenticationKey::new(self.public_key.to_authentication_key())
170 }
171
172 fn sign(&self, message: &[u8]) -> MovementResult<Vec<u8>> {
173 Ok(self.private_key.sign(message).to_bytes().to_vec())
174 }
175
176 fn public_key_bytes(&self) -> Vec<u8> {
177 self.public_key.to_bytes().to_vec()
178 }
179
180 fn signature_scheme(&self) -> u8 {
181 ED25519_SCHEME
182 }
183}
184
185impl fmt::Debug for Ed25519Account {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 f.debug_struct("Ed25519Account")
188 .field("address", &self.address)
189 .field("public_key", &self.public_key)
190 .finish_non_exhaustive()
191 }
192}
193
194#[derive(Clone)]
222pub struct Ed25519SingleKeyAccount {
223 private_key: Ed25519PrivateKey,
224 public_key: Ed25519PublicKey,
225 address: AccountAddress,
226}
227
228impl Ed25519SingleKeyAccount {
229 pub fn generate() -> Self {
231 let private_key = Ed25519PrivateKey::generate();
232 Self::from_private_key(private_key)
233 }
234
235 pub fn from_private_key(private_key: Ed25519PrivateKey) -> Self {
237 let public_key = private_key.public_key();
238 let address = Self::derive_address(&public_key);
239 Self {
240 private_key,
241 public_key,
242 address,
243 }
244 }
245
246 pub fn from_private_key_bytes(bytes: &[u8]) -> MovementResult<Self> {
252 let private_key = Ed25519PrivateKey::from_bytes(bytes)?;
253 Ok(Self::from_private_key(private_key))
254 }
255
256 pub fn from_private_key_hex(hex_str: &str) -> MovementResult<Self> {
264 let private_key = Ed25519PrivateKey::from_hex(hex_str)?;
265 Ok(Self::from_private_key(private_key))
266 }
267
268 #[cfg(feature = "mnemonic")]
276 pub fn from_mnemonic(mnemonic: &str, index: u32) -> MovementResult<Self> {
277 let mnemonic = Mnemonic::from_phrase(mnemonic)?;
278 let private_key = mnemonic.derive_ed25519_key(index)?;
279 Ok(Self::from_private_key(private_key))
280 }
281
282 pub fn address(&self) -> AccountAddress {
284 self.address
285 }
286
287 pub fn public_key(&self) -> &Ed25519PublicKey {
289 &self.public_key
290 }
291
292 pub fn private_key(&self) -> &Ed25519PrivateKey {
294 &self.private_key
295 }
296
297 pub fn sign_message(&self, message: &[u8]) -> crate::crypto::Ed25519Signature {
299 self.private_key.sign(message)
300 }
301
302 fn derive_address(public_key: &Ed25519PublicKey) -> AccountAddress {
304 let pk_bytes = public_key.to_bytes();
306 let mut bcs_bytes = Vec::with_capacity(1 + 1 + pk_bytes.len());
307 bcs_bytes.push(0x00); bcs_bytes.push(32); bcs_bytes.extend_from_slice(&pk_bytes);
310 let auth_key = derive_authentication_key(&bcs_bytes, SINGLE_KEY_SCHEME);
311 AccountAddress::new(auth_key)
312 }
313
314 fn bcs_public_key_bytes(&self) -> Vec<u8> {
318 let pk_bytes = self.public_key.to_bytes();
319 let mut bcs_bytes = Vec::with_capacity(1 + 1 + pk_bytes.len());
320 bcs_bytes.push(0x00); bcs_bytes.push(32); bcs_bytes.extend_from_slice(&pk_bytes);
323 bcs_bytes
324 }
325}
326
327impl Account for Ed25519SingleKeyAccount {
328 fn address(&self) -> AccountAddress {
329 self.address
330 }
331
332 fn authentication_key(&self) -> AuthenticationKey {
333 let bcs_bytes = self.bcs_public_key_bytes();
334 let key = derive_authentication_key(&bcs_bytes, SINGLE_KEY_SCHEME);
335 AuthenticationKey::new(key)
336 }
337
338 fn sign(&self, message: &[u8]) -> MovementResult<Vec<u8>> {
339 Ok(self.private_key.sign(message).to_bytes().to_vec())
340 }
341
342 fn public_key_bytes(&self) -> Vec<u8> {
343 self.bcs_public_key_bytes()
345 }
346
347 fn signature_scheme(&self) -> u8 {
348 SINGLE_KEY_SCHEME
349 }
350}
351
352impl fmt::Debug for Ed25519SingleKeyAccount {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354 f.debug_struct("Ed25519SingleKeyAccount")
355 .field("address", &self.address)
356 .field("public_key", &self.public_key)
357 .finish_non_exhaustive()
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364
365 #[test]
366 fn test_generate() {
367 let account = Ed25519Account::generate();
368 assert!(!account.address().is_zero());
369 }
370
371 #[test]
372 #[cfg(feature = "mnemonic")]
373 fn test_from_mnemonic() {
374 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
376 let account = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
377
378 let account2 = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
380 assert_eq!(account.address(), account2.address());
381
382 let account3 = Ed25519Account::from_mnemonic(mnemonic, 1).unwrap();
384 assert_ne!(account.address(), account3.address());
385 }
386
387 #[test]
388 fn test_sign_and_verify() {
389 let account = Ed25519Account::generate();
390 let message = b"hello world";
391
392 let signature = account.sign_message(message);
393 assert!(account.public_key().verify(message, &signature).is_ok());
394 }
395
396 #[test]
397 #[cfg(feature = "mnemonic")]
398 fn test_generate_with_mnemonic() {
399 let (account, mnemonic) = Ed25519Account::generate_with_mnemonic().unwrap();
400
401 let restored = Ed25519Account::from_mnemonic(&mnemonic, 0).unwrap();
403 assert_eq!(account.address(), restored.address());
404 }
405
406 #[test]
407 fn test_from_private_key() {
408 let original = Ed25519Account::generate();
409 let private_key = original.private_key().clone();
410 let restored = Ed25519Account::from_private_key(private_key);
411 assert_eq!(original.address(), restored.address());
412 }
413
414 #[test]
415 fn test_from_private_key_bytes() {
416 let original = Ed25519Account::generate();
417 let bytes = original.private_key().to_bytes();
418 let restored = Ed25519Account::from_private_key_bytes(&bytes).unwrap();
419 assert_eq!(original.address(), restored.address());
420 }
421
422 #[test]
423 fn test_from_private_key_hex() {
424 let original = Ed25519Account::generate();
425 let hex = original.private_key().to_hex();
426 let restored = Ed25519Account::from_private_key_hex(&hex).unwrap();
427 assert_eq!(original.address(), restored.address());
428 }
429
430 #[test]
431 fn test_authentication_key() {
432 let account = Ed25519Account::generate();
433 let auth_key = account.authentication_key();
434 assert_eq!(auth_key.as_bytes().len(), 32);
435 }
436
437 #[test]
438 fn test_public_key_bytes() {
439 let account = Ed25519Account::generate();
440 let bytes = account.public_key_bytes();
441 assert_eq!(bytes.len(), 32);
442 }
443
444 #[test]
445 fn test_signature_scheme() {
446 let account = Ed25519Account::generate();
447 assert_eq!(account.signature_scheme(), ED25519_SCHEME);
448 }
449
450 #[test]
451 fn test_sign_trait() {
452 let account = Ed25519Account::generate();
453 let message = b"test message";
454 let sig_bytes = account.sign(message).unwrap();
455 assert_eq!(sig_bytes.len(), 64);
456 }
457
458 #[test]
459 fn test_debug_output() {
460 let account = Ed25519Account::generate();
461 let debug = format!("{account:?}");
462 assert!(debug.contains("Ed25519Account"));
463 assert!(debug.contains("address"));
464 }
465
466 #[test]
467 fn test_invalid_private_key_bytes() {
468 let result = Ed25519Account::from_private_key_bytes(&[0u8; 16]);
469 assert!(result.is_err());
470 }
471
472 #[test]
473 fn test_invalid_private_key_hex() {
474 let result = Ed25519Account::from_private_key_hex("invalid");
475 assert!(result.is_err());
476 }
477
478 #[test]
479 #[cfg(feature = "mnemonic")]
480 fn test_invalid_mnemonic() {
481 let result = Ed25519Account::from_mnemonic("invalid mnemonic phrase", 0);
482 assert!(result.is_err());
483 }
484
485 #[test]
488 fn test_single_key_generate() {
489 let account = Ed25519SingleKeyAccount::generate();
490 assert!(!account.address().is_zero());
491 }
492
493 #[test]
494 fn test_single_key_different_address() {
495 let legacy_account = Ed25519Account::generate();
497 let private_key = legacy_account.private_key().clone();
498
499 let single_key_account = Ed25519SingleKeyAccount::from_private_key(private_key);
500
501 assert_ne!(legacy_account.address(), single_key_account.address());
503 }
504
505 #[test]
506 fn test_single_key_sign_and_verify() {
507 let account = Ed25519SingleKeyAccount::generate();
508 let message = b"hello world";
509
510 let signature = account.sign_message(message);
511 assert!(account.public_key().verify(message, &signature).is_ok());
512 }
513
514 #[test]
515 fn test_single_key_from_private_key() {
516 let original = Ed25519SingleKeyAccount::generate();
517 let private_key = original.private_key().clone();
518 let restored = Ed25519SingleKeyAccount::from_private_key(private_key);
519 assert_eq!(original.address(), restored.address());
520 }
521
522 #[test]
523 fn test_single_key_from_private_key_bytes() {
524 let original = Ed25519SingleKeyAccount::generate();
525 let bytes = original.private_key().to_bytes();
526 let restored = Ed25519SingleKeyAccount::from_private_key_bytes(&bytes).unwrap();
527 assert_eq!(original.address(), restored.address());
528 }
529
530 #[test]
531 fn test_single_key_from_private_key_hex() {
532 let original = Ed25519SingleKeyAccount::generate();
533 let hex = original.private_key().to_hex();
534 let restored = Ed25519SingleKeyAccount::from_private_key_hex(&hex).unwrap();
535 assert_eq!(original.address(), restored.address());
536 }
537
538 #[test]
539 fn test_single_key_authentication_key() {
540 let account = Ed25519SingleKeyAccount::generate();
541 let auth_key = account.authentication_key();
542 assert_eq!(auth_key.as_bytes().len(), 32);
543 }
544
545 #[test]
546 fn test_single_key_public_key_bytes() {
547 let account = Ed25519SingleKeyAccount::generate();
548 let bytes = account.public_key_bytes();
549 assert_eq!(bytes.len(), 34);
551 assert_eq!(bytes[0], 0x00); assert_eq!(bytes[1], 32); }
554
555 #[test]
556 fn test_single_key_signature_scheme() {
557 let account = Ed25519SingleKeyAccount::generate();
558 assert_eq!(account.signature_scheme(), SINGLE_KEY_SCHEME);
559 }
560
561 #[test]
562 fn test_single_key_sign_trait() {
563 let account = Ed25519SingleKeyAccount::generate();
564 let message = b"test message";
565 let sig_bytes = account.sign(message).unwrap();
566 assert_eq!(sig_bytes.len(), 64);
567 }
568
569 #[test]
570 fn test_single_key_debug_output() {
571 let account = Ed25519SingleKeyAccount::generate();
572 let debug = format!("{account:?}");
573 assert!(debug.contains("Ed25519SingleKeyAccount"));
574 assert!(debug.contains("address"));
575 }
576
577 #[test]
578 #[cfg(feature = "mnemonic")]
579 fn test_single_key_from_mnemonic() {
580 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
581 let account = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
582
583 let account2 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
585 assert_eq!(account.address(), account2.address());
586
587 let account3 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 1).unwrap();
589 assert_ne!(account.address(), account3.address());
590 }
591
592 #[test]
593 #[cfg(feature = "mnemonic")]
594 fn test_single_key_vs_legacy_mnemonic() {
595 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
596
597 let legacy = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
598 let single_key = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
599
600 assert_eq!(
602 legacy.private_key().to_bytes(),
603 single_key.private_key().to_bytes()
604 );
605 assert_ne!(legacy.address(), single_key.address());
606 }
607}