aptos_sdk/account/
account.rs1use crate::error::AptosResult;
4use crate::types::AccountAddress;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13pub struct AuthenticationKey([u8; 32]);
14
15impl AuthenticationKey {
16 pub fn new(bytes: [u8; 32]) -> Self {
18 Self(bytes)
19 }
20
21 pub fn from_bytes(bytes: &[u8]) -> AptosResult<Self> {
27 if bytes.len() != 32 {
28 return Err(crate::error::AptosError::InvalidAddress(format!(
29 "authentication key must be 32 bytes, got {}",
30 bytes.len()
31 )));
32 }
33 let mut key = [0u8; 32];
34 key.copy_from_slice(bytes);
35 Ok(Self(key))
36 }
37
38 pub fn from_hex(hex_str: &str) -> AptosResult<Self> {
46 let bytes = const_hex::decode(hex_str)?;
47 Self::from_bytes(&bytes)
48 }
49
50 pub fn as_bytes(&self) -> &[u8; 32] {
52 &self.0
53 }
54
55 pub fn to_bytes(&self) -> [u8; 32] {
57 self.0
58 }
59
60 pub fn to_hex(&self) -> String {
62 const_hex::encode_prefixed(self.0)
63 }
64
65 pub fn to_address(&self) -> AccountAddress {
69 AccountAddress::new(self.0)
70 }
71}
72
73impl fmt::Debug for AuthenticationKey {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "AuthenticationKey({})", self.to_hex())
76 }
77}
78
79impl fmt::Display for AuthenticationKey {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 write!(f, "{}", self.to_hex())
82 }
83}
84
85impl From<[u8; 32]> for AuthenticationKey {
86 fn from(bytes: [u8; 32]) -> Self {
87 Self(bytes)
88 }
89}
90
91impl From<AuthenticationKey> for [u8; 32] {
92 fn from(key: AuthenticationKey) -> Self {
93 key.0
94 }
95}
96
97impl From<AuthenticationKey> for AccountAddress {
98 fn from(key: AuthenticationKey) -> Self {
99 key.to_address()
100 }
101}
102
103pub trait Account: Send + Sync {
108 fn address(&self) -> AccountAddress;
110
111 fn authentication_key(&self) -> AuthenticationKey;
113
114 fn sign(&self, message: &[u8]) -> AptosResult<Vec<u8>>;
121
122 fn public_key_bytes(&self) -> Vec<u8>;
124
125 fn signature_scheme(&self) -> u8;
127}
128
129#[derive(Debug)]
143pub enum AnyAccount {
144 #[cfg(feature = "ed25519")]
146 Ed25519(super::Ed25519Account),
147 #[cfg(feature = "ed25519")]
149 MultiEd25519(super::MultiEd25519Account),
150 MultiKey(super::MultiKeyAccount),
152 #[cfg(feature = "secp256k1")]
154 Secp256k1(super::Secp256k1Account),
155}
156
157impl Account for AnyAccount {
158 fn address(&self) -> AccountAddress {
159 match self {
160 #[cfg(feature = "ed25519")]
161 AnyAccount::Ed25519(account) => account.address(),
162 #[cfg(feature = "ed25519")]
163 AnyAccount::MultiEd25519(account) => account.address(),
164 AnyAccount::MultiKey(account) => account.address(),
165 #[cfg(feature = "secp256k1")]
166 AnyAccount::Secp256k1(account) => account.address(),
167 }
168 }
169
170 fn authentication_key(&self) -> AuthenticationKey {
171 match self {
172 #[cfg(feature = "ed25519")]
173 AnyAccount::Ed25519(account) => account.authentication_key(),
174 #[cfg(feature = "ed25519")]
175 AnyAccount::MultiEd25519(account) => account.authentication_key(),
176 AnyAccount::MultiKey(account) => account.authentication_key(),
177 #[cfg(feature = "secp256k1")]
178 AnyAccount::Secp256k1(account) => account.authentication_key(),
179 }
180 }
181
182 fn sign(&self, message: &[u8]) -> AptosResult<Vec<u8>> {
183 match self {
184 #[cfg(feature = "ed25519")]
185 AnyAccount::Ed25519(account) => Account::sign(account, message),
186 #[cfg(feature = "ed25519")]
187 AnyAccount::MultiEd25519(account) => Account::sign(account, message),
188 AnyAccount::MultiKey(account) => Account::sign(account, message),
189 #[cfg(feature = "secp256k1")]
190 AnyAccount::Secp256k1(account) => Account::sign(account, message),
191 }
192 }
193
194 fn public_key_bytes(&self) -> Vec<u8> {
195 match self {
196 #[cfg(feature = "ed25519")]
197 AnyAccount::Ed25519(account) => account.public_key_bytes(),
198 #[cfg(feature = "ed25519")]
199 AnyAccount::MultiEd25519(account) => account.public_key_bytes(),
200 AnyAccount::MultiKey(account) => account.public_key_bytes(),
201 #[cfg(feature = "secp256k1")]
202 AnyAccount::Secp256k1(account) => account.public_key_bytes(),
203 }
204 }
205
206 fn signature_scheme(&self) -> u8 {
207 match self {
208 #[cfg(feature = "ed25519")]
209 AnyAccount::Ed25519(account) => account.signature_scheme(),
210 #[cfg(feature = "ed25519")]
211 AnyAccount::MultiEd25519(account) => account.signature_scheme(),
212 AnyAccount::MultiKey(account) => account.signature_scheme(),
213 #[cfg(feature = "secp256k1")]
214 AnyAccount::Secp256k1(account) => account.signature_scheme(),
215 }
216 }
217}
218
219#[cfg(feature = "ed25519")]
220impl From<super::Ed25519Account> for AnyAccount {
221 fn from(account: super::Ed25519Account) -> Self {
222 AnyAccount::Ed25519(account)
223 }
224}
225
226#[cfg(feature = "ed25519")]
227impl From<super::MultiEd25519Account> for AnyAccount {
228 fn from(account: super::MultiEd25519Account) -> Self {
229 AnyAccount::MultiEd25519(account)
230 }
231}
232
233#[cfg(feature = "secp256k1")]
234impl From<super::Secp256k1Account> for AnyAccount {
235 fn from(account: super::Secp256k1Account) -> Self {
236 AnyAccount::Secp256k1(account)
237 }
238}
239
240impl From<super::MultiKeyAccount> for AnyAccount {
241 fn from(account: super::MultiKeyAccount) -> Self {
242 AnyAccount::MultiKey(account)
243 }
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249
250 #[test]
251 fn test_authentication_key() {
252 let key = AuthenticationKey::new([1u8; 32]);
253 assert_eq!(key.as_bytes(), &[1u8; 32]);
254
255 let hex = key.to_hex();
256 let restored = AuthenticationKey::from_hex(&hex).unwrap();
257 assert_eq!(key, restored);
258 }
259
260 #[test]
261 fn test_auth_key_to_address() {
262 let key = AuthenticationKey::new([42u8; 32]);
263 let address = key.to_address();
264 assert_eq!(address.as_bytes(), &[42u8; 32]);
265 }
266
267 #[test]
268 fn test_auth_key_from_bytes() {
269 let bytes = [5u8; 32];
270 let key = AuthenticationKey::from_bytes(&bytes).unwrap();
271 assert_eq!(key.to_bytes(), bytes);
272 }
273
274 #[test]
275 fn test_auth_key_from_bytes_invalid_length() {
276 let bytes = [5u8; 16];
277 let result = AuthenticationKey::from_bytes(&bytes);
278 assert!(result.is_err());
279 }
280
281 #[test]
282 fn test_auth_key_from_hex_with_prefix() {
283 let key = AuthenticationKey::new([0xab; 32]);
284 let hex = key.to_hex();
285 assert!(hex.starts_with("0x"));
286 let restored = AuthenticationKey::from_hex(&hex).unwrap();
287 assert_eq!(key, restored);
288 }
289
290 #[test]
291 fn test_auth_key_from_hex_without_prefix() {
292 let key = AuthenticationKey::new([0xcd; 32]);
293 let hex = key.to_hex();
294 let hex_without_prefix = hex.trim_start_matches("0x");
295 let restored = AuthenticationKey::from_hex(hex_without_prefix).unwrap();
296 assert_eq!(key, restored);
297 }
298
299 #[test]
300 fn test_auth_key_display() {
301 let key = AuthenticationKey::new([0xff; 32]);
302 let display = format!("{key}");
303 assert!(display.starts_with("0x"));
304 assert_eq!(display.len(), 66); }
306
307 #[test]
308 fn test_auth_key_debug() {
309 let key = AuthenticationKey::new([0xaa; 32]);
310 let debug = format!("{key:?}");
311 assert!(debug.contains("AuthenticationKey"));
312 }
313
314 #[test]
315 fn test_auth_key_from_array() {
316 let bytes = [7u8; 32];
317 let key: AuthenticationKey = bytes.into();
318 assert_eq!(key.to_bytes(), bytes);
319 }
320
321 #[test]
322 fn test_auth_key_to_array() {
323 let key = AuthenticationKey::new([8u8; 32]);
324 let bytes: [u8; 32] = key.into();
325 assert_eq!(bytes, [8u8; 32]);
326 }
327
328 #[test]
329 fn test_auth_key_to_account_address() {
330 let key = AuthenticationKey::new([9u8; 32]);
331 let address: AccountAddress = key.into();
332 assert_eq!(address.as_bytes(), &[9u8; 32]);
333 }
334
335 #[cfg(feature = "ed25519")]
336 #[test]
337 fn test_any_account_from_ed25519() {
338 let ed25519 = super::super::Ed25519Account::generate();
339 let any_account: AnyAccount = ed25519.into();
340 if let AnyAccount::Ed25519(account) = any_account {
341 assert!(!account.address().is_zero());
342 } else {
343 panic!("Expected Ed25519 account");
344 }
345 }
346
347 #[cfg(feature = "ed25519")]
348 #[test]
349 fn test_any_account_ed25519_trait_methods() {
350 let ed25519 = super::super::Ed25519Account::generate();
351 let address = ed25519.address();
352 let auth_key = ed25519.authentication_key();
353 let any_account: AnyAccount = ed25519.into();
354
355 assert_eq!(any_account.address(), address);
356 assert_eq!(any_account.authentication_key(), auth_key);
357 assert!(!any_account.public_key_bytes().is_empty());
358
359 let sig = any_account.sign(b"test message").unwrap();
360 assert!(!sig.is_empty());
361 }
362
363 #[cfg(feature = "secp256k1")]
364 #[test]
365 fn test_any_account_from_secp256k1() {
366 let secp = super::super::Secp256k1Account::generate();
367 let any_account: AnyAccount = secp.into();
368 if let AnyAccount::Secp256k1(account) = any_account {
369 assert!(!account.address().is_zero());
370 } else {
371 panic!("Expected Secp256k1 account");
372 }
373 }
374
375 #[cfg(feature = "secp256k1")]
376 #[test]
377 fn test_any_account_secp256k1_trait_methods() {
378 let secp = super::super::Secp256k1Account::generate();
379 let address = secp.address();
380 let auth_key = secp.authentication_key();
381 let any_account: AnyAccount = secp.into();
382
383 assert_eq!(any_account.address(), address);
384 assert_eq!(any_account.authentication_key(), auth_key);
385 assert!(!any_account.public_key_bytes().is_empty());
386
387 let sig = any_account.sign(b"test message").unwrap();
388 assert!(!sig.is_empty());
389 }
390
391 #[cfg(feature = "ed25519")]
392 #[test]
393 fn test_any_account_from_multi_ed25519() {
394 use crate::crypto::Ed25519PrivateKey;
395
396 let keys: Vec<_> = (0..2).map(|_| Ed25519PrivateKey::generate()).collect();
397 let account = super::super::MultiEd25519Account::new(keys, 2).unwrap();
398 let any_account: AnyAccount = account.into();
399
400 if let AnyAccount::MultiEd25519(_) = any_account {
401 } else {
403 panic!("Expected MultiEd25519 account");
404 }
405 }
406
407 #[cfg(feature = "ed25519")]
408 #[test]
409 fn test_any_account_multi_ed25519_trait_methods() {
410 use crate::crypto::Ed25519PrivateKey;
411
412 let keys: Vec<_> = (0..2).map(|_| Ed25519PrivateKey::generate()).collect();
413 let account = super::super::MultiEd25519Account::new(keys, 2).unwrap();
414 let address = account.address();
415 let auth_key = account.authentication_key();
416 let any_account: AnyAccount = account.into();
417
418 assert_eq!(any_account.address(), address);
419 assert_eq!(any_account.authentication_key(), auth_key);
420 assert!(!any_account.public_key_bytes().is_empty());
421 assert!(any_account.signature_scheme() > 0);
422
423 let sig = any_account.sign(b"test").unwrap();
424 assert!(!sig.is_empty());
425 }
426
427 #[cfg(feature = "ed25519")]
428 #[test]
429 fn test_any_account_from_multi_key() {
430 use crate::account::AnyPrivateKey;
431 use crate::crypto::Ed25519PrivateKey;
432
433 let keys: Vec<_> = (0..2)
434 .map(|_| AnyPrivateKey::ed25519(Ed25519PrivateKey::generate()))
435 .collect();
436 let account = super::super::MultiKeyAccount::new(keys, 2).unwrap();
437 let any_account: AnyAccount = account.into();
438
439 if let AnyAccount::MultiKey(_) = any_account {
440 } else {
442 panic!("Expected MultiKey account");
443 }
444 }
445
446 #[cfg(feature = "ed25519")]
447 #[test]
448 fn test_any_account_multi_key_trait_methods() {
449 use crate::account::AnyPrivateKey;
450 use crate::crypto::Ed25519PrivateKey;
451
452 let keys: Vec<_> = (0..2)
453 .map(|_| AnyPrivateKey::ed25519(Ed25519PrivateKey::generate()))
454 .collect();
455 let account = super::super::MultiKeyAccount::new(keys, 2).unwrap();
456 let address = account.address();
457 let auth_key = account.authentication_key();
458 let any_account: AnyAccount = account.into();
459
460 assert_eq!(any_account.address(), address);
461 assert_eq!(any_account.authentication_key(), auth_key);
462 assert!(!any_account.public_key_bytes().is_empty());
463
464 let sig = any_account.sign(b"test").unwrap();
465 assert!(!sig.is_empty());
466 }
467
468 #[test]
469 fn test_auth_key_json_serialization() {
470 let key = AuthenticationKey::new([0xab; 32]);
471 let json = serde_json::to_string(&key).unwrap();
472 let restored: AuthenticationKey = serde_json::from_str(&json).unwrap();
473 assert_eq!(key, restored);
474 }
475
476 #[test]
477 fn test_auth_key_hash() {
478 use std::collections::HashSet;
479 let key1 = AuthenticationKey::new([1u8; 32]);
480 let key2 = AuthenticationKey::new([2u8; 32]);
481
482 let mut set = HashSet::new();
483 set.insert(key1);
484 set.insert(key2);
485 assert_eq!(set.len(), 2);
486 assert!(set.contains(&key1));
487 }
488
489 #[test]
490 fn test_auth_key_clone() {
491 let key = AuthenticationKey::new([42u8; 32]);
492 let cloned = key;
493 assert_eq!(key, cloned);
494 }
495
496 #[test]
497 fn test_any_account_debug() {
498 #[cfg(feature = "ed25519")]
499 {
500 let ed25519 = super::super::Ed25519Account::generate();
501 let any_account: AnyAccount = ed25519.into();
502 let debug = format!("{any_account:?}");
503 assert!(debug.contains("Ed25519"));
504 }
505 }
506}