1pub mod dotns;
6pub mod extrinsic;
7pub mod identity;
8pub mod statement_store;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum CryptoScheme {
17 Ed25519,
19 Sr25519,
21 Ecdsa,
23}
24
25pub fn encode_multi_signature(sig_bytes: &[u8], scheme: CryptoScheme) -> Result<Vec<u8>, String> {
34 let (variant_byte, expected_len) = match scheme {
35 CryptoScheme::Ed25519 => (0x00u8, 64usize),
36 CryptoScheme::Sr25519 => (0x01u8, 64usize),
37 CryptoScheme::Ecdsa => (0x02u8, 65usize),
38 };
39
40 if sig_bytes.len() != expected_len {
41 return Err(format!(
42 "expected {} bytes for {:?} signature, got {}",
43 expected_len,
44 scheme,
45 sig_bytes.len(),
46 ));
47 }
48
49 let mut out = Vec::with_capacity(1 + expected_len);
50 out.push(variant_byte);
51 out.extend_from_slice(sig_bytes);
52 Ok(out)
53}
54
55pub fn hex_encode(bytes: &[u8]) -> String {
57 let mut s = String::with_capacity(2 + bytes.len() * 2);
58 s.push_str("0x");
59 for b in bytes {
60 s.push_str(&format!("{b:02x}"));
61 }
62 s
63}
64
65pub fn hex_decode(s: &str) -> Option<Vec<u8>> {
69 let s = s.strip_prefix("0x").unwrap_or(s);
70 if !s.len().is_multiple_of(2) {
71 return None;
72 }
73 let mut out = Vec::with_capacity(s.len() / 2);
74 for i in (0..s.len()).step_by(2) {
75 out.push(u8::from_str_radix(&s[i..i + 2], 16).ok()?);
76 }
77 Some(out)
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_sr25519_multi_signature_prefix_and_length() {
86 let sig = [0xabu8; 64];
87 let out = encode_multi_signature(&sig, CryptoScheme::Sr25519).unwrap();
88 assert_eq!(out.len(), 65);
89 assert_eq!(out[0], 0x01);
90 assert_eq!(&out[1..], sig.as_ref());
91 }
92
93 #[test]
94 fn test_ed25519_multi_signature_prefix_and_length() {
95 let sig = [0xabu8; 64];
96 let out = encode_multi_signature(&sig, CryptoScheme::Ed25519).unwrap();
97 assert_eq!(out.len(), 65);
98 assert_eq!(out[0], 0x00);
99 assert_eq!(&out[1..], sig.as_ref());
100 }
101
102 #[test]
103 fn test_ecdsa_multi_signature_prefix_and_length() {
104 let sig = [0xabu8; 65];
105 let out = encode_multi_signature(&sig, CryptoScheme::Ecdsa).unwrap();
106 assert_eq!(out.len(), 66);
107 assert_eq!(out[0], 0x02);
108 assert_eq!(&out[1..], sig.as_ref());
109 }
110
111 #[test]
112 fn test_multi_signature_rejects_wrong_sr25519_length() {
113 let sig = [0x00u8; 63];
114 assert!(encode_multi_signature(&sig, CryptoScheme::Sr25519).is_err());
115 }
116
117 #[test]
118 fn test_multi_signature_rejects_wrong_ecdsa_length() {
119 let sig = [0x00u8; 64];
121 assert!(encode_multi_signature(&sig, CryptoScheme::Ecdsa).is_err());
122 }
123
124 #[test]
125 fn test_multi_signature_pinned_zeros() {
126 let sig = [0u8; 64];
127 let out = encode_multi_signature(&sig, CryptoScheme::Sr25519).unwrap();
128 assert_eq!(out.len(), 65);
130 assert_eq!(out[0], 0x01);
131 assert!(out[1..].iter().all(|&b| b == 0x00));
132 }
133}