1use rand::{thread_rng, Rng, RngCore};
7use serde::{Deserialize, Serialize};
8use sha2::{Digest, Sha256};
9use std::collections::HashMap;
10use std::fmt;
11use std::sync::Arc;
12use std::time::{Duration, SystemTime, UNIX_EPOCH};
13use thiserror::Error;
14use tokio::sync::{Mutex, RwLock};
15use tokio::time::interval;
16use x25519_dalek::{EphemeralSecret, PublicKey};
17
18#[derive(Debug, Error)]
20pub enum ShadowAddressError {
21 #[error("Key generation failed")]
23 KeyGenerationFailed,
24
25 #[error("Invalid key format: {0}")]
27 InvalidKeyFormat(String),
28
29 #[error("Address resolution failed: {0}")]
31 ResolutionFailed(String),
32
33 #[error("Cryptographic error: {0}")]
35 CryptoError(String),
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
40pub struct ShadowAddress {
41 pub view_key: Vec<u8>,
43
44 pub spend_key: Vec<u8>,
46
47 pub payment_id: Option<[u8; 32]>,
49
50 pub metadata: ShadowMetadata,
52
53 pub shadow_features: ShadowFeatures,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
59pub struct ShadowFeatures {
60 pub is_temporary: bool,
62
63 pub derivation_index: Option<u32>,
65
66 pub stealth_prefix: Option<[u8; 4]>,
68
69 pub mixing_enabled: bool,
71
72 pub pool_id: Option<String>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
78pub struct ShadowMetadata {
79 pub version: u8,
81
82 pub network: NetworkType,
84
85 pub expires_at: Option<u64>,
87
88 pub created_at: u64,
90
91 pub last_used: Option<u64>,
93
94 pub flags: u32,
96
97 pub ttl: Option<u64>,
99
100 pub usage_count: u32,
102
103 pub max_uses: Option<u32>,
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
109pub enum NetworkType {
110 Mainnet,
112 Testnet,
114 Devnet,
116}
117
118impl fmt::Display for ShadowAddress {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 write!(f, "ShadowAddress({:?})", self.metadata)
121 }
122}
123
124pub trait ShadowAddressGenerator {
126 fn generate_address(&self, network: NetworkType) -> Result<ShadowAddress, ShadowAddressError>;
128
129 fn generate_temporary_address(
131 &self,
132 network: NetworkType,
133 ttl: Duration,
134 ) -> Result<ShadowAddress, ShadowAddressError>;
135
136 fn generate_stealth_address(
138 &self,
139 network: NetworkType,
140 recipient_view_key: &[u8],
141 recipient_spend_key: &[u8],
142 ) -> Result<ShadowAddress, ShadowAddressError>;
143
144 fn derive_address(&self, base: &ShadowAddress) -> Result<ShadowAddress, ShadowAddressError>;
146
147 fn derive_from_master(
149 &self,
150 master_key: &[u8],
151 index: u32,
152 ) -> Result<ShadowAddress, ShadowAddressError>;
153
154 fn validate_address(&self, address: &ShadowAddress) -> Result<bool, ShadowAddressError>;
156}
157
158pub trait ShadowAddressResolver {
160 fn resolve_address(&self, address: &ShadowAddress) -> Result<Vec<u8>, ShadowAddressError>;
162
163 fn check_address(
165 &self,
166 shadow: &ShadowAddress,
167 onetime: &[u8],
168 ) -> Result<bool, ShadowAddressError>;
169}
170
171#[derive(Debug, Clone)]
173pub struct ShadowAddressPool {
174 pub id: String,
176
177 pub max_size: usize,
179
180 pub addresses: Vec<ShadowAddress>,
182
183 pub created_at: u64,
185
186 pub expires_at: Option<u64>,
188}
189
190pub struct ShadowAddressManager {
192 generator: Arc<RwLock<DefaultShadowAddressHandler>>,
194
195 active_addresses: Arc<RwLock<HashMap<String, ShadowAddress>>>,
197
198 address_pools: Arc<RwLock<HashMap<String, ShadowAddressPool>>>,
200
201 expired_addresses: Arc<RwLock<Vec<ShadowAddress>>>,
203
204 rotation_policies: Arc<RwLock<RotationPolicies>>,
206
207 #[allow(dead_code)]
209 cleanup_handle: Option<tokio::task::JoinHandle<()>>,
210}
211
212#[derive(Debug, Clone)]
214pub struct RotationPolicies {
215 pub rotate_after_uses: Option<u32>,
217
218 pub rotate_after_duration: Option<Duration>,
220
221 pub min_pool_size: usize,
223
224 pub max_pool_size: usize,
226}
227
228pub struct DefaultShadowAddressHandler {
230 network: NetworkType,
232
233 #[allow(dead_code)]
235 master_seed: [u8; 32],
236
237 #[allow(dead_code)]
239 derivation_counter: Mutex<u32>,
240}
241
242impl DefaultShadowAddressHandler {
243 pub fn new(network: NetworkType, master_seed: [u8; 32]) -> Self {
245 Self {
246 network,
247 master_seed,
248 derivation_counter: Mutex::new(0),
249 }
250 }
251
252 fn generate_seed(&self) -> [u8; 32] {
254 let mut seed = [0u8; 32];
255 thread_rng().fill_bytes(&mut seed);
256 seed
257 }
258
259 fn derive_keys(&self, seed: &[u8; 32]) -> Result<(Vec<u8>, Vec<u8>), ShadowAddressError> {
261 let mut hasher = Sha256::new();
263 hasher.update(b"SHADOW_VIEW_KEY");
264 hasher.update(seed);
265 let view_key = hasher.finalize().to_vec();
266
267 let mut hasher = Sha256::new();
268 hasher.update(b"SHADOW_SPEND_KEY");
269 hasher.update(seed);
270 let spend_key = hasher.finalize().to_vec();
271
272 Ok((view_key, spend_key))
273 }
274
275 fn generate_stealth_keys(
277 &self,
278 recipient_view_key: &[u8],
279 _recipient_spend_key: &[u8],
280 ) -> Result<(Vec<u8>, Vec<u8>, [u8; 32]), ShadowAddressError> {
281 let ephemeral_secret = EphemeralSecret::random_from_rng(thread_rng());
283 let ephemeral_public = PublicKey::from(&ephemeral_secret);
284
285 let recipient_view_pubkey =
287 PublicKey::from(<[u8; 32]>::try_from(recipient_view_key).map_err(|_| {
288 ShadowAddressError::InvalidKeyFormat("Invalid view key length".into())
289 })?);
290
291 let shared_secret = ephemeral_secret.diffie_hellman(&recipient_view_pubkey);
292
293 let mut hasher = Sha256::new();
295 hasher.update(shared_secret.as_bytes());
296 hasher.update(b"STEALTH_VIEW");
297 let stealth_view_key = hasher.finalize().to_vec();
298
299 let mut hasher = Sha256::new();
300 hasher.update(shared_secret.as_bytes());
301 hasher.update(b"STEALTH_SPEND");
302 let stealth_spend_key = hasher.finalize().to_vec();
303
304 Ok((
305 stealth_view_key,
306 stealth_spend_key,
307 ephemeral_public.to_bytes(),
308 ))
309 }
310
311 fn current_timestamp() -> u64 {
313 SystemTime::now()
314 .duration_since(UNIX_EPOCH)
315 .unwrap()
316 .as_secs()
317 }
318
319 fn generate_address_id() -> String {
321 let mut rng = thread_rng();
322 let id: u64 = rng.gen();
323 format!("shadow_{:016x}", id)
324 }
325}
326
327impl ShadowAddressGenerator for DefaultShadowAddressHandler {
328 fn generate_address(&self, network: NetworkType) -> Result<ShadowAddress, ShadowAddressError> {
329 let seed = self.generate_seed();
330 let (view_key, spend_key) = self.derive_keys(&seed)?;
331 let current_time = Self::current_timestamp();
332
333 Ok(ShadowAddress {
334 view_key,
335 spend_key,
336 payment_id: None,
337 metadata: ShadowMetadata {
338 version: 1,
339 network,
340 expires_at: None,
341 created_at: current_time,
342 last_used: None,
343 flags: 0,
344 ttl: None,
345 usage_count: 0,
346 max_uses: None,
347 },
348 shadow_features: ShadowFeatures {
349 is_temporary: false,
350 derivation_index: None,
351 stealth_prefix: None,
352 mixing_enabled: false,
353 pool_id: None,
354 },
355 })
356 }
357
358 fn generate_temporary_address(
359 &self,
360 network: NetworkType,
361 ttl: Duration,
362 ) -> Result<ShadowAddress, ShadowAddressError> {
363 let seed = self.generate_seed();
364 let (view_key, spend_key) = self.derive_keys(&seed)?;
365 let current_time = Self::current_timestamp();
366 let expires_at = current_time + ttl.as_secs();
367
368 Ok(ShadowAddress {
369 view_key,
370 spend_key,
371 payment_id: None,
372 metadata: ShadowMetadata {
373 version: 1,
374 network,
375 expires_at: Some(expires_at),
376 created_at: current_time,
377 last_used: None,
378 flags: 0x01, ttl: Some(ttl.as_secs()),
380 usage_count: 0,
381 max_uses: None,
382 },
383 shadow_features: ShadowFeatures {
384 is_temporary: true,
385 derivation_index: None,
386 stealth_prefix: None,
387 mixing_enabled: false,
388 pool_id: None,
389 },
390 })
391 }
392
393 fn generate_stealth_address(
394 &self,
395 network: NetworkType,
396 recipient_view_key: &[u8],
397 recipient_spend_key: &[u8],
398 ) -> Result<ShadowAddress, ShadowAddressError> {
399 let (stealth_view_key, stealth_spend_key, ephemeral_pubkey) =
400 self.generate_stealth_keys(recipient_view_key, recipient_spend_key)?;
401
402 let current_time = Self::current_timestamp();
403
404 let mut hasher = Sha256::new();
406 hasher.update(&ephemeral_pubkey);
407 let hash = hasher.finalize();
408 let stealth_prefix = [hash[0], hash[1], hash[2], hash[3]];
409
410 Ok(ShadowAddress {
411 view_key: stealth_view_key,
412 spend_key: stealth_spend_key,
413 payment_id: Some(ephemeral_pubkey),
414 metadata: ShadowMetadata {
415 version: 2, network,
417 expires_at: None,
418 created_at: current_time,
419 last_used: None,
420 flags: 0x02, ttl: None,
422 usage_count: 0,
423 max_uses: Some(1), },
425 shadow_features: ShadowFeatures {
426 is_temporary: false,
427 derivation_index: None,
428 stealth_prefix: Some(stealth_prefix),
429 mixing_enabled: true,
430 pool_id: None,
431 },
432 })
433 }
434
435 fn derive_address(&self, base: &ShadowAddress) -> Result<ShadowAddress, ShadowAddressError> {
436 let seed = self.generate_seed();
437 let (view_key, spend_key) = self.derive_keys(&seed)?;
438 let current_time = Self::current_timestamp();
439
440 Ok(ShadowAddress {
441 view_key,
442 spend_key,
443 payment_id: base.payment_id,
444 metadata: ShadowMetadata {
445 version: base.metadata.version,
446 network: base.metadata.network,
447 expires_at: base.metadata.expires_at,
448 created_at: current_time,
449 last_used: None,
450 flags: base.metadata.flags,
451 ttl: base.metadata.ttl,
452 usage_count: 0,
453 max_uses: base.metadata.max_uses,
454 },
455 shadow_features: base.shadow_features.clone(),
456 })
457 }
458
459 fn derive_from_master(
460 &self,
461 master_key: &[u8],
462 index: u32,
463 ) -> Result<ShadowAddress, ShadowAddressError> {
464 let mut hasher = Sha256::new();
466 hasher.update(b"SHADOW_HD_DERIVE");
467 hasher.update(master_key);
468 hasher.update(&index.to_le_bytes());
469 let derived_seed = hasher.finalize();
470
471 let seed_array: [u8; 32] = derived_seed.into();
472 let (view_key, spend_key) = self.derive_keys(&seed_array)?;
473 let current_time = Self::current_timestamp();
474
475 Ok(ShadowAddress {
476 view_key,
477 spend_key,
478 payment_id: None,
479 metadata: ShadowMetadata {
480 version: 1,
481 network: self.network,
482 expires_at: None,
483 created_at: current_time,
484 last_used: None,
485 flags: 0x04, ttl: None,
487 usage_count: 0,
488 max_uses: None,
489 },
490 shadow_features: ShadowFeatures {
491 is_temporary: false,
492 derivation_index: Some(index),
493 stealth_prefix: None,
494 mixing_enabled: false,
495 pool_id: None,
496 },
497 })
498 }
499
500 fn validate_address(&self, address: &ShadowAddress) -> Result<bool, ShadowAddressError> {
501 if address.view_key.len() != 32 || address.spend_key.len() != 32 {
503 return Ok(false);
504 }
505
506 if let Some(expires_at) = address.metadata.expires_at {
508 if Self::current_timestamp() > expires_at {
509 return Ok(false);
510 }
511 }
512
513 if let Some(max_uses) = address.metadata.max_uses {
515 if address.metadata.usage_count >= max_uses {
516 return Ok(false);
517 }
518 }
519
520 if address.metadata.network != self.network {
522 return Ok(false);
523 }
524
525 Ok(true)
526 }
527}
528
529impl ShadowAddressResolver for DefaultShadowAddressHandler {
530 fn resolve_address(&self, address: &ShadowAddress) -> Result<Vec<u8>, ShadowAddressError> {
531 let mut resolved = Vec::new();
534 resolved.extend_from_slice(&address.view_key);
535 resolved.extend_from_slice(&address.spend_key);
536 if let Some(payment_id) = address.payment_id {
537 resolved.extend_from_slice(&payment_id);
538 }
539 Ok(resolved)
540 }
541
542 fn check_address(
543 &self,
544 shadow: &ShadowAddress,
545 onetime: &[u8],
546 ) -> Result<bool, ShadowAddressError> {
547 let resolved = self.resolve_address(shadow)?;
548 Ok(resolved == onetime)
549 }
550}
551
552impl ShadowAddressManager {
553 pub async fn new(network: NetworkType, master_seed: [u8; 32]) -> Self {
555 let generator = Arc::new(RwLock::new(DefaultShadowAddressHandler::new(
556 network,
557 master_seed,
558 )));
559 let manager = Self {
560 generator,
561 active_addresses: Arc::new(RwLock::new(HashMap::new())),
562 address_pools: Arc::new(RwLock::new(HashMap::new())),
563 expired_addresses: Arc::new(RwLock::new(Vec::new())),
564 rotation_policies: Arc::new(RwLock::new(RotationPolicies::default())),
565 cleanup_handle: None,
566 };
567
568 let cleanup_manager = manager.clone();
570 let cleanup_handle = tokio::spawn(async move {
571 cleanup_manager.cleanup_task().await;
572 });
573
574 Self {
575 cleanup_handle: Some(cleanup_handle),
576 ..manager
577 }
578 }
579
580 fn clone(&self) -> Self {
582 Self {
583 generator: self.generator.clone(),
584 active_addresses: self.active_addresses.clone(),
585 address_pools: self.address_pools.clone(),
586 expired_addresses: self.expired_addresses.clone(),
587 rotation_policies: self.rotation_policies.clone(),
588 cleanup_handle: None,
589 }
590 }
591
592 pub async fn create_temporary_address(
594 &self,
595 ttl: Duration,
596 ) -> Result<ShadowAddress, ShadowAddressError> {
597 let generator = self.generator.read().await;
598 let address = generator.generate_temporary_address(generator.network, ttl)?;
599
600 let address_id = DefaultShadowAddressHandler::generate_address_id();
602 self.active_addresses
603 .write()
604 .await
605 .insert(address_id, address.clone());
606
607 Ok(address)
608 }
609
610 pub async fn create_stealth_address(
612 &self,
613 recipient_view_key: &[u8],
614 recipient_spend_key: &[u8],
615 ) -> Result<ShadowAddress, ShadowAddressError> {
616 let generator = self.generator.read().await;
617 let address = generator.generate_stealth_address(
618 generator.network,
619 recipient_view_key,
620 recipient_spend_key,
621 )?;
622
623 Ok(address)
625 }
626
627 pub async fn create_address_pool(
629 &self,
630 pool_id: String,
631 size: usize,
632 ttl: Option<Duration>,
633 ) -> Result<(), ShadowAddressError> {
634 let generator = self.generator.read().await;
635 let mut addresses = Vec::new();
636
637 for _ in 0..size {
638 let mut address = if let Some(ttl) = ttl {
639 generator.generate_temporary_address(generator.network, ttl)?
640 } else {
641 generator.generate_address(generator.network)?
642 };
643
644 address.shadow_features.pool_id = Some(pool_id.clone());
645 addresses.push(address);
646 }
647
648 let current_time = DefaultShadowAddressHandler::current_timestamp();
649 let pool = ShadowAddressPool {
650 id: pool_id.clone(),
651 max_size: size,
652 addresses,
653 created_at: current_time,
654 expires_at: ttl.map(|d| current_time + d.as_secs()),
655 };
656
657 self.address_pools.write().await.insert(pool_id, pool);
658 Ok(())
659 }
660
661 pub async fn get_pool_address(&self, pool_id: &str) -> Option<ShadowAddress> {
663 let pools = self.address_pools.read().await;
664 if let Some(pool) = pools.get(pool_id) {
665 if !pool.addresses.is_empty() {
666 let mut rng = thread_rng();
667 let index = rng.gen_range(0..pool.addresses.len());
668 return Some(pool.addresses[index].clone());
669 }
670 }
671 None
672 }
673
674 pub async fn rotate_pool(&self, pool_id: &str) -> Result<(), ShadowAddressError> {
676 let mut pools = self.address_pools.write().await;
677 if let Some(pool) = pools.get_mut(pool_id) {
678 let generator = self.generator.read().await;
679 let size = pool.max_size;
680 let ttl = pool.expires_at.map(|exp| {
681 let current = DefaultShadowAddressHandler::current_timestamp();
682 Duration::from_secs(exp.saturating_sub(current))
683 });
684
685 let old_addresses = std::mem::take(&mut pool.addresses);
687 self.expired_addresses.write().await.extend(old_addresses);
688
689 for _ in 0..size {
691 let mut address = if let Some(ttl) = ttl {
692 generator.generate_temporary_address(generator.network, ttl)?
693 } else {
694 generator.generate_address(generator.network)?
695 };
696
697 address.shadow_features.pool_id = Some(pool_id.to_string());
698 pool.addresses.push(address);
699 }
700
701 Ok(())
702 } else {
703 Err(ShadowAddressError::ResolutionFailed(
704 "Pool not found".into(),
705 ))
706 }
707 }
708
709 pub async fn mark_address_used(&self, address: &mut ShadowAddress) {
711 address.metadata.usage_count += 1;
712 address.metadata.last_used = Some(DefaultShadowAddressHandler::current_timestamp());
713
714 let policies = self.rotation_policies.read().await;
716 if let Some(max_uses) = policies.rotate_after_uses {
717 if address.metadata.usage_count >= max_uses {
718 if let Some(pool_id) = &address.shadow_features.pool_id {
719 let _ = self.rotate_pool(pool_id).await;
720 }
721 }
722 }
723 }
724
725 async fn cleanup_task(&self) {
727 let mut cleanup_interval = interval(Duration::from_secs(60)); loop {
730 cleanup_interval.tick().await;
731
732 let current_time = DefaultShadowAddressHandler::current_timestamp();
734
735 let mut active = self.active_addresses.write().await;
737 let expired: Vec<_> = active
738 .iter()
739 .filter(|(_, addr)| {
740 if let Some(expires_at) = addr.metadata.expires_at {
741 current_time > expires_at
742 } else {
743 false
744 }
745 })
746 .map(|(id, _)| id.clone())
747 .collect();
748
749 for id in expired {
750 if let Some(addr) = active.remove(&id) {
751 self.expired_addresses.write().await.push(addr);
752 }
753 }
754
755 let mut pools = self.address_pools.write().await;
757 let expired_pools: Vec<_> = pools
758 .iter()
759 .filter(|(_, pool)| {
760 if let Some(expires_at) = pool.expires_at {
761 current_time > expires_at
762 } else {
763 false
764 }
765 })
766 .map(|(id, _)| id.clone())
767 .collect();
768
769 for id in expired_pools {
770 pools.remove(&id);
771 }
772
773 let mut expired = self.expired_addresses.write().await;
775 if expired.len() > 1000 {
776 expired.drain(0..500); }
778 }
779 }
780}
781
782impl Default for RotationPolicies {
783 fn default() -> Self {
784 Self {
785 rotate_after_uses: Some(100),
786 rotate_after_duration: Some(Duration::from_secs(3600)), min_pool_size: 10,
788 max_pool_size: 100,
789 }
790 }
791}
792
793pub struct ShadowAddressMixer {
795 rounds: usize,
797
798 delay: Duration,
800}
801
802impl ShadowAddressMixer {
803 pub fn new(rounds: usize, delay: Duration) -> Self {
805 Self { rounds, delay }
806 }
807
808 pub async fn mix_addresses(
810 &self,
811 addresses: Vec<ShadowAddress>,
812 ) -> Result<Vec<ShadowAddress>, ShadowAddressError> {
813 let mut mixed = addresses;
814
815 for _round in 0..self.rounds {
816 let mut rng = thread_rng();
818 use rand::seq::SliceRandom;
819 mixed.shuffle(&mut rng);
820
821 tokio::time::sleep(self.delay).await;
823
824 mixed = mixed
826 .into_iter()
827 .map(|mut addr| {
828 addr.shadow_features.mixing_enabled = true;
830 addr.metadata.flags |= 0x08; addr
832 })
833 .collect();
834 }
835
836 Ok(mixed)
837 }
838}
839
840#[cfg(test)]
841mod tests {
842 use super::*;
843 use proptest::prelude::*;
844 use std::convert::TryInto;
845
846 fn arb_network_type() -> impl Strategy<Value = NetworkType> {
848 prop_oneof![
849 Just(NetworkType::Mainnet),
850 Just(NetworkType::Testnet),
851 Just(NetworkType::Devnet)
852 ]
853 }
854
855 fn arb_shadow_metadata() -> impl Strategy<Value = ShadowMetadata> {
857 (
858 arb_network_type(),
859 any::<u8>(),
860 any::<Option<u64>>(),
861 any::<u32>(),
862 )
863 .prop_map(|(network, version, expires_at, flags)| ShadowMetadata {
864 version,
865 network,
866 expires_at,
867 flags,
868 })
869 }
870
871 fn arb_shadow_address() -> impl Strategy<Value = ShadowAddress> {
873 (
874 proptest::collection::vec(any::<u8>(), 32..64),
875 proptest::collection::vec(any::<u8>(), 32..64),
876 any::<Option<[u8; 32]>>(),
877 arb_shadow_metadata(),
878 )
879 .prop_map(
880 |(view_key, spend_key, payment_id, metadata)| ShadowAddress {
881 view_key,
882 spend_key,
883 payment_id,
884 metadata,
885 },
886 )
887 }
888
889 fn create_test_address() -> ShadowAddress {
891 ShadowAddress {
892 view_key: vec![1, 2, 3, 4],
893 spend_key: vec![5, 6, 7, 8],
894 payment_id: None,
895 metadata: ShadowMetadata {
896 version: 1,
897 network: NetworkType::Testnet,
898 expires_at: None,
899 flags: 0,
900 },
901 }
902 }
903
904 #[test]
905 fn test_shadow_address_display() {
906 let addr = create_test_address();
907 let display = format!("{}", addr);
908 assert!(display.contains("ShadowAddress"));
909 }
910
911 #[test]
912 fn test_shadow_address_serialize() {
913 let addr = create_test_address();
914 let serialized = serde_json::to_string(&addr).unwrap();
915 let deserialized: ShadowAddress = serde_json::from_str(&serialized).unwrap();
916 assert_eq!(deserialized.view_key, addr.view_key);
917 assert_eq!(deserialized.metadata.network, NetworkType::Testnet);
918 }
919
920 proptest! {
921 #[test]
922 fn test_address_generation(network in arb_network_type()) {
923 let seed = [0u8; 32];
924 let handler = DefaultShadowAddressHandler::new(network, seed);
925 let addr = handler.generate_address(network).unwrap();
926
927 prop_assert_eq!(addr.metadata.network, network);
928 prop_assert!(!addr.view_key.is_empty());
929 prop_assert!(!addr.spend_key.is_empty());
930 }
931
932 #[test]
933 fn test_address_resolution(addr in arb_shadow_address()) {
934 let seed = [0u8; 32];
935 let handler = DefaultShadowAddressHandler::new(addr.metadata.network, seed);
936 let resolved = handler.resolve_address(&addr).unwrap();
937
938 prop_assert!(!resolved.is_empty());
940 prop_assert!(resolved.len() >= addr.view_key.len() + addr.spend_key.len());
941 }
942
943 #[test]
944 fn test_address_derivation(base in arb_shadow_address()) {
945 let seed = [0u8; 32];
946 let handler = DefaultShadowAddressHandler::new(base.metadata.network, seed);
947 let derived = handler.derive_address(&base).unwrap();
948
949 prop_assert_eq!(derived.metadata.network, base.metadata.network);
951 prop_assert_eq!(derived.metadata.version, base.metadata.version);
952 prop_assert_eq!(derived.payment_id, base.payment_id);
953
954 prop_assert_ne!(derived.view_key, base.view_key);
956 prop_assert_ne!(derived.spend_key, base.spend_key);
957 }
958
959 #[test]
960 fn test_address_validation(addr in arb_shadow_address()) {
961 let seed = [0u8; 32];
962 let handler = DefaultShadowAddressHandler::new(addr.metadata.network, seed);
963 let valid = handler.validate_address(&addr).unwrap();
964
965 prop_assert_eq!(valid, !addr.view_key.is_empty() && !addr.spend_key.is_empty());
967 }
968
969 #[test]
970 fn test_address_check(addr in arb_shadow_address()) {
971 let seed = [0u8; 32];
972 let handler = DefaultShadowAddressHandler::new(addr.metadata.network, seed);
973 let resolved = handler.resolve_address(&addr).unwrap();
974 let matches = handler.check_address(&addr, &resolved).unwrap();
975
976 prop_assert!(matches);
978 }
979 }
980
981 #[test]
982 fn test_temporary_address_generation() {
983 let seed = [0u8; 32];
984 let handler = DefaultShadowAddressHandler::new(NetworkType::Testnet, seed);
985 let ttl = Duration::from_secs(300);
986 let addr = handler
987 .generate_temporary_address(NetworkType::Testnet, ttl)
988 .unwrap();
989
990 assert!(addr.shadow_features.is_temporary);
991 assert_eq!(addr.metadata.ttl, Some(300));
992 assert!(addr.metadata.expires_at.is_some());
993 assert_eq!(addr.metadata.flags & 0x01, 0x01); }
995
996 #[test]
997 fn test_stealth_address_generation() {
998 let seed = [0u8; 32];
999 let handler = DefaultShadowAddressHandler::new(NetworkType::Testnet, seed);
1000 let view_key = [1u8; 32];
1001 let spend_key = [2u8; 32];
1002
1003 let addr = handler
1004 .generate_stealth_address(NetworkType::Testnet, &view_key, &spend_key)
1005 .unwrap();
1006
1007 assert_eq!(addr.metadata.version, 2); assert_eq!(addr.metadata.flags & 0x02, 0x02); assert!(addr.shadow_features.stealth_prefix.is_some());
1010 assert!(addr.shadow_features.mixing_enabled);
1011 assert_eq!(addr.metadata.max_uses, Some(1)); }
1013
1014 #[test]
1015 fn test_hierarchical_derivation() {
1016 let master_key = [42u8; 32];
1017 let handler = DefaultShadowAddressHandler::new(NetworkType::Testnet, master_key);
1018
1019 let addr1 = handler.derive_from_master(&master_key, 0).unwrap();
1021 let addr2 = handler.derive_from_master(&master_key, 1).unwrap();
1022 let addr3 = handler.derive_from_master(&master_key, 0).unwrap();
1023
1024 assert_eq!(addr1.view_key, addr3.view_key);
1026 assert_eq!(addr1.spend_key, addr3.spend_key);
1027
1028 assert_ne!(addr1.view_key, addr2.view_key);
1030 assert_ne!(addr1.spend_key, addr2.spend_key);
1031
1032 assert_eq!(addr1.shadow_features.derivation_index, Some(0));
1034 assert_eq!(addr2.shadow_features.derivation_index, Some(1));
1035 assert_eq!(addr1.metadata.flags & 0x04, 0x04); }
1037
1038 #[test]
1039 fn test_address_expiration_validation() {
1040 let seed = [0u8; 32];
1041 let handler = DefaultShadowAddressHandler::new(NetworkType::Testnet, seed);
1042
1043 let mut addr = create_test_address();
1045 addr.metadata.expires_at = Some(1); let is_valid = handler.validate_address(&addr).unwrap();
1048 assert!(!is_valid);
1049
1050 addr.metadata.expires_at = Some(u64::MAX);
1052 let is_valid = handler.validate_address(&addr).unwrap();
1053 assert!(is_valid);
1054 }
1055
1056 #[test]
1057 fn test_usage_limit_validation() {
1058 let seed = [0u8; 32];
1059 let handler = DefaultShadowAddressHandler::new(NetworkType::Testnet, seed);
1060
1061 let mut addr = create_test_address();
1063 addr.metadata.max_uses = Some(5);
1064 addr.metadata.usage_count = 5;
1065
1066 let is_valid = handler.validate_address(&addr).unwrap();
1067 assert!(!is_valid); addr.metadata.usage_count = 4;
1070 let is_valid = handler.validate_address(&addr).unwrap();
1071 assert!(is_valid); }
1073
1074 #[tokio::test]
1075 async fn test_shadow_address_manager() {
1076 let seed = [0u8; 32];
1077 let manager = ShadowAddressManager::new(NetworkType::Testnet, seed).await;
1078
1079 let temp_addr = manager
1081 .create_temporary_address(Duration::from_secs(60))
1082 .await
1083 .unwrap();
1084 assert!(temp_addr.shadow_features.is_temporary);
1085 assert!(temp_addr.metadata.expires_at.is_some());
1086
1087 manager
1089 .create_address_pool("test_pool".to_string(), 3, Some(Duration::from_secs(120)))
1090 .await
1091 .unwrap();
1092
1093 let pool_addr = manager.get_pool_address("test_pool").await;
1095 assert!(pool_addr.is_some());
1096
1097 manager.rotate_pool("test_pool").await.unwrap();
1099 }
1100
1101 #[tokio::test]
1102 async fn test_address_mixing() {
1103 let mixer = ShadowAddressMixer::new(2, Duration::from_millis(10));
1104
1105 let addresses = vec![
1106 create_test_address(),
1107 create_test_address(),
1108 create_test_address(),
1109 ];
1110
1111 let mixed = mixer.mix_addresses(addresses.clone()).await.unwrap();
1112
1113 assert_eq!(mixed.len(), addresses.len());
1114 for addr in &mixed {
1115 assert!(addr.shadow_features.mixing_enabled);
1116 assert_eq!(addr.metadata.flags & 0x08, 0x08); }
1118 }
1119
1120 #[tokio::test]
1121 async fn test_address_usage_tracking() {
1122 let seed = [0u8; 32];
1123 let manager = ShadowAddressManager::new(NetworkType::Testnet, seed).await;
1124
1125 let mut addr = create_test_address();
1126 let initial_count = addr.metadata.usage_count;
1127
1128 manager.mark_address_used(&mut addr).await;
1129
1130 assert_eq!(addr.metadata.usage_count, initial_count + 1);
1131 assert!(addr.metadata.last_used.is_some());
1132 }
1133}