agentic_payments/agents/
verification.rs1use 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#[derive(Debug, Clone)]
12pub struct VerificationTask {
13 pub message: Vec<u8>,
15 pub signature: Signature,
17 pub public_key: VerifyingKey,
19}
20
21impl VerificationTask {
22 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#[derive(Debug, Clone)]
34pub struct VerificationResult {
35 pub is_valid: bool,
37 pub duration_ms: u64,
39 pub error: Option<String>,
41}
42
43impl VerificationResult {
44 pub fn success(duration_ms: u64) -> Self {
46 Self {
47 is_valid: true,
48 duration_ms,
49 error: None,
50 }
51 }
52
53 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 pub async fn verify_task(&self, task: VerificationTask) -> VerificationResult {
66 let start = Instant::now();
67
68 {
70 let mut health = self.health.lock().unwrap();
71 health.status = AgentStatus::Busy;
72 health.heartbeat();
73 }
74
75 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 self.health.lock().unwrap().status = AgentStatus::Healthy;
99
100 result
101 }
102
103 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(), );
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}