Add events chapter
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
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<Vec<String>>) -> 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));
|
||||
}
|
||||
Reference in New Issue
Block a user