1use crate::error::{LighterError, Result};
2use std::sync::atomic::{AtomicU64, Ordering};
3use std::time::{SystemTime, UNIX_EPOCH};
4
5#[derive(Debug)]
6pub struct NonceManager {
7 counter: AtomicU64,
8 last_timestamp: AtomicU64,
9}
10
11impl NonceManager {
12 pub fn new() -> Self {
13 Self {
14 counter: AtomicU64::new(0),
15 last_timestamp: AtomicU64::new(0),
16 }
17 }
18
19 pub fn generate(&self) -> Result<u64> {
20 let current_timestamp = SystemTime::now()
21 .duration_since(UNIX_EPOCH)
22 .map_err(|e| LighterError::Nonce(format!("Time error: {}", e)))?
23 .as_millis() as u64;
24
25 let last_timestamp = self.last_timestamp.load(Ordering::Acquire);
26
27 if current_timestamp > last_timestamp {
28 self.last_timestamp
29 .store(current_timestamp, Ordering::Release);
30 self.counter.store(0, Ordering::Release);
31 Ok(current_timestamp * 1000)
32 } else {
33 let counter = self.counter.fetch_add(1, Ordering::AcqRel);
34 if counter >= 999 {
35 return Err(LighterError::Nonce(
36 "Too many nonces generated in the same millisecond".to_string(),
37 ));
38 }
39 Ok(last_timestamp * 1000 + counter + 1)
40 }
41 }
42}
43
44impl Default for NonceManager {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use std::collections::HashSet;
54 use std::sync::Arc;
55 use std::thread;
56
57 #[test]
58 fn test_nonce_uniqueness() {
59 let manager = NonceManager::new();
60 let mut nonces = HashSet::new();
61
62 for _ in 0..100 {
64 let nonce = manager.generate().unwrap();
65 assert!(nonces.insert(nonce), "Duplicate nonce generated: {}", nonce);
66 }
67 }
68
69 #[test]
70 fn test_nonce_increasing() {
71 let manager = NonceManager::new();
72 let mut previous = 0;
73
74 for _ in 0..50 {
76 let nonce = manager.generate().unwrap();
77 assert!(
78 nonce > previous,
79 "Nonce {} is not greater than previous {}",
80 nonce,
81 previous
82 );
83 previous = nonce;
84 }
85 }
86
87 #[test]
88 fn test_nonce_concurrent_generation() {
89 let manager = Arc::new(NonceManager::new());
90 let mut handles = vec![];
91 let nonces = Arc::new(std::sync::Mutex::new(HashSet::new()));
92
93 for _ in 0..10 {
95 let manager_clone = Arc::clone(&manager);
96 let nonces_clone = Arc::clone(&nonces);
97
98 let handle = thread::spawn(move || {
99 for _ in 0..10 {
100 let nonce = manager_clone.generate().unwrap();
101 let mut nonces_guard = nonces_clone.lock().unwrap();
102 assert!(
103 nonces_guard.insert(nonce),
104 "Duplicate nonce in concurrent generation: {}",
105 nonce
106 );
107 }
108 });
109
110 handles.push(handle);
111 }
112
113 for handle in handles {
115 handle.join().unwrap();
116 }
117
118 let final_nonces = nonces.lock().unwrap();
120 assert_eq!(final_nonces.len(), 100);
121 }
122
123 #[test]
124 fn test_nonce_timestamp_format() {
125 let manager = NonceManager::new();
126 let nonce = manager.generate().unwrap();
127
128 assert!(
130 nonce > 1_000_000_000_000,
131 "Nonce should be at least 13 digits"
132 );
133
134 let current_time_micros = SystemTime::now()
136 .duration_since(UNIX_EPOCH)
137 .unwrap()
138 .as_millis() as u64
139 * 1000;
140
141 assert!(nonce <= current_time_micros + 1_000_000);
143 assert!(nonce >= current_time_micros - 1_000_000);
144 }
145
146 #[test]
147 fn test_nonce_counter_reset() {
148 let manager = NonceManager::new();
149
150 let first_nonce = manager.generate().unwrap();
152
153 std::thread::sleep(std::time::Duration::from_millis(2));
155
156 let second_nonce = manager.generate().unwrap();
158
159 assert!(second_nonce > first_nonce);
161
162 assert!(second_nonce - first_nonce >= 1000);
164 }
165
166 #[test]
167 fn test_nonce_rapid_generation() {
168 let manager = NonceManager::new();
169 let mut nonces = Vec::new();
170
171 for _ in 0..100 {
173 match manager.generate() {
174 Ok(nonce) => nonces.push(nonce),
175 Err(e) => {
176 if let LighterError::Nonce(msg) = e {
178 assert!(msg.contains("Too many nonces"));
179 break;
180 } else {
181 panic!("Unexpected error: {}", e);
182 }
183 }
184 }
185 }
186
187 let unique_nonces: HashSet<_> = nonces.iter().collect();
189 assert_eq!(unique_nonces.len(), nonces.len());
190 }
191
192 #[test]
193 fn test_nonce_default_impl() {
194 let manager1 = NonceManager::new();
195 let manager2 = NonceManager::default();
196
197 assert!(manager1.generate().is_ok());
199 assert!(manager2.generate().is_ok());
200 }
201}