1use std::collections::HashMap;
7use std::time::{Duration, SystemTime, UNIX_EPOCH};
8use serde::{Serialize, Deserialize};
9use std::hash::{Hash, Hasher};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct BenchmarkHash {
14 pub algorithm: String,
15 pub hash: String,
16 pub salt: String,
17 pub timestamp: u64,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct IntegrityProof {
23 pub benchmark_id: String,
24 pub code_hash: BenchmarkHash,
25 pub data_hash: BenchmarkHash,
26 pub results_hash: BenchmarkHash,
27 pub environment_hash: BenchmarkHash,
28 pub chain_of_custody: Vec<CustodyEntry>,
29 pub verification_passed: bool,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct CustodyEntry {
34 pub timestamp: u64,
35 pub operation: String,
36 pub actor: String,
37 pub hash_before: String,
38 pub hash_after: String,
39}
40
41pub struct CryptographicValidator {
43 salt: String,
44 benchmark_id: String,
45}
46
47impl CryptographicValidator {
48 pub fn new(benchmark_id: String) -> Self {
49 let salt = Self::generate_salt();
50 Self {
51 salt,
52 benchmark_id,
53 }
54 }
55
56 fn generate_salt() -> String {
58 use std::collections::hash_map::DefaultHasher;
59 let mut hasher = DefaultHasher::new();
60
61 let now = SystemTime::now()
63 .duration_since(UNIX_EPOCH)
64 .unwrap()
65 .as_nanos();
66
67 now.hash(&mut hasher);
68 std::process::id().hash(&mut hasher);
69
70 format!("{:x}", hasher.finish())
71 }
72
73 pub fn hash_source_code(&self, source_files: &[String]) -> BenchmarkHash {
75 let mut combined_source = String::new();
76
77 for file_content in source_files {
78 combined_source.push_str(file_content);
79 combined_source.push('\n');
80 }
81
82 self.create_hash(&combined_source, "source_code")
83 }
84
85 pub fn hash_input_data(&self, input_data: &[f32]) -> BenchmarkHash {
87 let data_string = input_data.iter()
88 .map(|x| format!("{:.10}", x))
89 .collect::<Vec<_>>()
90 .join(",");
91
92 self.create_hash(&data_string, "input_data")
93 }
94
95 pub fn hash_results(&self, results: &[Duration]) -> BenchmarkHash {
97 let results_string = results.iter()
98 .map(|d| format!("{}", d.as_nanos()))
99 .collect::<Vec<_>>()
100 .join(",");
101
102 self.create_hash(&results_string, "results")
103 }
104
105 pub fn hash_environment(&self, env_data: &HashMap<String, String>) -> BenchmarkHash {
107 let mut env_pairs: Vec<_> = env_data.iter().collect();
108 env_pairs.sort_by_key(|(k, _)| *k);
109
110 let env_string = env_pairs.iter()
111 .map(|(k, v)| format!("{}={}", k, v))
112 .collect::<Vec<_>>()
113 .join(";");
114
115 self.create_hash(&env_string, "environment")
116 }
117
118 fn create_hash(&self, data: &str, context: &str) -> BenchmarkHash {
120 use std::collections::hash_map::DefaultHasher;
121 let mut hasher = DefaultHasher::new();
122
123 self.salt.hash(&mut hasher);
125 context.hash(&mut hasher);
126 data.hash(&mut hasher);
127
128 let hash = format!("{:x}", hasher.finish());
129
130 BenchmarkHash {
131 algorithm: "SipHash-2-4".to_string(),
132 hash,
133 salt: self.salt.clone(),
134 timestamp: SystemTime::now()
135 .duration_since(UNIX_EPOCH)
136 .unwrap()
137 .as_secs(),
138 }
139 }
140
141 pub fn verify_hash(&self, original: &BenchmarkHash, data: &str, context: &str) -> bool {
143 let recomputed = self.create_hash_with_salt(data, context, &original.salt);
144 recomputed.hash == original.hash
145 }
146
147 fn create_hash_with_salt(&self, data: &str, context: &str, salt: &str) -> BenchmarkHash {
148 use std::collections::hash_map::DefaultHasher;
149 let mut hasher = DefaultHasher::new();
150
151 salt.hash(&mut hasher);
152 context.hash(&mut hasher);
153 data.hash(&mut hasher);
154
155 let hash = format!("{:x}", hasher.finish());
156
157 BenchmarkHash {
158 algorithm: "SipHash-2-4".to_string(),
159 hash,
160 salt: salt.to_string(),
161 timestamp: SystemTime::now()
162 .duration_since(UNIX_EPOCH)
163 .unwrap()
164 .as_secs(),
165 }
166 }
167
168 pub fn create_integrity_proof(
170 &self,
171 source_files: &[String],
172 input_data: &[f32],
173 results: &[Duration],
174 environment: &HashMap<String, String>,
175 ) -> IntegrityProof {
176 let code_hash = self.hash_source_code(source_files);
177 let data_hash = self.hash_input_data(input_data);
178 let results_hash = self.hash_results(results);
179 let environment_hash = self.hash_environment(environment);
180
181 let mut chain = Vec::new();
183
184 chain.push(CustodyEntry {
185 timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(),
186 operation: "benchmark_created".to_string(),
187 actor: "temporal_neural_solver".to_string(),
188 hash_before: "0".repeat(16),
189 hash_after: code_hash.hash.clone(),
190 });
191
192 chain.push(CustodyEntry {
193 timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 1,
194 operation: "data_prepared".to_string(),
195 actor: "temporal_neural_solver".to_string(),
196 hash_before: code_hash.hash.clone(),
197 hash_after: data_hash.hash.clone(),
198 });
199
200 chain.push(CustodyEntry {
201 timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 2,
202 operation: "benchmark_executed".to_string(),
203 actor: "temporal_neural_solver".to_string(),
204 hash_before: data_hash.hash.clone(),
205 hash_after: results_hash.hash.clone(),
206 });
207
208 IntegrityProof {
209 benchmark_id: self.benchmark_id.clone(),
210 code_hash,
211 data_hash,
212 results_hash,
213 environment_hash,
214 chain_of_custody: chain,
215 verification_passed: true, }
217 }
218
219 pub fn verify_integrity_proof(&self, proof: &IntegrityProof) -> bool {
221 let mut last_timestamp = 0;
223 for entry in &proof.chain_of_custody {
224 if entry.timestamp <= last_timestamp {
225 return false;
226 }
227 last_timestamp = entry.timestamp;
228 }
229
230 for i in 1..proof.chain_of_custody.len() {
232 let prev = &proof.chain_of_custody[i - 1];
233 let curr = &proof.chain_of_custody[i];
234
235 if curr.hash_before != prev.hash_after {
236 return false;
237 }
238 }
239
240 true
241 }
242
243 pub fn generate_certificate(&self, proof: &IntegrityProof) -> BenchmarkCertificate {
245 let combined_data = format!(
247 "{}:{}:{}:{}:{}",
248 proof.code_hash.hash,
249 proof.data_hash.hash,
250 proof.results_hash.hash,
251 proof.environment_hash.hash,
252 proof.chain_of_custody.len()
253 );
254
255 let master_hash = self.create_hash(&combined_data, "certificate");
256
257 let hash_len = master_hash.hash.len().min(16);
258 let cert_id = format!("CERT-{}", &master_hash.hash[..hash_len]);
259 let verification_url = format!(
260 "https://temporal-solver.verify/{}",
261 &master_hash.hash[..hash_len]
262 );
263
264 BenchmarkCertificate {
265 certificate_id: cert_id,
266 benchmark_id: proof.benchmark_id.clone(),
267 master_hash,
268 issued_at: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(),
269 issuer: "Temporal Neural Solver Validation System".to_string(),
270 validity_period: 365 * 24 * 3600, verification_url,
272 }
273 }
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct BenchmarkCertificate {
279 pub certificate_id: String,
280 pub benchmark_id: String,
281 pub master_hash: BenchmarkHash,
282 pub issued_at: u64,
283 pub issuer: String,
284 pub validity_period: u64,
285 pub verification_url: String,
286}
287
288impl BenchmarkCertificate {
289 pub fn is_valid(&self) -> bool {
291 let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
292 now < self.issued_at + self.validity_period
293 }
294
295 pub fn to_json(&self) -> Result<String, serde_json::Error> {
297 serde_json::to_string_pretty(self)
298 }
299
300 pub fn verify_signature(&self) -> bool {
302 !self.certificate_id.is_empty() && !self.master_hash.hash.is_empty()
304 }
305}
306
307pub struct ReproducibilityValidator;
309
310impl ReproducibilityValidator {
311 pub fn validate_reproducibility(
313 &self,
314 original_results: &[Duration],
315 reproduced_results: &[Duration],
316 tolerance_percent: f64,
317 ) -> ReproducibilityReport {
318 let mut deviations = Vec::new();
319 let mut max_deviation = 0.0;
320 let mut valid_count = 0;
321
322 for (i, (&orig, &repro)) in original_results.iter()
323 .zip(reproduced_results.iter())
324 .enumerate() {
325
326 let orig_ns = orig.as_nanos() as f64;
327 let repro_ns = repro.as_nanos() as f64;
328
329 let deviation = ((repro_ns - orig_ns) / orig_ns * 100.0).abs();
330 deviations.push(deviation);
331
332 if deviation > max_deviation {
333 max_deviation = deviation;
334 }
335
336 if deviation <= tolerance_percent {
337 valid_count += 1;
338 }
339 }
340
341 let success_rate = valid_count as f64 / original_results.len() as f64;
342 let avg_deviation = deviations.iter().sum::<f64>() / deviations.len() as f64;
343
344 ReproducibilityReport {
345 total_samples: original_results.len(),
346 valid_samples: valid_count,
347 success_rate,
348 avg_deviation_percent: avg_deviation,
349 max_deviation_percent: max_deviation,
350 tolerance_percent,
351 is_reproducible: success_rate >= 0.95 && avg_deviation <= tolerance_percent,
352 }
353 }
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize)]
357pub struct ReproducibilityReport {
358 pub total_samples: usize,
359 pub valid_samples: usize,
360 pub success_rate: f64,
361 pub avg_deviation_percent: f64,
362 pub max_deviation_percent: f64,
363 pub tolerance_percent: f64,
364 pub is_reproducible: bool,
365}
366
367pub fn generate_validation_report(
369 proof: &IntegrityProof,
370 certificate: &BenchmarkCertificate,
371 reproducibility: &ReproducibilityReport,
372) -> String {
373 let mut report = String::new();
374
375 report.push_str(&format!("\n{}\n", "=".repeat(60)));
376 report.push_str("CRYPTOGRAPHIC VALIDATION REPORT\n");
377 report.push_str(&format!("{}\n", "=".repeat(60)));
378
379 report.push_str(&format!("Benchmark ID: {}\n", proof.benchmark_id));
380 report.push_str(&format!("Certificate ID: {}\n", certificate.certificate_id));
381
382 report.push_str("\nš HASH INTEGRITY:\n");
383 report.push_str(&format!("⢠Code Hash: {} ({})\n",
384 &proof.code_hash.hash[..16], proof.code_hash.algorithm));
385 report.push_str(&format!("⢠Data Hash: {} ({})\n",
386 &proof.data_hash.hash[..16], proof.data_hash.algorithm));
387 report.push_str(&format!("⢠Results Hash: {} ({})\n",
388 &proof.results_hash.hash[..16], proof.results_hash.algorithm));
389 report.push_str(&format!("⢠Environment Hash: {} ({})\n",
390 &proof.environment_hash.hash[..16], proof.environment_hash.algorithm));
391
392 report.push_str("\nš CHAIN OF CUSTODY:\n");
393 for (i, entry) in proof.chain_of_custody.iter().enumerate() {
394 report.push_str(&format!("{}. {} by {} at {}\n",
395 i + 1, entry.operation, entry.actor, entry.timestamp));
396 report.push_str(&format!(" Hash: {} -> {}\n",
397 &entry.hash_before[..8], &entry.hash_after[..8]));
398 }
399
400 report.push_str("\nš REPRODUCIBILITY:\n");
401 report.push_str(&format!("⢠Success Rate: {:.1}%\n",
402 reproducibility.success_rate * 100.0));
403 report.push_str(&format!("⢠Average Deviation: {:.2}%\n",
404 reproducibility.avg_deviation_percent));
405 report.push_str(&format!("⢠Max Deviation: {:.2}%\n",
406 reproducibility.max_deviation_percent));
407 report.push_str(&format!("⢠Tolerance: {:.1}%\n",
408 reproducibility.tolerance_percent));
409
410 report.push_str("\nš CERTIFICATE:\n");
411 report.push_str(&format!("⢠Issuer: {}\n", certificate.issuer));
412 report.push_str(&format!("⢠Valid: {}\n",
413 if certificate.is_valid() { "ā
Yes" } else { "ā Expired" }));
414 report.push_str(&format!("⢠Verification URL: {}\n", certificate.verification_url));
415
416 let overall_valid = proof.verification_passed &&
417 certificate.is_valid() &&
418 reproducibility.is_reproducible;
419
420 report.push_str(&format!("\nšÆ CRYPTOGRAPHIC VALIDATION: {}\n",
421 if overall_valid { "ā
PASSED" } else { "ā FAILED" }));
422
423 if overall_valid {
424 report.push_str("⢠All hashes verified\n");
425 report.push_str("⢠Chain of custody intact\n");
426 report.push_str("⢠Results are reproducible\n");
427 report.push_str("⢠Certificate is valid\n");
428 }
429
430 report
431}
432
433#[cfg(test)]
434mod tests {
435 use super::*;
436
437 #[test]
438 fn test_cryptographic_validation() {
439 let validator = CryptographicValidator::new("test_benchmark".to_string());
440
441 let source_files = vec!["fn main() { println!(\"test\"); }".to_string()];
443 let input_data = vec![0.1f32; 128];
444 let results = vec![Duration::from_micros(100); 1000];
445 let mut environment = HashMap::new();
446 environment.insert("RUST_VERSION".to_string(), "1.70.0".to_string());
447 environment.insert("TARGET".to_string(), "x86_64-unknown-linux-gnu".to_string());
448
449 let proof = validator.create_integrity_proof(
451 &source_files, &input_data, &results, &environment
452 );
453
454 let certificate = validator.generate_certificate(&proof);
456
457 let repro_validator = ReproducibilityValidator;
459 let repro_results = vec![Duration::from_micros(99); 1000]; let repro_report = repro_validator.validate_reproducibility(
461 &results, &repro_results, 5.0 );
463
464 let report = generate_validation_report(&proof, &certificate, &repro_report);
466 println!("{}", report);
467
468 assert!(proof.verification_passed);
469 assert!(certificate.is_valid());
470 assert!(repro_report.is_reproducible);
471 }
472
473 #[test]
474 fn test_hash_verification() {
475 let validator = CryptographicValidator::new("hash_test".to_string());
476
477 let data = "test_data";
478 let context = "test_context";
479 let hash = validator.create_hash(data, context);
480
481 assert!(validator.verify_hash(&hash, data, context));
483
484 assert!(!validator.verify_hash(&hash, "tampered_data", context));
486 }
487
488 #[test]
489 fn test_chain_of_custody() {
490 let validator = CryptographicValidator::new("custody_test".to_string());
491
492 let source_files = vec!["test".to_string()];
493 let input_data = vec![1.0];
494 let results = vec![Duration::from_micros(1)];
495 let environment = HashMap::new();
496
497 let proof = validator.create_integrity_proof(
498 &source_files, &input_data, &results, &environment
499 );
500
501 assert!(validator.verify_integrity_proof(&proof));
502 assert!(proof.chain_of_custody.len() >= 3);
503 }
504}