identity.rs
1 /// Multi-chain identity generation for Alpha and Delta chains 2 /// 3 /// Generates cryptographic identities (keypairs and addresses) for both 4 /// Alpha (ax1 bech32 addresses) and Delta (dx1 bech32 addresses) chains. 5 6 use crate::{BotError, Result}; 7 use ed25519_dalek::{SigningKey, VerifyingKey, Signature, Signer}; 8 use blake2::{Blake2s256, Digest}; 9 use rand::rngs::OsRng; 10 use serde::{Deserialize, Serialize}; 11 12 /// A multi-chain identity for Alpha and Delta protocols 13 #[derive(Debug, Clone, Serialize, Deserialize)] 14 pub struct Identity { 15 /// Unique identifier 16 pub id: String, 17 18 /// Alpha chain address (ax1...) 19 pub alpha_address: String, 20 21 /// Delta chain address (dx1...) 22 pub delta_address: String, 23 24 /// Private key (stored as bytes, careful with serialization) 25 #[serde(skip)] 26 signing_key: Option<SigningKey>, 27 } 28 29 impl Identity { 30 /// Create a new identity from a signing key 31 pub fn from_signing_key(id: String, signing_key: SigningKey) -> Result<Self> { 32 let verifying_key = signing_key.verifying_key(); 33 34 // Generate addresses for both chains 35 let alpha_address = Self::generate_address(&verifying_key, "ax")?; 36 let delta_address = Self::generate_address(&verifying_key, "dx")?; 37 38 Ok(Self { 39 id, 40 alpha_address, 41 delta_address, 42 signing_key: Some(signing_key), 43 }) 44 } 45 46 /// Generate a bech32 address from a verifying key 47 fn generate_address(verifying_key: &VerifyingKey, prefix: &str) -> Result<String> { 48 // Hash the public key 49 let mut hasher = Blake2s256::new(); 50 hasher.update(verifying_key.as_bytes()); 51 let hash = hasher.finalize(); 52 53 // Take first 32 bytes (full hash for Blake2s256) 54 let address_bytes = &hash[..]; 55 56 // Convert to bech32 57 // Note: For production, use proper bech32 encoding 58 // This is a simplified version for the testbot framework 59 let encoded = bech32::encode( 60 prefix, 61 address_bytes.to_vec(), 62 bech32::Variant::Bech32, 63 ).map_err(|e| BotError::IdentityError(format!("Bech32 encoding failed: {}", e)))?; 64 65 Ok(encoded) 66 } 67 68 /// Sign a message with this identity 69 pub fn sign(&self, message: &[u8]) -> Result<Signature> { 70 let signing_key = self.signing_key.as_ref() 71 .ok_or_else(|| BotError::IdentityError("No signing key available".to_string()))?; 72 73 Ok(signing_key.sign(message)) 74 } 75 76 /// Get the verifying key 77 pub fn verifying_key(&self) -> Result<VerifyingKey> { 78 let signing_key = self.signing_key.as_ref() 79 .ok_or_else(|| BotError::IdentityError("No signing key available".to_string()))?; 80 81 Ok(signing_key.verifying_key()) 82 } 83 84 /// Create a view-only identity (no signing capability) 85 pub fn view_only(id: String, alpha_address: String, delta_address: String) -> Self { 86 Self { 87 id, 88 alpha_address, 89 delta_address, 90 signing_key: None, 91 } 92 } 93 94 /// Check if this identity can sign 95 pub fn can_sign(&self) -> bool { 96 self.signing_key.is_some() 97 } 98 } 99 100 /// Generator for creating new identities 101 pub struct IdentityGenerator { 102 /// Deterministic seed for reproducible bot generation 103 seed: Option<u64>, 104 } 105 106 impl IdentityGenerator { 107 /// Create a new identity generator 108 pub fn new() -> Self { 109 Self { seed: None } 110 } 111 112 /// Create a generator with a deterministic seed 113 pub fn with_seed(seed: u64) -> Self { 114 Self { seed: Some(seed) } 115 } 116 117 /// Generate a new identity 118 pub fn generate(&self, bot_id: String) -> Result<Identity> { 119 // For now, use OS random source 120 // TODO: Add deterministic generation from seed for reproducibility 121 let signing_key = SigningKey::generate(&mut OsRng); 122 123 Identity::from_signing_key(bot_id, signing_key) 124 } 125 126 /// Generate multiple identities 127 pub fn generate_batch(&self, prefix: &str, count: usize) -> Result<Vec<Identity>> { 128 let mut identities = Vec::with_capacity(count); 129 130 for i in 0..count { 131 let bot_id = format!("{}-{}", prefix, i); 132 identities.push(self.generate(bot_id)?); 133 } 134 135 Ok(identities) 136 } 137 } 138 139 impl Default for IdentityGenerator { 140 fn default() -> Self { 141 Self::new() 142 } 143 } 144 145 #[cfg(test)] 146 mod tests { 147 use super::*; 148 149 #[test] 150 fn test_identity_generation() { 151 let generator = IdentityGenerator::new(); 152 let identity = generator.generate("test-bot-1".to_string()) 153 .expect("Failed to generate identity"); 154 155 assert!(identity.alpha_address.starts_with("ax")); 156 assert!(identity.delta_address.starts_with("dx")); 157 assert!(identity.can_sign()); 158 } 159 160 #[test] 161 fn test_batch_generation() { 162 let generator = IdentityGenerator::new(); 163 let identities = generator.generate_batch("bot", 10) 164 .expect("Failed to generate batch"); 165 166 assert_eq!(identities.len(), 10); 167 168 for (i, identity) in identities.iter().enumerate() { 169 assert_eq!(identity.id, format!("bot-{}", i)); 170 assert!(identity.can_sign()); 171 } 172 } 173 174 #[test] 175 fn test_view_only_identity() { 176 let identity = Identity::view_only( 177 "view-bot".to_string(), 178 "ax1test123".to_string(), 179 "dx1test456".to_string(), 180 ); 181 182 assert!(!identity.can_sign()); 183 assert!(identity.sign(&[1, 2, 3]).is_err()); 184 } 185 186 #[test] 187 fn test_signing() { 188 let generator = IdentityGenerator::new(); 189 let identity = generator.generate("signer-bot".to_string()) 190 .expect("Failed to generate identity"); 191 192 let message = b"test message"; 193 let signature = identity.sign(message) 194 .expect("Failed to sign message"); 195 196 // Verify the signature 197 let verifying_key = identity.verifying_key() 198 .expect("Failed to get verifying key"); 199 200 assert!(verifying_key.verify(message, &signature).is_ok()); 201 } 202 }