agentic_payments/agents/
verification.rs

1//! Verification agent implementation
2
3use super::{AgentStatus, BasicVerificationAgent};
4use crate::crypto::{verify_signature, Signature};
5use crate::error::{Error, Result};
6use ed25519_dalek::VerifyingKey;
7use std::time::Instant;
8use tracing::{debug, warn};
9
10/// Verification task
11#[derive(Debug, Clone)]
12pub struct VerificationTask {
13    /// Message to verify
14    pub message: Vec<u8>,
15    /// Signature to verify
16    pub signature: Signature,
17    /// Public key for verification
18    pub public_key: VerifyingKey,
19}
20
21impl VerificationTask {
22    /// Create a new verification task
23    pub fn new(message: Vec<u8>, signature: Signature, public_key: VerifyingKey) -> Self {
24        Self {
25            message,
26            signature,
27            public_key,
28        }
29    }
30}
31
32/// Verification result from an agent
33#[derive(Debug, Clone)]
34pub struct VerificationResult {
35    /// Whether the signature is valid
36    pub is_valid: bool,
37    /// Verification duration
38    pub duration_ms: u64,
39    /// Error message if verification failed
40    pub error: Option<String>,
41}
42
43impl VerificationResult {
44    /// Create a successful result
45    pub fn success(duration_ms: u64) -> Self {
46        Self {
47            is_valid: true,
48            duration_ms,
49            error: None,
50        }
51    }
52
53    /// Create a failed result
54    pub fn failure(duration_ms: u64, error: String) -> Self {
55        Self {
56            is_valid: false,
57            duration_ms,
58            error: Some(error),
59        }
60    }
61}
62
63impl BasicVerificationAgent {
64    /// Perform a verification task
65    pub async fn verify_task(&self, task: VerificationTask) -> VerificationResult {
66        let start = Instant::now();
67
68        // Update status
69        {
70            let mut health = self.health.lock().unwrap();
71            health.status = AgentStatus::Busy;
72            health.heartbeat();
73        }
74
75        // Perform verification
76        let result = match verify_signature(&task.public_key, &task.message, &task.signature) {
77            Ok(true) => {
78                debug!("Agent {} verified signature successfully", self.id);
79                let duration = start.elapsed();
80                self.health.lock().unwrap().record_verification(true, duration);
81                VerificationResult::success(duration.as_millis() as u64)
82            }
83            Ok(false) => {
84                warn!("Agent {} verification failed: invalid signature", self.id);
85                let duration = start.elapsed();
86                self.health.lock().unwrap().record_verification(false, duration);
87                VerificationResult::failure(duration.as_millis() as u64, "Invalid signature".to_string())
88            }
89            Err(e) => {
90                warn!("Agent {} verification error: {}", self.id, e);
91                let duration = start.elapsed();
92                self.health.lock().unwrap().record_verification(false, duration);
93                VerificationResult::failure(duration.as_millis() as u64, e.to_string())
94            }
95        };
96
97        // Update status back to healthy
98        self.health.lock().unwrap().status = AgentStatus::Healthy;
99
100        result
101    }
102
103    /// Perform multiple verifications
104    pub async fn verify_batch(&self, tasks: Vec<VerificationTask>) -> Vec<VerificationResult> {
105        let mut results = Vec::with_capacity(tasks.len());
106
107        for task in tasks {
108            results.push(self.verify_task(task).await);
109        }
110
111        results
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118    use crate::crypto::AgentIdentity;
119
120    #[tokio::test]
121    async fn test_agent_verification_success() {
122        let agent = BasicVerificationAgent::new().unwrap();
123        let identity = AgentIdentity::generate().unwrap();
124
125        let message = b"test message".to_vec();
126        let signature = identity.sign(&message).unwrap();
127
128        let task = VerificationTask::new(
129            message,
130            signature,
131            *identity.verifying_key(),
132        );
133
134        let result = agent.verify_task(task).await;
135        assert!(result.is_valid);
136        assert_eq!(agent.health.lock().unwrap().successful_verifications, 1);
137    }
138
139    #[tokio::test]
140    async fn test_agent_verification_failure() {
141        let agent = BasicVerificationAgent::new().unwrap();
142        let identity1 = AgentIdentity::generate().unwrap();
143        let identity2 = AgentIdentity::generate().unwrap();
144
145        let message = b"test message".to_vec();
146        let signature = identity1.sign(&message).unwrap();
147
148        let task = VerificationTask::new(
149            message,
150            signature,
151            *identity2.verifying_key(), // Wrong key
152        );
153
154        let result = agent.verify_task(task).await;
155        assert!(!result.is_valid);
156        assert_eq!(agent.health.lock().unwrap().failed_verifications, 1);
157    }
158
159    #[tokio::test]
160    async fn test_agent_batch_verification() {
161        let agent = BasicVerificationAgent::new().unwrap();
162        let identity = AgentIdentity::generate().unwrap();
163
164        let mut tasks = Vec::new();
165        for i in 0..5 {
166            let message = format!("message {}", i).into_bytes();
167            let signature = identity.sign(&message).unwrap();
168            tasks.push(VerificationTask::new(
169                message,
170                signature,
171                *identity.verifying_key(),
172            ));
173        }
174
175        let results = agent.verify_batch(tasks).await;
176        assert_eq!(results.len(), 5);
177        assert!(results.iter().all(|r| r.is_valid));
178    }
179}