sentri_core/registry/
mod.rs1use once_cell::sync::Lazy;
8use serde::{Deserialize, Serialize};
9use std::collections::BTreeMap;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Exploit {
14 pub id: String,
16 pub protocol: String,
18 pub date: String,
20 pub loss_usd: u64,
22 pub chain: String,
24 pub invariant_ids: Vec<String>,
26 pub attack_summary: String,
28 pub tx_hash: String,
30 pub postmortem_url: String,
32}
33
34static EXPLOIT_REGISTRY_JSON: &[u8] = include_bytes!("exploits.json");
36
37pub static EXPLOIT_REGISTRY: Lazy<ExploitRegistry> =
39 Lazy::new(|| ExploitRegistry::load().expect("Failed to parse exploit registry"));
40
41#[derive(Debug, Clone)]
43pub struct ExploitRegistry {
44 exploits: BTreeMap<String, Exploit>,
45}
46
47impl ExploitRegistry {
48 fn load() -> Result<Self, Box<dyn std::error::Error>> {
50 let exploits: Vec<Exploit> = serde_json::from_slice(EXPLOIT_REGISTRY_JSON)?;
51 let mut map = BTreeMap::new();
52 for exploit in exploits {
53 map.insert(exploit.id.clone(), exploit);
54 }
55 Ok(Self { exploits: map })
56 }
57
58 pub fn get(&self, id: &str) -> Option<&Exploit> {
60 self.exploits.get(id)
61 }
62
63 pub fn all(&self) -> Vec<&Exploit> {
65 self.exploits.values().collect()
66 }
67
68 pub fn by_chain(&self, chain: &str) -> Vec<&Exploit> {
70 self.exploits
71 .values()
72 .filter(|e| e.chain.eq_ignore_ascii_case(chain))
73 .collect()
74 }
75
76 pub fn by_invariant(&self, invariant_id: &str) -> Vec<&Exploit> {
78 self.exploits
79 .values()
80 .filter(|e| e.invariant_ids.iter().any(|id| id == invariant_id))
81 .collect()
82 }
83
84 pub fn total_loss(&self) -> u64 {
86 self.exploits.values().map(|e| e.loss_usd).sum()
87 }
88
89 pub fn count(&self) -> usize {
91 self.exploits.len()
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn test_registry_loads() {
101 let registry = &*EXPLOIT_REGISTRY;
102 assert!(registry.count() > 0, "Registry should have exploits");
103 }
104
105 #[test]
106 fn test_registry_access() {
107 let registry = &*EXPLOIT_REGISTRY;
108 let all = registry.all();
109 assert!(!all.is_empty());
110
111 for exploit in all {
113 assert!(!exploit.id.is_empty());
114 assert!(!exploit.protocol.is_empty());
115 assert!(!exploit.chain.is_empty());
116 }
117 }
118}