//! Agent types for simulation testing. use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey}; use rand::rngs::OsRng; use stemedb_core::types::{ Assertion, Hash, HlcTimestamp, LifecycleStage, ObjectValue, SignatureEntry, SourceClass, Vote, }; /// A simulated agent with a cryptographic identity. pub(crate) struct Agent { pub id: String, signing_key: SigningKey, verifying_key: VerifyingKey, } impl Agent { pub fn new(id: &str) -> Self { let mut csprng = OsRng; let signing_key = SigningKey::generate(&mut csprng); let verifying_key = VerifyingKey::from(&signing_key); Self { id: id.to_string(), signing_key, verifying_key } } /// Get the agent's public key as a 32-byte array. pub fn public_key(&self) -> [u8; 32] { self.verifying_key.to_bytes() } /// Create and sign an assertion with custom lifecycle and timestamp. pub fn sign_assertion_with_options( &self, subject: &str, predicate: &str, object: ObjectValue, lifecycle: LifecycleStage, custom_timestamp: Option, ) -> Assertion { let timestamp = custom_timestamp.unwrap_or_else(|| { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map(|d| d.as_secs()) .unwrap_or(0) }); // For simulation, we sign the concatenation of subject and predicate. // In a real system, we'd sign the hash of the fact data. let message = format!("{}:{}", subject, predicate); let signature: Signature = self.signing_key.sign(message.as_bytes()); Assertion { subject: subject.to_string(), predicate: predicate.to_string(), object, parent_hash: None, source_hash: [0u8; 32], source_class: SourceClass::Expert, visual_hash: None, epoch: None, source_metadata: None, lifecycle, signatures: vec![SignatureEntry { agent_id: self.verifying_key.to_bytes(), signature: signature.to_bytes(), timestamp, version: 1, }], confidence: 1.0, timestamp, hlc_timestamp: HlcTimestamp::default(), vector: None, } } /// Create and sign a vote for an assertion. /// /// The agent signs the assertion_hash to prove authenticity. pub fn vote(&self, assertion_hash: Hash, weight: f32) -> Vote { let timestamp = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map(|d| d.as_secs()) .unwrap_or(0); // Sign the assertion hash to prove we're voting on this specific assertion let signature: Signature = self.signing_key.sign(&assertion_hash); Vote { assertion_hash, agent_id: self.verifying_key.to_bytes(), weight, signature: signature.to_bytes(), timestamp, source_url: None, observed_context: None, } } }