1use crate::types::AccountAddress;
4use serde::ser::{SerializeTuple, SerializeTupleVariant};
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7fn serialize_raw_bytes<S: Serializer>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
21 let mut tup = serializer.serialize_tuple(bytes.len())?;
24 for byte in bytes {
25 tup.serialize_element(byte)?;
26 }
27 tup.end()
28}
29
30#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct Ed25519PublicKey(pub [u8; 32]);
34
35impl Serialize for Ed25519PublicKey {
36 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
37 serde_bytes::Bytes::new(&self.0).serialize(serializer)
40 }
41}
42
43impl<'de> Deserialize<'de> for Ed25519PublicKey {
44 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
45 let bytes: Vec<u8> = serde_bytes::deserialize(deserializer)?;
47 if bytes.len() != 32 {
48 return Err(serde::de::Error::invalid_length(bytes.len(), &"32 bytes"));
49 }
50 let mut arr = [0u8; 32];
51 arr.copy_from_slice(&bytes);
52 Ok(Ed25519PublicKey(arr))
53 }
54}
55
56impl From<Vec<u8>> for Ed25519PublicKey {
57 fn from(bytes: Vec<u8>) -> Self {
64 assert!(
65 bytes.len() == 32,
66 "Ed25519PublicKey requires exactly 32 bytes, got {}",
67 bytes.len()
68 );
69 let mut arr = [0u8; 32];
70 arr.copy_from_slice(&bytes);
71 Ed25519PublicKey(arr)
72 }
73}
74
75impl Ed25519PublicKey {
76 pub fn try_from_bytes(bytes: &[u8]) -> crate::error::AptosResult<Self> {
84 if bytes.len() != 32 {
85 return Err(crate::error::AptosError::InvalidPublicKey(format!(
86 "Ed25519PublicKey requires exactly 32 bytes, got {}",
87 bytes.len()
88 )));
89 }
90 let mut arr = [0u8; 32];
91 arr.copy_from_slice(bytes);
92 Ok(Ed25519PublicKey(arr))
93 }
94}
95
96#[derive(Clone, Debug, PartialEq, Eq)]
99pub struct Ed25519Signature(pub [u8; 64]);
100
101impl Serialize for Ed25519Signature {
102 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
103 serde_bytes::Bytes::new(&self.0).serialize(serializer)
106 }
107}
108
109impl<'de> Deserialize<'de> for Ed25519Signature {
110 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
111 let bytes: Vec<u8> = serde_bytes::deserialize(deserializer)?;
113 if bytes.len() != 64 {
114 return Err(serde::de::Error::invalid_length(bytes.len(), &"64 bytes"));
115 }
116 let mut arr = [0u8; 64];
117 arr.copy_from_slice(&bytes);
118 Ok(Ed25519Signature(arr))
119 }
120}
121
122impl From<Vec<u8>> for Ed25519Signature {
123 fn from(bytes: Vec<u8>) -> Self {
130 assert!(
131 bytes.len() == 64,
132 "Ed25519Signature requires exactly 64 bytes, got {}",
133 bytes.len()
134 );
135 let mut arr = [0u8; 64];
136 arr.copy_from_slice(&bytes);
137 Ed25519Signature(arr)
138 }
139}
140
141impl Ed25519Signature {
142 pub fn try_from_bytes(bytes: &[u8]) -> crate::error::AptosResult<Self> {
148 if bytes.len() != 64 {
149 return Err(crate::error::AptosError::InvalidSignature(format!(
150 "Ed25519Signature requires exactly 64 bytes, got {}",
151 bytes.len()
152 )));
153 }
154 let mut arr = [0u8; 64];
155 arr.copy_from_slice(bytes);
156 Ok(Ed25519Signature(arr))
157 }
158}
159
160#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
172pub enum TransactionAuthenticator {
173 Ed25519 {
175 public_key: Ed25519PublicKey,
177 signature: Ed25519Signature,
179 },
180 MultiEd25519 {
182 public_key: Vec<u8>,
184 signature: Vec<u8>,
186 },
187 MultiAgent {
189 sender: AccountAuthenticator,
191 secondary_signer_addresses: Vec<AccountAddress>,
193 secondary_signers: Vec<AccountAuthenticator>,
195 },
196 FeePayer {
198 sender: AccountAuthenticator,
200 secondary_signer_addresses: Vec<AccountAddress>,
202 secondary_signers: Vec<AccountAuthenticator>,
204 fee_payer_address: AccountAddress,
206 fee_payer_signer: AccountAuthenticator,
208 },
209 SingleSender {
212 sender: AccountAuthenticator,
214 },
215}
216
217#[derive(Clone, Debug, PartialEq, Eq)]
229pub enum AccountAuthenticator {
230 Ed25519 {
232 public_key: Ed25519PublicKey,
234 signature: Ed25519Signature,
236 },
237 MultiEd25519 {
239 public_key: Vec<u8>,
241 signature: Vec<u8>,
243 },
244 SingleKey {
246 public_key: Vec<u8>,
248 signature: Vec<u8>,
250 },
251 MultiKey {
253 public_key: Vec<u8>,
255 signature: Vec<u8>,
257 },
258 NoAccountAuthenticator,
260 #[cfg(feature = "keyless")]
263 Keyless {
264 public_key: Vec<u8>,
266 signature: Vec<u8>,
268 },
269}
270
271const ACCOUNT_AUTH_TAG_ED25519: u32 = 0;
273const ACCOUNT_AUTH_TAG_MULTI_ED25519: u32 = 1;
274const ACCOUNT_AUTH_TAG_SINGLE_KEY: u32 = 2;
275const ACCOUNT_AUTH_TAG_MULTI_KEY: u32 = 3;
276const ACCOUNT_AUTH_TAG_NO_ACCOUNT: u32 = 4;
277#[cfg(feature = "keyless")]
278const ACCOUNT_AUTH_TAG_KEYLESS: u32 = 5;
279
280impl Serialize for AccountAuthenticator {
281 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
282 match self {
283 AccountAuthenticator::Ed25519 {
284 public_key,
285 signature,
286 } => {
287 let mut tv = serializer.serialize_tuple_variant(
290 "AccountAuthenticator",
291 ACCOUNT_AUTH_TAG_ED25519,
292 "Ed25519",
293 2,
294 )?;
295 tv.serialize_field(public_key)?;
296 tv.serialize_field(signature)?;
297 tv.end()
298 }
299 AccountAuthenticator::MultiEd25519 {
300 public_key,
301 signature,
302 } => {
303 let mut tv = serializer.serialize_tuple_variant(
307 "AccountAuthenticator",
308 ACCOUNT_AUTH_TAG_MULTI_ED25519,
309 "MultiEd25519",
310 2,
311 )?;
312 tv.serialize_field(public_key)?;
313 tv.serialize_field(signature)?;
314 tv.end()
315 }
316 AccountAuthenticator::SingleKey {
317 public_key,
318 signature,
319 } => {
320 serialize_account_auth_raw_pair(
323 serializer,
324 ACCOUNT_AUTH_TAG_SINGLE_KEY,
325 "SingleKey",
326 public_key,
327 signature,
328 )
329 }
330 AccountAuthenticator::MultiKey {
331 public_key,
332 signature,
333 } => {
334 serialize_account_auth_raw_pair(
337 serializer,
338 ACCOUNT_AUTH_TAG_MULTI_KEY,
339 "MultiKey",
340 public_key,
341 signature,
342 )
343 }
344 AccountAuthenticator::NoAccountAuthenticator => serializer
345 .serialize_tuple_variant(
346 "AccountAuthenticator",
347 ACCOUNT_AUTH_TAG_NO_ACCOUNT,
348 "NoAccountAuthenticator",
349 0,
350 )
351 .and_then(SerializeTupleVariant::end),
352 #[cfg(feature = "keyless")]
353 AccountAuthenticator::Keyless {
354 public_key,
355 signature,
356 } => serialize_account_auth_raw_pair(
357 serializer,
358 ACCOUNT_AUTH_TAG_KEYLESS,
359 "Keyless",
360 public_key,
361 signature,
362 ),
363 }
364 }
365}
366
367fn serialize_account_auth_raw_pair<S: Serializer>(
368 serializer: S,
369 tag: u32,
370 name: &'static str,
371 public_key: &[u8],
372 signature: &[u8],
373) -> Result<S::Ok, S::Error> {
374 struct Raw<'a>(&'a [u8]);
381 impl Serialize for Raw<'_> {
382 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
383 serialize_raw_bytes(self.0, s)
384 }
385 }
386
387 let mut tv = serializer.serialize_tuple_variant("AccountAuthenticator", tag, name, 2)?;
388 tv.serialize_field(&Raw(public_key))?;
389 tv.serialize_field(&Raw(signature))?;
390 tv.end()
391}
392
393impl<'de> Deserialize<'de> for AccountAuthenticator {
394 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
395 #[derive(Deserialize)]
410 enum Compat {
411 Ed25519 {
412 public_key: Ed25519PublicKey,
413 signature: Ed25519Signature,
414 },
415 MultiEd25519 {
416 public_key: Vec<u8>,
417 signature: Vec<u8>,
418 },
419 SingleKey {
420 public_key: Vec<u8>,
421 signature: Vec<u8>,
422 },
423 MultiKey {
424 public_key: Vec<u8>,
425 signature: Vec<u8>,
426 },
427 NoAccountAuthenticator,
428 #[cfg(feature = "keyless")]
429 Keyless {
430 public_key: Vec<u8>,
431 signature: Vec<u8>,
432 },
433 }
434
435 Compat::deserialize(deserializer).map(|c| match c {
436 Compat::Ed25519 {
437 public_key,
438 signature,
439 } => AccountAuthenticator::Ed25519 {
440 public_key,
441 signature,
442 },
443 Compat::MultiEd25519 {
444 public_key,
445 signature,
446 } => AccountAuthenticator::MultiEd25519 {
447 public_key,
448 signature,
449 },
450 Compat::SingleKey {
451 public_key,
452 signature,
453 } => AccountAuthenticator::SingleKey {
454 public_key,
455 signature,
456 },
457 Compat::MultiKey {
458 public_key,
459 signature,
460 } => AccountAuthenticator::MultiKey {
461 public_key,
462 signature,
463 },
464 Compat::NoAccountAuthenticator => AccountAuthenticator::NoAccountAuthenticator,
465 #[cfg(feature = "keyless")]
466 Compat::Keyless {
467 public_key,
468 signature,
469 } => AccountAuthenticator::Keyless {
470 public_key,
471 signature,
472 },
473 })
474 }
475}
476
477#[derive(Clone, Debug, PartialEq, Eq)]
479pub struct Ed25519Authenticator {
480 pub public_key: Vec<u8>,
482 pub signature: Vec<u8>,
484}
485
486impl Ed25519Authenticator {
487 pub fn new(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
489 Self {
490 public_key,
491 signature,
492 }
493 }
494}
495
496impl From<Ed25519Authenticator> for TransactionAuthenticator {
497 fn from(auth: Ed25519Authenticator) -> Self {
498 TransactionAuthenticator::Ed25519 {
499 public_key: auth.public_key.into(),
500 signature: auth.signature.into(),
501 }
502 }
503}
504
505impl From<Ed25519Authenticator> for AccountAuthenticator {
506 fn from(auth: Ed25519Authenticator) -> Self {
507 AccountAuthenticator::Ed25519 {
508 public_key: auth.public_key.into(),
509 signature: auth.signature.into(),
510 }
511 }
512}
513
514impl TransactionAuthenticator {
515 pub fn ed25519(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
517 Self::Ed25519 {
518 public_key: public_key.into(),
519 signature: signature.into(),
520 }
521 }
522
523 pub fn multi_ed25519(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
525 Self::MultiEd25519 {
526 public_key,
527 signature,
528 }
529 }
530
531 pub fn multi_agent(
533 sender: AccountAuthenticator,
534 secondary_signer_addresses: Vec<AccountAddress>,
535 secondary_signers: Vec<AccountAuthenticator>,
536 ) -> Self {
537 Self::MultiAgent {
538 sender,
539 secondary_signer_addresses,
540 secondary_signers,
541 }
542 }
543
544 pub fn fee_payer(
546 sender: AccountAuthenticator,
547 secondary_signer_addresses: Vec<AccountAddress>,
548 secondary_signers: Vec<AccountAuthenticator>,
549 fee_payer_address: AccountAddress,
550 fee_payer_signer: AccountAuthenticator,
551 ) -> Self {
552 Self::FeePayer {
553 sender,
554 secondary_signer_addresses,
555 secondary_signers,
556 fee_payer_address,
557 fee_payer_signer,
558 }
559 }
560
561 pub fn single_sender(sender: AccountAuthenticator) -> Self {
564 Self::SingleSender { sender }
565 }
566
567 #[must_use]
576 pub fn for_simulate_endpoint(self) -> Self {
577 match self {
578 Self::Ed25519 {
579 public_key,
580 signature: _,
581 } => Self::Ed25519 {
582 public_key,
583 signature: Ed25519Signature([0u8; 64]),
584 },
585 Self::MultiEd25519 {
586 public_key,
587 signature,
588 } => Self::MultiEd25519 {
589 public_key,
590 signature: vec![0u8; signature.len()],
591 },
592 Self::MultiAgent {
593 sender,
594 secondary_signer_addresses,
595 secondary_signers,
596 } => {
597 let secondary: Vec<AccountAuthenticator> = secondary_signers
598 .into_iter()
599 .map(AccountAuthenticator::for_simulate_endpoint)
600 .collect();
601 Self::multi_agent(
602 sender.for_simulate_endpoint(),
603 secondary_signer_addresses,
604 secondary,
605 )
606 }
607 Self::FeePayer {
608 sender,
609 secondary_signer_addresses,
610 secondary_signers,
611 fee_payer_address,
612 fee_payer_signer,
613 } => {
614 let secondary: Vec<AccountAuthenticator> = secondary_signers
615 .into_iter()
616 .map(AccountAuthenticator::for_simulate_endpoint)
617 .collect();
618 Self::fee_payer(
619 sender.for_simulate_endpoint(),
620 secondary_signer_addresses,
621 secondary,
622 fee_payer_address,
623 fee_payer_signer.for_simulate_endpoint(),
624 )
625 }
626 Self::SingleSender { sender } => Self::single_sender(sender.for_simulate_endpoint()),
627 }
628 }
629}
630
631impl AccountAuthenticator {
632 pub fn ed25519(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
634 Self::Ed25519 {
635 public_key: public_key.into(),
636 signature: signature.into(),
637 }
638 }
639 pub fn single_key(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
641 Self::SingleKey {
642 public_key,
643 signature,
644 }
645 }
646
647 pub fn multi_key(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
649 Self::MultiKey {
650 public_key,
651 signature,
652 }
653 }
654
655 pub fn no_account_authenticator() -> Self {
657 Self::NoAccountAuthenticator
658 }
659
660 #[must_use]
674 pub fn for_simulate_endpoint(self) -> Self {
675 match self {
676 Self::NoAccountAuthenticator => Self::NoAccountAuthenticator,
677 Self::Ed25519 {
678 public_key,
679 signature: _,
680 } => Self::Ed25519 {
681 public_key,
682 signature: Ed25519Signature([0u8; 64]),
683 },
684 Self::MultiEd25519 {
685 public_key,
686 signature,
687 } => Self::MultiEd25519 {
688 public_key,
689 signature: vec![0u8; signature.len()],
690 },
691 Self::SingleKey { .. } => Self::NoAccountAuthenticator,
692 Self::MultiKey {
693 public_key,
694 signature,
695 } => Self::MultiKey {
696 public_key,
697 signature: vec![0u8; signature.len()],
698 },
699 #[cfg(feature = "keyless")]
700 Self::Keyless { .. } => Self::NoAccountAuthenticator,
701 }
702 }
703
704 #[cfg(feature = "keyless")]
711 pub fn keyless(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
712 Self::Keyless {
713 public_key,
714 signature,
715 }
716 }
717
718 pub fn verify(&self, message: &[u8]) -> crate::error::AptosResult<()> {
724 match self {
725 #[cfg(feature = "ed25519")]
726 Self::Ed25519 {
727 public_key,
728 signature,
729 } => {
730 let public_key = crate::crypto::Ed25519PublicKey::from_bytes(&public_key.0)?;
731 let signature = crate::crypto::Ed25519Signature::from_bytes(&signature.0)?;
732 public_key.verify(message, &signature)
733 }
734 #[cfg(not(feature = "ed25519"))]
735 Self::Ed25519 { .. } => Err(crate::error::AptosError::FeatureNotEnabled(
736 "Ed25519 verification".into(),
737 )),
738 #[cfg(feature = "ed25519")]
739 Self::MultiEd25519 {
740 public_key,
741 signature,
742 } => {
743 let public_key = crate::crypto::MultiEd25519PublicKey::from_bytes(public_key)?;
744 let signature = crate::crypto::MultiEd25519Signature::from_bytes(signature)?;
745 public_key.verify(message, &signature)
746 }
747 #[cfg(not(feature = "ed25519"))]
748 Self::MultiEd25519 { .. } => Err(crate::error::AptosError::FeatureNotEnabled(
749 "MultiEd25519 verification".into(),
750 )),
751 Self::SingleKey {
752 public_key,
753 signature,
754 } => {
755 let pk = crate::crypto::AnyPublicKey::from_bcs_bytes(public_key)?;
756 let sig = crate::crypto::AnySignature::from_bcs_bytes(signature)?;
757 pk.verify(message, &sig)
758 }
759 Self::MultiKey {
760 public_key,
761 signature,
762 } => {
763 let pk = crate::crypto::MultiKeyPublicKey::from_bytes(public_key)?;
764 let sig = crate::crypto::MultiKeySignature::from_bytes(signature)?;
765 pk.verify(message, &sig)
766 }
767 Self::NoAccountAuthenticator => Err(crate::error::AptosError::InvalidSignature(
768 "no account authenticator cannot be verified".into(),
769 )),
770 #[cfg(feature = "keyless")]
771 Self::Keyless { .. } => Err(crate::error::AptosError::FeatureNotEnabled(
772 "local keyless verification".into(),
773 )),
774 }
775 }
776
777 pub fn derived_address(&self) -> crate::error::AptosResult<AccountAddress> {
783 match self {
784 #[cfg(feature = "ed25519")]
785 Self::Ed25519 { public_key, .. } => {
786 let public_key = crate::crypto::Ed25519PublicKey::from_bytes(&public_key.0)?;
787 Ok(public_key.to_address())
788 }
789 #[cfg(not(feature = "ed25519"))]
790 Self::Ed25519 { .. } => Err(crate::error::AptosError::FeatureNotEnabled(
791 "Ed25519 address derivation".into(),
792 )),
793 #[cfg(feature = "ed25519")]
794 Self::MultiEd25519 { public_key, .. } => {
795 let public_key = crate::crypto::MultiEd25519PublicKey::from_bytes(public_key)?;
796 Ok(public_key.to_address())
797 }
798 #[cfg(not(feature = "ed25519"))]
799 Self::MultiEd25519 { .. } => Err(crate::error::AptosError::FeatureNotEnabled(
800 "MultiEd25519 address derivation".into(),
801 )),
802 Self::SingleKey { public_key, .. } => Ok(AccountAddress::new(
803 crate::crypto::derive_authentication_key(
804 public_key,
805 crate::crypto::SINGLE_KEY_SCHEME,
806 ),
807 )),
808 Self::MultiKey { public_key, .. } => {
809 let pk = crate::crypto::MultiKeyPublicKey::from_bytes(public_key)?;
810 Ok(pk.to_address())
811 }
812 Self::NoAccountAuthenticator => Err(crate::error::AptosError::InvalidSignature(
813 "no account authenticator has no derived address".into(),
814 )),
815 #[cfg(feature = "keyless")]
816 Self::Keyless { .. } => Err(crate::error::AptosError::FeatureNotEnabled(
817 "local keyless address derivation".into(),
818 )),
819 }
820 }
821}
822
823#[cfg(test)]
824mod tests {
825 use super::*;
826 use crate::crypto::{AnyPublicKey, AnySignature, MultiKeyPublicKey, MultiKeySignature};
827
828 #[test]
829 fn test_ed25519_authenticator() {
830 let mut pk = [0u8; 32];
831 pk[0..3].copy_from_slice(&[1, 2, 3]);
832 let mut sig = [0u8; 64];
833 sig[0..3].copy_from_slice(&[4, 5, 6]);
834
835 let auth = Ed25519Authenticator::new(pk.to_vec(), sig.to_vec());
836 let txn_auth: TransactionAuthenticator = auth.into();
837
838 match txn_auth {
839 TransactionAuthenticator::Ed25519 {
840 public_key,
841 signature,
842 } => {
843 assert_eq!(public_key.0[0..3], [1, 2, 3]);
844 assert_eq!(signature.0[0..3], [4, 5, 6]);
845 }
846 _ => panic!("wrong authenticator type"),
847 }
848 }
849
850 #[test]
851 fn test_multi_agent_authenticator() {
852 let sender = AccountAuthenticator::ed25519(vec![0; 32], vec![0; 64]);
853 let auth = TransactionAuthenticator::multi_agent(sender, vec![], vec![]);
854
855 match auth {
856 TransactionAuthenticator::MultiAgent { .. } => {}
857 _ => panic!("wrong authenticator type"),
858 }
859 }
860
861 #[test]
862 fn test_ed25519_bcs_format() {
863 let auth = TransactionAuthenticator::Ed25519 {
865 public_key: Ed25519PublicKey([0xab; 32]),
866 signature: Ed25519Signature([0xcd; 64]),
867 };
868 let bcs = aptos_bcs::to_bytes(&auth).unwrap();
869
870 assert_eq!(bcs[0], 0, "Ed25519 variant index should be 0");
872 assert_eq!(bcs[1], 32, "Pubkey length prefix should be 32");
874 assert_eq!(bcs[2], 0xab, "First pubkey byte should be 0xab");
876 assert_eq!(bcs[34], 64, "Signature length prefix should be 64");
878 assert_eq!(bcs[35], 0xcd, "First signature byte should be 0xcd");
880 assert_eq!(bcs.len(), 99, "BCS length should be 99");
882 }
883
884 #[test]
885 fn test_ed25519_authenticator_into_account_authenticator() {
886 let auth = Ed25519Authenticator::new(vec![0xaa; 32], vec![0xbb; 64]);
887 let account_auth: AccountAuthenticator = auth.into();
888
889 match account_auth {
890 AccountAuthenticator::Ed25519 {
891 public_key,
892 signature,
893 } => {
894 assert_eq!(public_key.0[0], 0xaa);
895 assert_eq!(signature.0[0], 0xbb);
896 }
897 _ => panic!("Expected Ed25519 variant"),
898 }
899 }
900
901 #[test]
902 fn test_transaction_authenticator_ed25519() {
903 let auth = TransactionAuthenticator::ed25519(vec![0x11; 32], vec![0x22; 64]);
904 match auth {
905 TransactionAuthenticator::Ed25519 {
906 public_key,
907 signature,
908 } => {
909 assert_eq!(public_key.0[0], 0x11);
910 assert_eq!(signature.0[0], 0x22);
911 }
912 _ => panic!("Expected Ed25519 variant"),
913 }
914 }
915
916 #[test]
917 fn test_transaction_authenticator_multi_ed25519() {
918 let auth = TransactionAuthenticator::multi_ed25519(vec![0x33; 64], vec![0x44; 128]);
919 match auth {
920 TransactionAuthenticator::MultiEd25519 {
921 public_key,
922 signature,
923 } => {
924 assert_eq!(public_key.len(), 64);
925 assert_eq!(signature.len(), 128);
926 }
927 _ => panic!("Expected MultiEd25519 variant"),
928 }
929 }
930
931 #[test]
932 fn test_fee_payer_authenticator() {
933 let sender = AccountAuthenticator::ed25519(vec![0; 32], vec![0; 64]);
934 let fee_payer = AccountAuthenticator::ed25519(vec![1; 32], vec![1; 64]);
935 let fee_payer_address = AccountAddress::from_hex("0x123").unwrap();
936
937 let auth = TransactionAuthenticator::fee_payer(
938 sender,
939 vec![],
940 vec![],
941 fee_payer_address,
942 fee_payer,
943 );
944
945 match auth {
946 TransactionAuthenticator::FeePayer {
947 fee_payer_address: addr,
948 ..
949 } => {
950 assert_eq!(addr, fee_payer_address);
951 }
952 _ => panic!("Expected FeePayer variant"),
953 }
954 }
955
956 #[test]
957 fn test_single_sender_authenticator() {
958 let sender = AccountAuthenticator::ed25519(vec![0x55; 32], vec![0x66; 64]);
959 let auth = TransactionAuthenticator::single_sender(sender);
960
961 match auth {
962 TransactionAuthenticator::SingleSender { sender } => match sender {
963 AccountAuthenticator::Ed25519 { public_key, .. } => {
964 assert_eq!(public_key.0[0], 0x55);
965 }
966 _ => panic!("Expected Ed25519 sender"),
967 },
968 _ => panic!("Expected SingleSender variant"),
969 }
970 }
971
972 #[test]
973 fn test_account_authenticator_multi_key() {
974 let auth = AccountAuthenticator::multi_key(vec![0x77; 100], vec![0x88; 200]);
975 match auth {
976 AccountAuthenticator::MultiKey {
977 public_key,
978 signature,
979 } => {
980 assert_eq!(public_key.len(), 100);
981 assert_eq!(signature.len(), 200);
982 }
983 _ => panic!("Expected MultiKey variant"),
984 }
985 }
986
987 #[test]
988 fn test_ed25519_public_key_from_vec() {
989 let pk: Ed25519PublicKey = vec![0x12; 32].into();
990 assert_eq!(pk.0[0], 0x12);
991 assert_eq!(pk.0.len(), 32);
992 }
993
994 #[test]
995 fn test_ed25519_signature_from_vec() {
996 let sig: Ed25519Signature = vec![0x34; 64].into();
997 assert_eq!(sig.0[0], 0x34);
998 assert_eq!(sig.0.len(), 64);
999 }
1000
1001 #[test]
1002 fn test_ed25519_public_key_bcs_roundtrip() {
1003 let pk = Ed25519PublicKey([0xef; 32]);
1004 let serialized = aptos_bcs::to_bytes(&pk).unwrap();
1005 assert_eq!(serialized.len(), 33);
1007 assert_eq!(serialized[0], 32); let deserialized: Ed25519PublicKey = aptos_bcs::from_bytes(&serialized).unwrap();
1009 assert_eq!(pk, deserialized);
1010 }
1011
1012 #[test]
1013 fn test_ed25519_signature_bcs_roundtrip() {
1014 let sig = Ed25519Signature([0x99; 64]);
1015 let serialized = aptos_bcs::to_bytes(&sig).unwrap();
1016 let deserialized: Ed25519Signature = aptos_bcs::from_bytes(&serialized).unwrap();
1017 assert_eq!(sig, deserialized);
1018 }
1019
1020 #[test]
1021 fn test_multi_agent_with_secondary_signers() {
1022 let sender = AccountAuthenticator::ed25519(vec![0; 32], vec![0; 64]);
1023 let secondary_signer1 = AccountAuthenticator::ed25519(vec![1; 32], vec![1; 64]);
1024 let secondary_signer2 = AccountAuthenticator::ed25519(vec![2; 32], vec![2; 64]);
1025 let addr1 = AccountAddress::from_hex("0x111").unwrap();
1026 let addr2 = AccountAddress::from_hex("0x222").unwrap();
1027
1028 let auth = TransactionAuthenticator::multi_agent(
1029 sender,
1030 vec![addr1, addr2],
1031 vec![secondary_signer1, secondary_signer2],
1032 );
1033
1034 match auth {
1035 TransactionAuthenticator::MultiAgent {
1036 secondary_signer_addresses,
1037 secondary_signers,
1038 ..
1039 } => {
1040 assert_eq!(secondary_signer_addresses.len(), 2);
1041 assert_eq!(secondary_signers.len(), 2);
1042 }
1043 _ => panic!("Expected MultiAgent variant"),
1044 }
1045 }
1046
1047 #[test]
1048 fn test_transaction_authenticator_bcs_roundtrip() {
1049 let auth = TransactionAuthenticator::Ed25519 {
1050 public_key: Ed25519PublicKey([0x11; 32]),
1051 signature: Ed25519Signature([0x22; 64]),
1052 };
1053
1054 let serialized = aptos_bcs::to_bytes(&auth).unwrap();
1055 let deserialized: TransactionAuthenticator = aptos_bcs::from_bytes(&serialized).unwrap();
1056
1057 assert_eq!(auth, deserialized);
1058 }
1059
1060 #[test]
1061 fn test_account_authenticator_bcs_roundtrip() {
1062 let auth = AccountAuthenticator::Ed25519 {
1063 public_key: Ed25519PublicKey([0x33; 32]),
1064 signature: Ed25519Signature([0x44; 64]),
1065 };
1066
1067 let serialized = aptos_bcs::to_bytes(&auth).unwrap();
1068 let deserialized: AccountAuthenticator = aptos_bcs::from_bytes(&serialized).unwrap();
1069
1070 assert_eq!(auth, deserialized);
1071 }
1072
1073 #[test]
1074 fn test_account_authenticator_single_key() {
1075 let auth = AccountAuthenticator::single_key(vec![0x55; 33], vec![0x66; 65]);
1076 match auth {
1077 AccountAuthenticator::SingleKey {
1078 public_key,
1079 signature,
1080 } => {
1081 assert_eq!(public_key.len(), 33);
1082 assert_eq!(signature.len(), 65);
1083 }
1084 _ => panic!("Expected SingleKey variant"),
1085 }
1086 }
1087
1088 #[test]
1089 fn test_account_authenticator_single_key_bcs_wire_format() {
1090 let pk = vec![0x77; 33]; let sig = vec![0x88; 65]; let auth = AccountAuthenticator::SingleKey {
1102 public_key: pk.clone(),
1103 signature: sig.clone(),
1104 };
1105
1106 let serialized = aptos_bcs::to_bytes(&auth).unwrap();
1107 let mut expected = Vec::new();
1108 expected.push(2u8); expected.extend_from_slice(&pk);
1110 expected.extend_from_slice(&sig);
1111 assert_eq!(
1112 serialized, expected,
1113 "SingleKey wire format must be variant tag + raw pubkey bytes + raw signature bytes \
1114 (no inner length prefixes)"
1115 );
1116 }
1117
1118 #[cfg(feature = "ed25519")]
1119 #[test]
1120 fn test_account_authenticator_single_key_verify_and_derived_address() {
1121 use crate::crypto::{Ed25519PrivateKey, SINGLE_KEY_SCHEME, derive_authentication_key};
1122
1123 let private_key = Ed25519PrivateKey::generate();
1124 let message = b"single-key verify test";
1125 let public_key = crate::crypto::AnyPublicKey::ed25519(&private_key.public_key());
1126 let signature = crate::crypto::AnySignature::ed25519(&private_key.sign(message));
1127 let auth =
1128 AccountAuthenticator::single_key(public_key.to_bcs_bytes(), signature.to_bcs_bytes());
1129
1130 auth.verify(message).unwrap();
1131 let expected = AccountAddress::new(derive_authentication_key(
1132 &public_key.to_bcs_bytes(),
1133 SINGLE_KEY_SCHEME,
1134 ));
1135 assert_eq!(auth.derived_address().unwrap(), expected);
1136 }
1137
1138 #[cfg(feature = "ed25519")]
1139 #[test]
1140 fn test_account_authenticator_multi_ed25519_verify_and_derived_address() {
1141 use crate::account::{Account, MultiEd25519Account};
1142 use crate::crypto::Ed25519PrivateKey;
1143
1144 let account = MultiEd25519Account::new(
1145 vec![Ed25519PrivateKey::generate(), Ed25519PrivateKey::generate()],
1146 2,
1147 )
1148 .unwrap();
1149 let message = b"multi-ed25519 verify test";
1150 let auth = AccountAuthenticator::MultiEd25519 {
1151 public_key: account.public_key_bytes(),
1152 signature: account.sign(message).unwrap().to_bytes(),
1153 };
1154
1155 auth.verify(message).unwrap();
1156 assert_eq!(auth.derived_address().unwrap(), account.address());
1157 }
1158
1159 #[test]
1160 fn test_no_account_authenticator() {
1161 let auth = AccountAuthenticator::no_account_authenticator();
1162 match auth {
1163 AccountAuthenticator::NoAccountAuthenticator => {}
1164 _ => panic!("Expected NoAccountAuthenticator variant"),
1165 }
1166 }
1167
1168 #[cfg(feature = "ed25519")]
1169 #[test]
1170 fn test_account_authenticator_for_simulate_endpoint_single_key_to_no_account() {
1171 let auth = AccountAuthenticator::single_key(vec![0x01, 0x02], vec![0x03, 0x04]);
1172 let sanitized = auth.for_simulate_endpoint();
1173 assert!(matches!(
1174 sanitized,
1175 AccountAuthenticator::NoAccountAuthenticator
1176 ));
1177 }
1178
1179 #[cfg(feature = "ed25519")]
1180 #[test]
1181 fn test_transaction_authenticator_for_simulate_endpoint_single_sender_strips_single_key() {
1182 let sender = AccountAuthenticator::single_key(vec![0x05, 0x06], vec![0x07, 0x08]);
1183 let auth = TransactionAuthenticator::single_sender(sender);
1184 let sanitized = auth.for_simulate_endpoint();
1185 assert!(matches!(
1186 sanitized,
1187 TransactionAuthenticator::SingleSender { ref sender }
1188 if matches!(sender, AccountAuthenticator::NoAccountAuthenticator)
1189 ));
1190 }
1191
1192 #[cfg(feature = "ed25519")]
1193 #[test]
1194 fn test_transaction_authenticator_for_simulate_endpoint_ed25519_zeros_sig() {
1195 let auth = TransactionAuthenticator::Ed25519 {
1196 public_key: Ed25519PublicKey([7u8; 32]),
1197 signature: Ed25519Signature([9u8; 64]),
1198 };
1199 let sanitized = auth.for_simulate_endpoint();
1200 match sanitized {
1201 TransactionAuthenticator::Ed25519 { signature, .. } => {
1202 assert_eq!(signature.0, [0u8; 64]);
1203 }
1204 _ => panic!("expected Ed25519"),
1205 }
1206 }
1207
1208 #[test]
1209 fn test_no_account_authenticator_verify_and_derived_address_errors() {
1210 let auth = AccountAuthenticator::NoAccountAuthenticator;
1211 assert!(auth.verify(b"no-auth").is_err());
1212 assert!(auth.derived_address().is_err());
1213 }
1214
1215 #[cfg(feature = "keyless")]
1216 #[test]
1217 fn test_keyless_authenticator_verify_and_derived_address_not_enabled() {
1218 let auth = AccountAuthenticator::keyless(vec![0x11; 32], vec![0x22; 64]);
1219 assert!(auth.verify(b"keyless-local").is_err());
1220 assert!(auth.derived_address().is_err());
1221 }
1222
1223 #[test]
1224 fn test_no_account_authenticator_bcs_roundtrip() {
1225 let auth = AccountAuthenticator::NoAccountAuthenticator;
1226
1227 let serialized = aptos_bcs::to_bytes(&auth).unwrap();
1228 assert_eq!(
1230 serialized[0], 4,
1231 "NoAccountAuthenticator variant index should be 4"
1232 );
1233 assert_eq!(
1235 serialized.len(),
1236 1,
1237 "NoAccountAuthenticator should be 1 byte"
1238 );
1239 let deserialized: AccountAuthenticator = aptos_bcs::from_bytes(&serialized).unwrap();
1240 assert_eq!(auth, deserialized);
1241 }
1242
1243 #[test]
1244 fn test_single_sender_with_single_key() {
1245 let sender = AccountAuthenticator::single_key(vec![0x99; 33], vec![0xaa; 65]);
1246 let auth = TransactionAuthenticator::single_sender(sender);
1247
1248 match auth {
1249 TransactionAuthenticator::SingleSender { sender } => match sender {
1250 AccountAuthenticator::SingleKey { public_key, .. } => {
1251 assert_eq!(public_key.len(), 33);
1252 }
1253 _ => panic!("Expected SingleKey sender"),
1254 },
1255 _ => panic!("Expected SingleSender variant"),
1256 }
1257 }
1258
1259 #[test]
1260 fn test_account_authenticator_variant_indices() {
1261 let ed25519 = AccountAuthenticator::ed25519(vec![0; 32], vec![0; 64]);
1263 let multi_ed25519 = AccountAuthenticator::MultiEd25519 {
1264 public_key: vec![0; 64],
1265 signature: vec![0; 128],
1266 };
1267 let single_key = AccountAuthenticator::single_key(vec![0; 33], vec![0; 65]);
1268 let multi_key = AccountAuthenticator::multi_key(vec![0; 100], vec![0; 200]);
1269 let no_account = AccountAuthenticator::no_account_authenticator();
1270
1271 assert_eq!(aptos_bcs::to_bytes(&ed25519).unwrap()[0], 0, "Ed25519 = 0");
1272 assert_eq!(
1273 aptos_bcs::to_bytes(&multi_ed25519).unwrap()[0],
1274 1,
1275 "MultiEd25519 = 1"
1276 );
1277 assert_eq!(
1278 aptos_bcs::to_bytes(&single_key).unwrap()[0],
1279 2,
1280 "SingleKey = 2"
1281 );
1282 assert_eq!(
1283 aptos_bcs::to_bytes(&multi_key).unwrap()[0],
1284 3,
1285 "MultiKey = 3"
1286 );
1287 assert_eq!(
1288 aptos_bcs::to_bytes(&no_account).unwrap()[0],
1289 4,
1290 "NoAccountAuthenticator = 4"
1291 );
1292 }
1293
1294 #[test]
1295 fn test_ed25519_public_key_try_from_bytes_valid() {
1296 let bytes = vec![0x12; 32];
1297 let pk = Ed25519PublicKey::try_from_bytes(&bytes).unwrap();
1298 assert_eq!(pk.0[0], 0x12);
1299 }
1300
1301 #[test]
1302 fn test_ed25519_public_key_try_from_bytes_invalid_length() {
1303 let bytes = vec![0x12; 16]; let result = Ed25519PublicKey::try_from_bytes(&bytes);
1305 assert!(result.is_err());
1306 }
1307
1308 #[test]
1309 fn test_ed25519_signature_try_from_bytes_valid() {
1310 let bytes = vec![0x34; 64];
1311 let sig = Ed25519Signature::try_from_bytes(&bytes).unwrap();
1312 assert_eq!(sig.0[0], 0x34);
1313 }
1314
1315 #[test]
1316 fn test_ed25519_signature_try_from_bytes_invalid_length() {
1317 let bytes = vec![0x34; 32]; let result = Ed25519Signature::try_from_bytes(&bytes);
1319 assert!(result.is_err());
1320 }
1321
1322 #[test]
1323 fn test_transaction_authenticator_variant_indices() {
1324 let ed25519 = TransactionAuthenticator::ed25519(vec![0; 32], vec![0; 64]);
1326 let multi_ed25519 = TransactionAuthenticator::multi_ed25519(vec![0; 64], vec![0; 128]);
1327 let sender = AccountAuthenticator::ed25519(vec![0; 32], vec![0; 64]);
1328 let multi_agent = TransactionAuthenticator::multi_agent(sender.clone(), vec![], vec![]);
1329 let fee_payer = TransactionAuthenticator::fee_payer(
1330 sender.clone(),
1331 vec![],
1332 vec![],
1333 AccountAddress::ONE,
1334 sender.clone(),
1335 );
1336 let single_sender = TransactionAuthenticator::single_sender(sender);
1337
1338 assert_eq!(aptos_bcs::to_bytes(&ed25519).unwrap()[0], 0, "Ed25519 = 0");
1339 assert_eq!(
1340 aptos_bcs::to_bytes(&multi_ed25519).unwrap()[0],
1341 1,
1342 "MultiEd25519 = 1"
1343 );
1344 assert_eq!(
1345 aptos_bcs::to_bytes(&multi_agent).unwrap()[0],
1346 2,
1347 "MultiAgent = 2"
1348 );
1349 assert_eq!(
1350 aptos_bcs::to_bytes(&fee_payer).unwrap()[0],
1351 3,
1352 "FeePayer = 3"
1353 );
1354 assert_eq!(
1355 aptos_bcs::to_bytes(&single_sender).unwrap()[0],
1356 4,
1357 "SingleSender = 4"
1358 );
1359 }
1360
1361 #[test]
1362 fn test_single_key_single_sender_bcs_wire_format() {
1363 let mut pk = vec![0u8; 67];
1370 pk[0] = 0x02; pk[1] = 65; pk[2] = 0x04; let mut sig = vec![0u8; 66];
1374 sig[0] = 0x02; sig[1] = 64; let auth = AccountAuthenticator::single_key(pk.clone(), sig.clone());
1378 let bytes = aptos_bcs::to_bytes(&auth).unwrap();
1379 let mut expected_inner = Vec::new();
1380 expected_inner.push(2u8); expected_inner.extend_from_slice(&pk); expected_inner.extend_from_slice(&sig); assert_eq!(bytes, expected_inner);
1384
1385 let txn = TransactionAuthenticator::single_sender(auth);
1386 let bytes = aptos_bcs::to_bytes(&txn).unwrap();
1387 let mut expected_outer = Vec::new();
1388 expected_outer.push(4u8); expected_outer.extend_from_slice(&expected_inner);
1390 assert_eq!(bytes, expected_outer);
1391 }
1392
1393 #[test]
1394 fn test_multi_key_authenticator_bcs_wire_format() {
1395 let pk = vec![0xaa; 100];
1402 let sig = vec![0xbb; 200];
1403 let auth = AccountAuthenticator::multi_key(pk.clone(), sig.clone());
1404
1405 let serialized = aptos_bcs::to_bytes(&auth).unwrap();
1406 let mut expected = Vec::new();
1407 expected.push(3u8); expected.extend_from_slice(&pk);
1409 expected.extend_from_slice(&sig);
1410 assert_eq!(
1411 serialized, expected,
1412 "MultiKey wire format must be variant tag + raw pubkey bytes + raw signature bytes"
1413 );
1414 }
1415
1416 #[test]
1417 fn test_multi_key_authenticator_bcs_rejects_keyless_public_key() {
1418 let mk_pk = MultiKeyPublicKey::new(
1419 vec![AnyPublicKey::new(
1420 crate::crypto::AnyPublicKeyVariant::Keyless,
1421 vec![],
1422 )],
1423 1,
1424 )
1425 .unwrap();
1426 let mk_sig = MultiKeySignature::new(vec![(
1427 0,
1428 AnySignature::new(crate::crypto::AnyPublicKeyVariant::Ed25519, vec![0x66; 64]),
1429 )])
1430 .unwrap();
1431 let auth = AccountAuthenticator::multi_key(mk_pk.to_bytes(), mk_sig.to_bytes());
1432
1433 let serialized = aptos_bcs::to_bytes(&auth).unwrap();
1434 let result: Result<AccountAuthenticator, _> = aptos_bcs::from_bytes(&serialized);
1435 assert!(result.is_err());
1436 }
1437
1438 #[test]
1439 fn test_multi_ed25519_authenticator_bcs_roundtrip() {
1440 let auth = AccountAuthenticator::MultiEd25519 {
1441 public_key: vec![0xcc; 64],
1442 signature: vec![0xdd; 128],
1443 };
1444
1445 let serialized = aptos_bcs::to_bytes(&auth).unwrap();
1446 assert_eq!(serialized[0], 1, "MultiEd25519 variant index should be 1");
1448 let deserialized: AccountAuthenticator = aptos_bcs::from_bytes(&serialized).unwrap();
1449 assert_eq!(auth, deserialized);
1450 }
1451
1452 #[test]
1453 fn test_ed25519_public_key_deserialize_invalid_length() {
1454 let mut bytes = vec![16u8]; bytes.extend_from_slice(&[0xab; 16]); let result: Result<Ed25519PublicKey, _> = aptos_bcs::from_bytes(&bytes);
1458 assert!(result.is_err());
1459 }
1460
1461 #[test]
1462 fn test_ed25519_signature_deserialize_invalid_length() {
1463 let mut bytes = vec![32u8]; bytes.extend_from_slice(&[0xab; 32]); let result: Result<Ed25519Signature, _> = aptos_bcs::from_bytes(&bytes);
1467 assert!(result.is_err());
1468 }
1469}