1use super::{Ap2Error, Result};
4use crate::ap2::credentials::VerifiableCredential;
5use crate::ap2::did::DidResolver;
6use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use tokio::sync::RwLock;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct VerificationResult {
14 pub verified: bool,
15 pub consensus_achieved: bool,
16 pub verifier_count: usize,
17 pub approval_count: usize,
18 pub rejection_count: usize,
19 pub threshold_percentage: f64,
20 pub verifier_results: Vec<VerifierResult>,
21 pub timestamp: DateTime<Utc>,
22 pub metadata: HashMap<String, String>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct VerifierResult {
28 pub verifier_id: String,
29 pub verified: bool,
30 pub timestamp: DateTime<Utc>,
31 pub reason: Option<String>,
32}
33
34#[derive(Debug, Clone)]
36pub struct VerifierNode {
37 pub id: String,
38 pub did: String,
39 pub endpoint: String,
40 pub weight: f64, pub reputation: f64,
42}
43
44impl VerifierNode {
45 pub fn new(id: String, did: String, endpoint: String) -> Self {
46 Self {
47 id,
48 did,
49 endpoint,
50 weight: 1.0,
51 reputation: 1.0,
52 }
53 }
54
55 pub fn with_weight(mut self, weight: f64) -> Self {
56 self.weight = weight;
57 self
58 }
59
60 pub fn with_reputation(mut self, reputation: f64) -> Self {
61 self.reputation = reputation;
62 self
63 }
64}
65
66#[derive(Debug)]
68pub struct ConsensusVerification {
69 threshold: f64, min_verifiers: usize, timeout_seconds: u64, }
73
74impl ConsensusVerification {
75 pub fn new(threshold: f64, min_verifiers: usize) -> Self {
76 Self {
77 threshold: threshold.clamp(0.0, 1.0),
78 min_verifiers,
79 timeout_seconds: 30,
80 }
81 }
82
83 pub fn with_timeout(mut self, timeout_seconds: u64) -> Self {
84 self.timeout_seconds = timeout_seconds;
85 self
86 }
87
88 pub async fn verify(
90 &self,
91 credential: &VerifiableCredential,
92 verifiers: Vec<VerifierNode>,
93 did_resolver: &DidResolver,
94 ) -> Result<VerificationResult> {
95 if verifiers.len() < self.min_verifiers {
96 return Err(Ap2Error::ConsensusVerificationFailed(format!(
97 "Insufficient verifiers: {} < {}",
98 verifiers.len(),
99 self.min_verifiers
100 )));
101 }
102
103 let signature_valid = credential.verify(did_resolver)?;
105 if !signature_valid {
106 return Ok(VerificationResult {
107 verified: false,
108 consensus_achieved: false,
109 verifier_count: 0,
110 approval_count: 0,
111 rejection_count: 0,
112 threshold_percentage: self.threshold,
113 verifier_results: vec![],
114 timestamp: Utc::now(),
115 metadata: HashMap::from([(
116 "error".to_string(),
117 "Signature verification failed".to_string(),
118 )]),
119 });
120 }
121
122 let verification_futures: Vec<_> = verifiers
124 .iter()
125 .map(|verifier| self.verify_with_node(credential, verifier, did_resolver))
126 .collect();
127
128 let results = futures::future::join_all(verification_futures).await;
129
130 let verifier_results: Vec<VerifierResult> = results.into_iter().flatten().collect();
132
133 let total_weight: f64 = verifiers.iter().map(|v| v.weight * v.reputation).sum();
134 let approval_weight: f64 = verifier_results
135 .iter()
136 .zip(verifiers.iter())
137 .filter(|(r, _)| r.verified)
138 .map(|(_, v)| v.weight * v.reputation)
139 .sum();
140
141 let approval_percentage = if total_weight > 0.0 {
142 approval_weight / total_weight
143 } else {
144 0.0
145 };
146
147 let approval_count = verifier_results.iter().filter(|r| r.verified).count();
148 let rejection_count = verifier_results.len() - approval_count;
149 let consensus_achieved = approval_percentage >= self.threshold;
150
151 Ok(VerificationResult {
152 verified: consensus_achieved,
153 consensus_achieved,
154 verifier_count: verifiers.len(),
155 approval_count,
156 rejection_count,
157 threshold_percentage: self.threshold,
158 verifier_results,
159 timestamp: Utc::now(),
160 metadata: HashMap::from([
161 ("approval_percentage".to_string(), approval_percentage.to_string()),
162 ("total_weight".to_string(), total_weight.to_string()),
163 ("approval_weight".to_string(), approval_weight.to_string()),
164 ]),
165 })
166 }
167
168 async fn verify_with_node(
170 &self,
171 credential: &VerifiableCredential,
172 verifier: &VerifierNode,
173 did_resolver: &DidResolver,
174 ) -> Result<VerifierResult> {
175 let verified = credential.verify(did_resolver).unwrap_or(false);
178
179 Ok(VerifierResult {
180 verifier_id: verifier.id.clone(),
181 verified,
182 timestamp: Utc::now(),
183 reason: if verified {
184 None
185 } else {
186 Some("Verification failed".to_string())
187 },
188 })
189 }
190}
191
192impl Default for ConsensusVerification {
193 fn default() -> Self {
194 Self::new(0.66, 3) }
196}
197
198#[derive(Debug)]
200pub struct VerificationWorkflow {
201 consensus: ConsensusVerification,
202 verifier_registry: RwLock<HashMap<String, VerifierNode>>,
203}
204
205impl VerificationWorkflow {
206 pub fn new() -> Self {
207 Self {
208 consensus: ConsensusVerification::default(),
209 verifier_registry: RwLock::new(HashMap::new()),
210 }
211 }
212
213 pub fn with_consensus(mut self, consensus: ConsensusVerification) -> Self {
214 self.consensus = consensus;
215 self
216 }
217
218 pub async fn register_verifier(&self, verifier: VerifierNode) {
220 let mut registry = self.verifier_registry.write().await;
221 registry.insert(verifier.id.clone(), verifier);
222 }
223
224 pub async fn unregister_verifier(&self, verifier_id: &str) -> bool {
226 let mut registry = self.verifier_registry.write().await;
227 registry.remove(verifier_id).is_some()
228 }
229
230 pub async fn get_verifiers(&self) -> Vec<VerifierNode> {
232 let registry = self.verifier_registry.read().await;
233 registry.values().cloned().collect()
234 }
235
236 pub async fn get_verifier(&self, verifier_id: &str) -> Option<VerifierNode> {
238 let registry = self.verifier_registry.read().await;
239 registry.get(verifier_id).cloned()
240 }
241
242 pub async fn verify_with_consensus(
244 &self,
245 credential: &VerifiableCredential,
246 verifiers: Vec<VerifierNode>,
247 did_resolver: &DidResolver,
248 ) -> Result<VerificationResult> {
249 self.consensus.verify(credential, verifiers, did_resolver).await
250 }
251
252 pub async fn verify_with_all_verifiers(
254 &self,
255 credential: &VerifiableCredential,
256 did_resolver: &DidResolver,
257 ) -> Result<VerificationResult> {
258 let verifiers = self.get_verifiers().await;
259 self.verify_with_consensus(credential, verifiers, did_resolver).await
260 }
261
262 pub async fn update_verifier_reputation(&self, verifier_id: &str, reputation_delta: f64) {
264 let mut registry = self.verifier_registry.write().await;
265 if let Some(verifier) = registry.get_mut(verifier_id) {
266 verifier.reputation = (verifier.reputation + reputation_delta).clamp(0.0, 2.0);
267 }
268 }
269}
270
271impl Default for VerificationWorkflow {
272 fn default() -> Self {
273 Self::new()
274 }
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct VerificationPolicy {
280 pub min_verifiers: usize,
281 pub consensus_threshold: f64,
282 pub timeout_seconds: u64,
283 pub require_signature: bool,
284 pub require_expiration_check: bool,
285 pub allowed_credential_types: Vec<String>,
286}
287
288impl VerificationPolicy {
289 pub fn strict() -> Self {
290 Self {
291 min_verifiers: 5,
292 consensus_threshold: 0.8,
293 timeout_seconds: 30,
294 require_signature: true,
295 require_expiration_check: true,
296 allowed_credential_types: vec!["VerifiableCredential".to_string()],
297 }
298 }
299
300 pub fn standard() -> Self {
301 Self {
302 min_verifiers: 3,
303 consensus_threshold: 0.66,
304 timeout_seconds: 30,
305 require_signature: true,
306 require_expiration_check: true,
307 allowed_credential_types: vec![],
308 }
309 }
310
311 pub fn permissive() -> Self {
312 Self {
313 min_verifiers: 1,
314 consensus_threshold: 0.5,
315 timeout_seconds: 60,
316 require_signature: true,
317 require_expiration_check: false,
318 allowed_credential_types: vec![],
319 }
320 }
321
322 pub fn validate(&self, credential: &VerifiableCredential) -> Result<()> {
323 if self.require_expiration_check && credential.is_expired() {
324 return Err(Ap2Error::Expired);
325 }
326
327 if !self.allowed_credential_types.is_empty() {
328 let has_allowed_type = credential
329 .types
330 .iter()
331 .any(|t| self.allowed_credential_types.contains(t));
332
333 if !has_allowed_type {
334 return Err(Ap2Error::InvalidCredential(
335 "Credential type not allowed by policy".to_string(),
336 ));
337 }
338 }
339
340 Ok(())
341 }
342}
343
344impl Default for VerificationPolicy {
345 fn default() -> Self {
346 Self::standard()
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 use super::*;
353
354 #[test]
355 fn test_verifier_node_creation() {
356 let node = VerifierNode::new(
357 "verifier1".to_string(),
358 "did:ap2:verifier1".to_string(),
359 "https://verifier1.example.com".to_string(),
360 );
361
362 assert_eq!(node.weight, 1.0);
363 assert_eq!(node.reputation, 1.0);
364 }
365
366 #[test]
367 fn test_consensus_verification_initialization() {
368 let consensus = ConsensusVerification::new(0.66, 3);
369 assert_eq!(consensus.threshold, 0.66);
370 assert_eq!(consensus.min_verifiers, 3);
371 }
372
373 #[test]
374 fn test_verification_policy_validation() {
375 let policy = VerificationPolicy::strict();
376 assert_eq!(policy.min_verifiers, 5);
377 assert_eq!(policy.consensus_threshold, 0.8);
378 }
379
380 #[tokio::test]
381 async fn test_workflow_verifier_registration() {
382 let workflow = VerificationWorkflow::new();
383 let verifier = VerifierNode::new(
384 "test1".to_string(),
385 "did:ap2:test1".to_string(),
386 "https://test1.example.com".to_string(),
387 );
388
389 workflow.register_verifier(verifier.clone()).await;
390
391 let verifiers = workflow.get_verifiers().await;
392 assert_eq!(verifiers.len(), 1);
393 assert_eq!(verifiers[0].id, "test1");
394 }
395}