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