use coracle_lib::events::{ Event, EventContent, EventError, EventTemplate, HashedEvent, OwnedEvent, StampedEvent, }; use coracle_lib::keys::SecretKey; fn fixed_secret() -> SecretKey { let bytes: [u8; 32] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]; SecretKey::from_hex(&hex::encode(bytes)).unwrap() } fn build_hashed(content: &str, tags: Vec>) -> HashedEvent { EventContent::new(content, tags) .kind(1) .stamp(1_700_000_000) .own(fixed_secret().public_key()) .hash() } fn sign_fixture() -> Event { let sk = fixed_secret(); let hashed = build_hashed("hello nostr", vec![vec!["t".into(), "nostr".into()]]); let sig = sk.sign(&hashed.id); hashed.sign(sig) } #[test] fn pipeline_progresses_through_types() { let content = EventContent::new("hi", vec![]); let template: EventTemplate = content.kind(1); let stamped: StampedEvent = template.stamp(1_700_000_000); let owned: OwnedEvent = stamped.own(fixed_secret().public_key()); let hashed: HashedEvent = owned.hash(); let sig = fixed_secret().sign(&hashed.id); let event: Event = hashed.sign(sig); assert_eq!(event.content, "hi"); assert_eq!(event.kind, 1); } #[test] fn id_is_deterministic() { let a = build_hashed("hello", vec![]); let b = build_hashed("hello", vec![]); assert_eq!(a.id, b.id); } #[test] fn id_changes_with_content() { let a = build_hashed("hello", vec![]); let b = build_hashed("goodbye", vec![]); assert_ne!(a.id, b.id); } #[test] fn sign_and_verify_roundtrip() { let event = sign_fixture(); assert!(event.verify_id()); event.verify().expect("signature should verify"); } #[test] fn tampered_content_fails_id_check() { let mut event = sign_fixture(); event.content = "something else".to_string(); assert!(!event.verify_id()); assert_eq!(event.verify(), Err(EventError::InvalidId)); } #[test] fn tampered_sig_fails_verify() { let mut event = sign_fixture(); event.sig[0] ^= 0x01; assert_eq!(event.verify(), Err(EventError::InvalidSignature)); } #[test] fn json_roundtrip() { let event = sign_fixture(); let json = serde_json::to_string(&event).unwrap(); let parsed: Event = serde_json::from_str(&json).unwrap(); assert_eq!(parsed, event); parsed.verify().expect("roundtripped event still verifies"); } #[test] fn json_contains_hex_fields() { let event = sign_fixture(); let value: serde_json::Value = serde_json::to_value(&event).unwrap(); let obj = value.as_object().unwrap(); assert_eq!(obj["id"].as_str().unwrap().len(), 64); assert_eq!(obj["pubkey"].as_str().unwrap().len(), 64); assert_eq!(obj["sig"].as_str().unwrap().len(), 128); assert_eq!(obj["kind"].as_u64().unwrap(), 1); assert_eq!(obj["content"].as_str().unwrap(), "hello nostr"); assert!(obj["tags"].is_array()); } #[test] fn json_ignores_unknown_fields() { let event = sign_fixture(); let mut value: serde_json::Value = serde_json::to_value(&event).unwrap(); value .as_object_mut() .unwrap() .insert("custom_field".to_string(), serde_json::json!("ignored")); let reparsed: Event = serde_json::from_value(value).unwrap(); assert_eq!(reparsed, event); } #[test] fn secret_key_sign_is_deterministic() { let sk = fixed_secret(); let msg = [42u8; 32]; assert_eq!(sk.sign(&msg), sk.sign(&msg)); }