nostr_db/
event.rs

1use crate::error::Error;
2use rkyv::{
3    vec::ArchivedVec, AlignedVec, Archive, Archived, Deserialize as RkyvDeserialize,
4    Serialize as RkyvSerialize,
5};
6use secp256k1::{schnorr::Signature, Keypair, Message, XOnlyPublicKey, SECP256K1};
7use serde::{Deserialize, Serialize};
8use serde_json::{json, Value};
9use sha2::{Digest, Sha256};
10use std::{
11    fmt::Display,
12    str::FromStr,
13    time::{SystemTime, UNIX_EPOCH},
14};
15
16type Tags = Vec<(Vec<u8>, Vec<u8>)>;
17type BuildTags = (Tags, Option<u64>, Option<[u8; 32]>);
18#[derive(
19    Serialize,
20    Deserialize,
21    PartialEq,
22    Eq,
23    Debug,
24    Clone,
25    Default,
26    Archive,
27    RkyvDeserialize,
28    RkyvSerialize,
29)]
30pub struct EventIndex {
31    #[serde(with = "hex::serde")]
32    id: [u8; 32],
33
34    #[serde(with = "hex::serde")]
35    pubkey: [u8; 32],
36
37    created_at: u64,
38
39    kind: u16,
40
41    #[serde(skip)]
42    tags: Tags,
43
44    #[serde(skip)]
45    expiration: Option<u64>,
46
47    /// [NIP-26](https://nips.be/26)
48    #[serde(skip)]
49    delegator: Option<[u8; 32]>,
50}
51
52impl EventIndex {
53    pub fn from_zeroes(bytes: &[u8]) -> Result<&ArchivedEventIndex, Error> {
54        let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
55        Ok(archived)
56    }
57
58    pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<Self, Error> {
59        let bytes = bytes.as_ref();
60        let archived = unsafe { rkyv::archived_root::<Self>(bytes) };
61        let deserialized: Self = archived
62            .deserialize(&mut rkyv::Infallible)
63            .map_err(|e| Error::Deserialization(e.to_string()))?;
64        Ok(deserialized)
65    }
66
67    pub fn to_bytes(&self) -> Result<AlignedVec, Error> {
68        let vec =
69            rkyv::to_bytes::<_, 256>(self).map_err(|e| Error::Serialization(e.to_string()))?;
70        Ok(vec)
71    }
72
73    pub fn new(
74        id: [u8; 32],
75        pubkey: [u8; 32],
76        created_at: u64,
77        kind: u16,
78        tags: &Vec<Vec<String>>,
79    ) -> Result<Self, Error> {
80        let (tags, expiration, delegator) = Self::build_index_tags(tags)?;
81        Ok(Self {
82            id,
83            pubkey,
84            created_at,
85            kind,
86            tags,
87            expiration,
88            delegator,
89        })
90    }
91
92    pub fn build_index_tags(tags: &Vec<Vec<String>>) -> Result<BuildTags, Error> {
93        let mut t = vec![];
94        let mut expiration = None;
95        let mut delegator = None;
96
97        for tag in tags {
98            if tag.len() > 1 {
99                if tag[0] == "expiration" {
100                    expiration = Some(
101                        u64::from_str(&tag[1])
102                            .map_err(|_| Error::Invalid("invalid expiration".to_string()))?,
103                    );
104                } else if tag[0] == "delegation" {
105                    let mut h = [0u8; 32];
106                    hex::decode_to_slice(&tag[1], &mut h)?;
107                    delegator = Some(h);
108                }
109
110                let key = tag[0].as_bytes().to_vec();
111                // only index key length 1
112                // 0 will break the index separator, ignore
113                if key.len() == 1 && key[0] != 0 {
114                    let v;
115                    // fixed length 32 e and p
116                    if tag[0] == "e" || tag[0] == "p" {
117                        let h = hex::decode(&tag[1])?;
118                        if h.len() != 32 {
119                            return Err(Error::Invalid("invalid e or p tag value".to_string()));
120                        }
121                        v = h;
122                    } else {
123                        v = tag[1].as_bytes().to_vec();
124                        // 0 will break the index separator, ignore
125                        // lmdb max_key_size 511 bytes
126                        // we only index tag value length < 255
127                        if v.contains(&0) || v.len() > 255 {
128                            continue;
129                        }
130                    };
131                    t.push((key, v));
132                }
133            }
134        }
135        Ok((t, expiration, delegator))
136    }
137
138    pub fn id(&self) -> &[u8; 32] {
139        &self.id
140    }
141
142    pub fn pubkey(&self) -> &[u8; 32] {
143        &self.pubkey
144    }
145
146    pub fn created_at(&self) -> u64 {
147        self.created_at
148    }
149
150    pub fn kind(&self) -> u16 {
151        self.kind
152    }
153
154    pub fn tags(&self) -> &Vec<(Vec<u8>, Vec<u8>)> {
155        &self.tags
156    }
157
158    pub fn expiration(&self) -> Option<&u64> {
159        self.expiration.as_ref()
160    }
161
162    pub fn delegator(&self) -> Option<&[u8; 32]> {
163        self.delegator.as_ref()
164    }
165
166    pub fn is_ephemeral(&self) -> bool {
167        let kind = self.kind;
168        (20_000..30_000).contains(&kind)
169    }
170
171    pub fn is_expired(&self, now: u64) -> bool {
172        if let Some(exp) = self.expiration {
173            exp < now
174        } else {
175            false
176        }
177    }
178}
179
180impl ArchivedEventIndex {
181    pub fn id(&self) -> &Archived<[u8; 32]> {
182        &self.id
183    }
184    pub fn pubkey(&self) -> &Archived<[u8; 32]> {
185        &self.pubkey
186    }
187
188    pub fn created_at(&self) -> u64 {
189        self.created_at
190    }
191
192    pub fn kind(&self) -> u16 {
193        self.kind
194    }
195
196    pub fn tags(&self) -> &ArchivedVec<(ArchivedVec<u8>, ArchivedVec<u8>)> {
197        &self.tags
198    }
199
200    pub fn expiration(&self) -> Option<&u64> {
201        self.expiration.as_ref()
202    }
203
204    pub fn delegator(&self) -> Option<&Archived<[u8; 32]>> {
205        self.delegator.as_ref()
206    }
207
208    pub fn is_ephemeral(&self) -> bool {
209        let kind = self.kind;
210        (20_000..30_000).contains(&kind)
211    }
212
213    pub fn is_expired(&self, now: u64) -> bool {
214        if let Some(exp) = self.expiration.as_ref() {
215            exp < &now
216        } else {
217            false
218        }
219    }
220}
221// the shadow event for deserialize
222#[derive(Deserialize)]
223struct _Event {
224    #[serde(with = "hex::serde")]
225    id: [u8; 32],
226    #[serde(with = "hex::serde")]
227    pubkey: [u8; 32],
228    created_at: u64,
229    kind: u16,
230    #[serde(default)]
231    tags: Vec<Vec<String>>,
232    #[serde(default)]
233    content: String,
234    #[serde(with = "hex::serde")]
235    sig: [u8; 64],
236    // #[serde(flatten)]
237    // index: IndexEvent,
238}
239
240/// The default event document.
241// TODO: validate index tag value length 255
242#[derive(Serialize, Deserialize, Debug, Clone)]
243#[serde(try_from = "_Event")]
244pub struct Event {
245    #[serde(default)]
246    tags: Vec<Vec<String>>,
247
248    #[serde(default)]
249    content: String,
250
251    #[serde(with = "hex::serde")]
252    sig: [u8; 64],
253
254    #[serde(flatten)]
255    index: EventIndex,
256
257    #[serde(skip)]
258    pub words: Vec<Vec<u8>>,
259}
260
261impl TryFrom<_Event> for Event {
262    type Error = Error;
263
264    fn try_from(value: _Event) -> Result<Self, Self::Error> {
265        let event = Event {
266            content: value.content,
267            sig: value.sig,
268            index: EventIndex::new(
269                value.id,
270                value.pubkey,
271                value.created_at,
272                value.kind,
273                &value.tags,
274            )?,
275            tags: value.tags,
276            words: Default::default(),
277        };
278        Ok(event)
279    }
280}
281
282impl Event {
283    pub fn new(
284        id: [u8; 32],
285        pubkey: [u8; 32],
286        created_at: u64,
287        kind: u16,
288        tags: Vec<Vec<String>>,
289        content: String,
290        sig: [u8; 64],
291    ) -> Result<Self, Error> {
292        let index = EventIndex::new(id, pubkey, created_at, kind, &tags)?;
293        let event = Self {
294            tags,
295            content,
296            sig,
297            index,
298            words: Default::default(),
299        };
300        Ok(event)
301    }
302
303    pub fn create(
304        key_pair: &Keypair,
305        created_at: u64,
306        kind: u16,
307        tags: Vec<Vec<String>>,
308        content: String,
309    ) -> Result<Self, Error> {
310        let pubkey = XOnlyPublicKey::from_keypair(key_pair).0.serialize();
311        let id = hash(&pubkey, created_at, kind, &tags, &content);
312        let sig = *SECP256K1
313            .sign_schnorr(&Message::from_digest_slice(&id)?, key_pair)
314            .as_ref();
315        Self::new(id, pubkey, created_at, kind, tags, content, sig)
316    }
317}
318
319impl AsRef<Event> for Event {
320    fn as_ref(&self) -> &Event {
321        self
322    }
323}
324
325impl FromStr for Event {
326    type Err = Error;
327    fn from_str(s: &str) -> Result<Self, Self::Err> {
328        Ok(serde_json::from_str(s)?)
329    }
330}
331
332impl Display for Event {
333    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
334        let str = serde_json::to_string(&self).unwrap();
335        f.write_str(&str)?;
336        Ok(())
337    }
338}
339
340impl TryInto<String> for Event {
341    type Error = Error;
342    fn try_into(self) -> Result<String, Self::Error> {
343        Ok(serde_json::to_string(&self)?)
344    }
345}
346
347pub trait FromEventData: Sized {
348    type Err: std::error::Error;
349    /// only pass the event id to from_data
350    fn only_id() -> bool {
351        false
352    }
353    fn from_data<S: AsRef<[u8]>>(data: S) -> Result<Self, Self::Err>;
354}
355
356/// Get the event id
357impl FromEventData for Vec<u8> {
358    type Err = Error;
359    fn only_id() -> bool {
360        true
361    }
362    fn from_data<S: AsRef<[u8]>>(data: S) -> Result<Self, Self::Err> {
363        Ok(data.as_ref().to_vec())
364    }
365}
366
367/// Get the json string
368impl FromEventData for String {
369    type Err = Error;
370    fn from_data<S: AsRef<[u8]>>(json: S) -> Result<Self, Self::Err> {
371        let (t, bytes) = parse_data_type(json.as_ref());
372        if t == 1 {
373            #[cfg(feature = "zstd")]
374            {
375                let bytes = zstd::decode_all(bytes)?;
376                Ok(unsafe { String::from_utf8_unchecked(bytes) })
377            }
378            #[cfg(not(feature = "zstd"))]
379            {
380                Err(Error::Invalid("Need zstd feature".to_owned()))
381            }
382        } else {
383            Ok(unsafe { String::from_utf8_unchecked(bytes.to_vec()) })
384        }
385    }
386}
387
388fn parse_data_type(json: &[u8]) -> (u8, &[u8]) {
389    if !json.is_empty() {
390        let last = json.len() - 1;
391        let t = json[last];
392        if t == 0 || t == 1 {
393            return (t, &json[0..last]);
394        }
395    }
396    (0, json)
397}
398
399/// Parse the json string to event object
400impl FromEventData for Event {
401    type Err = Error;
402    /// decode the json data to event object
403    fn from_data<S: AsRef<[u8]>>(json: S) -> Result<Self, Self::Err> {
404        let (t, bytes) = parse_data_type(json.as_ref());
405        if t == 1 {
406            #[cfg(feature = "zstd")]
407            {
408                let bytes = zstd::decode_all(bytes)?;
409                Ok(serde_json::from_slice(&bytes)?)
410            }
411            #[cfg(not(feature = "zstd"))]
412            {
413                Err(Error::Invalid("Need zstd feature".to_owned()))
414            }
415        } else {
416            Ok(serde_json::from_slice(bytes)?)
417        }
418    }
419}
420
421#[cfg(feature = "search")]
422impl Event {
423    /// build keywords for search ability
424    pub fn build_note_words(&mut self) {
425        if self.kind() == 1 {
426            let mut words = crate::segment(&self.content);
427            self.words.append(&mut words);
428        }
429    }
430}
431
432impl Event {
433    /// to json string
434    pub fn to_json(&self) -> Result<String, Error> {
435        Ok(serde_json::to_string(&self)?)
436    }
437
438    pub fn index(&self) -> &EventIndex {
439        &self.index
440    }
441
442    pub fn id(&self) -> &[u8; 32] {
443        &self.index.id
444    }
445
446    pub fn id_str(&self) -> String {
447        hex::encode(self.index.id)
448    }
449
450    pub fn pubkey(&self) -> &[u8; 32] {
451        &self.index.pubkey
452    }
453
454    pub fn pubkey_str(&self) -> String {
455        hex::encode(self.index.pubkey)
456    }
457
458    pub fn created_at(&self) -> u64 {
459        self.index.created_at
460    }
461
462    pub fn kind(&self) -> u16 {
463        self.index.kind
464    }
465
466    pub fn tags(&self) -> &Vec<Vec<String>> {
467        &self.tags
468    }
469
470    pub fn content(&self) -> &String {
471        &self.content
472    }
473
474    pub fn sig(&self) -> &[u8; 64] {
475        &self.sig
476    }
477}
478
479pub fn now() -> u64 {
480    SystemTime::now()
481        .duration_since(UNIX_EPOCH)
482        .unwrap_or_default()
483        .as_secs()
484}
485
486fn hash(
487    pubkey: &[u8],
488    created_at: u64,
489    kind: u16,
490    tags: &Vec<Vec<String>>,
491    content: &String,
492) -> [u8; 32] {
493    let json: Value = json!([0, hex::encode(pubkey), created_at, kind, tags, content]);
494    let mut hasher = Sha256::new();
495    hasher.update(json.to_string());
496    hasher.finalize().into()
497}
498
499impl Event {
500    pub fn hash(&self) -> [u8; 32] {
501        hash(
502            self.pubkey(),
503            self.created_at(),
504            self.kind(),
505            self.tags(),
506            self.content(),
507        )
508    }
509
510    pub fn verify_id(&self) -> Result<(), Error> {
511        if &self.hash() == self.id() {
512            Ok(())
513        } else {
514            Err(Error::Invalid("bad event id".to_owned()))
515        }
516    }
517
518    pub fn verify_sign(&self) -> Result<(), Error> {
519        if verify_sign(&self.sig, self.pubkey(), self.id()).is_ok() {
520            Ok(())
521        } else {
522            Err(Error::Invalid("signature is wrong".to_owned()))
523        }
524    }
525
526    /// check event created time newer than (now - older), older than (now + newer)
527    /// ignore when 0
528    pub fn verify_time(&self, now: u64, older: u64, newer: u64) -> Result<(), Error> {
529        let time = self.created_at();
530        if 0 != older && time < now - older {
531            return Err(Error::Invalid(format!(
532                "event creation date must be newer than {}",
533                now - older
534            )));
535        }
536
537        if 0 != newer && time > now + newer {
538            return Err(Error::Invalid(format!(
539                "event creation date must be older than {}",
540                now + newer
541            )));
542        }
543        Ok(())
544    }
545
546    pub fn verify_delegation(&self) -> Result<(), Error> {
547        if self.index.delegator.is_some() {
548            for tag in self.tags() {
549                if tag.len() == 4 && tag[0] == "delegation" {
550                    return verify_delegation(self, &tag[1], &tag[2], &tag[3]);
551                }
552            }
553            Err(Error::Invalid("error delegation arguments".to_owned()))
554        } else {
555            Ok(())
556        }
557    }
558
559    pub fn validate(&self, now: u64, older: u64, newer: u64) -> Result<(), Error> {
560        if self.index.is_expired(now) {
561            return Err(Error::Invalid("event is expired".to_owned()));
562        }
563        self.verify_time(now, older, newer)?;
564        self.verify_id()?;
565        self.verify_sign()?;
566        self.verify_delegation()?;
567        Ok(())
568    }
569}
570
571fn verify_delegation(
572    event: &Event,
573    delegator: &String,
574    conditions: &String,
575    sig: &String,
576) -> Result<(), Error> {
577    let msg = format!(
578        "nostr:delegation:{}:{}",
579        hex::encode(event.pubkey()),
580        conditions
581    );
582    let mut hasher = Sha256::new();
583    hasher.update(msg);
584    let token = hasher.finalize().to_vec();
585    verify_sign(&hex::decode(sig)?, &hex::decode(delegator)?, &token)?;
586    let time = event.created_at();
587    // check conditions
588    for cond in conditions.split('&') {
589        if let Some(kind) = cond.strip_prefix("kind=") {
590            let n = u16::from_str(kind)?;
591            if n != event.kind() {
592                return Err(Error::Invalid(format!(
593                    "event kind must be {}",
594                    event.kind()
595                )));
596            }
597        }
598        if let Some(t) = cond.strip_prefix("created_at<") {
599            let n = u64::from_str(t)?;
600            if time >= n {
601                return Err(Error::Invalid(format!(
602                    "event created_at must older than {}",
603                    n
604                )));
605            }
606        }
607        if let Some(t) = cond.strip_prefix("created_at>") {
608            let n = u64::from_str(t)?;
609            if time <= n {
610                return Err(Error::Invalid(format!(
611                    "event created_at must newer than {}",
612                    n
613                )));
614            }
615        }
616    }
617
618    Ok(())
619}
620
621fn verify_sign(sig: &[u8], pk: &[u8], msg: &[u8]) -> Result<(), Error> {
622    let sig = Signature::from_slice(sig)?;
623    let pk = XOnlyPublicKey::from_slice(pk)?;
624    let msg = Message::from_digest_slice(msg)?;
625    Ok(SECP256K1.verify_schnorr(&sig, &msg, &pk)?)
626}
627
628#[cfg(test)]
629mod tests {
630    use super::*;
631    use anyhow::Result;
632    use secp256k1::rand::thread_rng;
633    use serde_json::Value;
634    use std::str::FromStr;
635
636    #[test]
637    fn index_event() -> Result<()> {
638        let note = r#"
639        {
640            "content": "Good morning everyone 😃",
641            "created_at": 1680690006,
642            "id": "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d",
643            "kind": 1,
644            "pubkey": "7abf57d516b1ff7308ca3bd5650ea6a4674d469c7c5057b1d005fb13d218bfef",
645            "sig": "ef4ff4f69ac387239eb1401fb07d7a44a5d5d57127e0dc3466a0403cf7d5486b668608ebfcbe9ff1f8d3b5d710545999fe08ee767284ec0b474e4cf92537678f",
646            "tags": [["t", "nostr"], ["t", ""], ["expiration", "1"], ["delegation", "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd"]]
647          }
648        "#;
649        let event: Event = Event::from_str(note)?;
650        assert_eq!(event.index().tags().len(), 2);
651        let e2 = EventIndex::from_bytes(&event.index().to_bytes()?)?;
652        assert_eq!(&e2, event.index());
653        assert!(&e2.expiration().is_some());
654        assert!(&e2.delegator().is_some());
655
656        let note = r#"
657        {
658            "content": "Good morning everyone 😃",
659            "created_at": 1680690006,
660            "id": "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d",
661            "kind": 1,
662            "pubkey": "7abf57d516b1ff7308ca3bd5650ea6a4674d469c7c5057b1d005fb13d218bfef",
663            "sig": "ef4ff4f69ac387239eb1401fb07d7a44a5d5d57127e0dc3466a0403cf7d5486b668608ebfcbe9ff1f8d3b5d710545999fe08ee767284ec0b474e4cf92537678f",
664            "tags": []
665          }
666        "#;
667        let event: Event = Event::from_str(note)?;
668        assert_eq!(event.index().tags().len(), 0);
669        let e2 = EventIndex::from_bytes(&event.index().to_bytes()?)?;
670        assert_eq!(&e2, event.index());
671        Ok(())
672    }
673
674    #[test]
675    fn string() -> Result<()> {
676        let note = r#"
677        {
678            "content": "Good morning everyone 😃",
679            "created_at": 1680690006,
680            "id": "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d",
681            "kind": 1,
682            "pubkey": "7abf57d516b1ff7308ca3bd5650ea6a4674d469c7c5057b1d005fb13d218bfef",
683            "sig": "ef4ff4f69ac387239eb1401fb07d7a44a5d5d57127e0dc3466a0403cf7d5486b668608ebfcbe9ff1f8d3b5d710545999fe08ee767284ec0b474e4cf92537678f",
684            "tags": [["t", "nostr"]]
685          }
686        "#;
687        let event: Event = Event::from_str(note)?;
688        assert_eq!(
689            hex::encode(event.index().id()),
690            "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d"
691        );
692        assert_eq!(
693            hex::encode(event.index().id()),
694            "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d"
695        );
696        assert_eq!(event.index().id().len(), 32);
697        let json: String = event.try_into()?;
698        let val: Value = serde_json::from_str(&json)?;
699        assert_eq!(
700            val["id"],
701            Value::String(
702                "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d".to_string()
703            )
704        );
705        Ok(())
706    }
707    #[test]
708    fn deserialize() -> Result<()> {
709        let note = r#"
710        {
711            "content": "Good morning everyone 😃",
712            "created_at": 1680690006,
713            "id": "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d",
714            "kind": 1,
715            "pubkey": "7abf57d516b1ff7308ca3bd5650ea6a4674d469c7c5057b1d005fb13d218bfef",
716            "sig": "ef4ff4f69ac387239eb1401fb07d7a44a5d5d57127e0dc3466a0403cf7d5486b668608ebfcbe9ff1f8d3b5d710545999fe08ee767284ec0b474e4cf92537678f",
717            "tags": [["t", "nostr"]]
718          }
719        "#;
720        let event: Event = serde_json::from_str(note)?;
721        assert_eq!(
722            hex::encode(event.index().id()),
723            "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d"
724        );
725        assert_eq!(
726            hex::encode(event.index().id()),
727            "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d"
728        );
729        assert_eq!(event.index().id().len(), 32);
730        assert_eq!(&event.tags, &vec![vec!["t", "nostr"]]);
731        assert_eq!(event.index().tags.len(), 1);
732
733        // null tag
734        let note = r#"
735        {"content":"","created_at":1681838474,"id":"bf2b783de44b814778d02ca9e4e87aacd0bc7a629bad29b5db62a1c151580ed1","kind":1,"pubkey":"d477a41316e6d28c469181690237705024eb313b43ed3e1f059dc2ff49a6dd2f","sig":"96fa5e33aefd4b18f2d5ab5dc199e731fd6c33162ef3eeee945959b98901e80d1b8fb62856f4f0baed166f4aab2d4401aa8ce9e48071dbe220d2b8e9773755de","tags":[["e","fad5161223be749e364f0eac0fc8cf1566659a32c75d9ce388be42c36ac33e44",null,"root"]]}
736        "#;
737        let event = Event::from_str(note);
738        assert!(event.is_err());
739
740        // invalid kind
741        let note = r#"
742        {
743            "content": "Good morning everyone 😃",
744            "created_at": 1680690006,
745            "id": "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d",
746            "kind": 65536,
747            "pubkey": "7abf57d516b1ff7308ca3bd5650ea6a4674d469c7c5057b1d005fb13d218bfef",
748            "sig": "ef4ff4f69ac387239eb1401fb07d7a44a5d5d57127e0dc3466a0403cf7d5486b668608ebfcbe9ff1f8d3b5d710545999fe08ee767284ec0b474e4cf92537678f",
749            "tags": [["t", "nostr"]]
750          }
751        "#;
752        let event = Event::from_str(note);
753        assert!(event.is_err());
754
755        Ok(())
756    }
757
758    #[test]
759    fn default() -> Result<()> {
760        let note = r#"
761        {
762            "created_at": 1680690006,
763            "id": "332747c0fab8a1a92def4b0937e177be6df4382ce6dd7724f86dc4710b7d4d7d",
764            "kind": 1,
765            "pubkey": "7abf57d516b1ff7308ca3bd5650ea6a4674d469c7c5057b1d005fb13d218bfef",
766            "sig": "ef4ff4f69ac387239eb1401fb07d7a44a5d5d57127e0dc3466a0403cf7d5486b668608ebfcbe9ff1f8d3b5d710545999fe08ee767284ec0b474e4cf92537678f"
767          }
768        "#;
769        let event: Event = serde_json::from_str(note)?;
770        assert_eq!(&event.content, "");
771        assert_eq!(&event.tags, &Vec::<Vec<String>>::new());
772        Ok(())
773    }
774
775    #[test]
776    fn verify() -> Result<()> {
777        let note = r#"
778        {"content":"bgQih8o+R83t00qvueD7twglJRvvabI+nDu+bTvRsAs=?iv=92TlqnpEeiUMzDtUxsZeUA==","created_at":1682257003,"id":"dba1951f0959dfea6e3123ad916d191a07b35392c4b541d4b4814e77113de14a","kind":4,"pubkey":"3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24","sig":"15dcc89bca7d037d6a5282c1e63ea40ca4f76d81821ca1260898a324c99516a0cb577617cf18a3febe6303ed32e7a1a08382eecde5a7183195ca8f186a0cb037","tags":[["p","6efb74e66b7ed7fb9fb7b8b8f12e1fbbabe7f45823a33a14ac60cc9241285536"]]}
779        "#;
780        let event: Event = serde_json::from_str(note)?;
781        assert!(event.verify_sign().is_ok());
782        assert!(event.verify_id().is_ok());
783        assert!(!event.index().is_expired(now()));
784        assert!(!event.index().is_ephemeral());
785
786        let note = r#"
787        {"content":"{\"display_name\": \"maglevclient\", \"uptime\": 103180, \"maglev\": \"1a98030114cf\"}","created_at":1682258083,"id":"153a480d7bb9d7564147241b330a8667b19c3f9178b8179e64bf57f200654cb0","kind":0,"pubkey":"fb7324a1b807b48756be8df06bd9ccf11741a9678b120e91e044b5137734dcb2","sig":"08c0ffa072fd49f405df467ccab25152a54073fc0639ea0952e1eabff7962e008c54cb8f4d2d55dc4398703df4a5654d2ae3e93f68a801bcbabcdb8050a918ef","tags":[["t","TESTmaglev"],["expiration","1682258683"]]}
788          "#;
789        let event: Event = serde_json::from_str(note)?;
790        assert!(event.verify_sign().is_ok());
791        assert!(event.verify_id().is_ok());
792        assert!(event.index().is_expired(now()));
793
794        let event = Event::new([0; 32], [0; 32], 10, 1, vec![], "".to_string(), [0; 64])?;
795        assert!(event.verify_time(10, 1, 1).is_ok());
796        assert!(event.verify_time(20, 1, 1).is_err());
797        assert!(event.verify_time(5, 1, 1).is_err());
798
799        let note = r#"
800        {
801            "id": "e93c6095c3db1c31d15ac771f8fc5fb672f6e52cd25505099f62cd055523224f",
802            "pubkey": "477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396",
803            "created_at": 1677426298,
804            "kind": 1,
805            "tags": [
806              [
807                "delegation",
808                "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd",
809                "kind=1&created_at>1674834236&created_at<1677426236",
810                "6f44d7fe4f1c09f3954640fb58bd12bae8bb8ff4120853c4693106c82e920e2b898f1f9ba9bd65449a987c39c0423426ab7b53910c0c6abfb41b30bc16e5f524"
811              ]
812            ],
813            "content": "Hello, world!",
814            "sig": "633db60e2e7082c13a47a6b19d663d45b2a2ebdeaf0b4c35ef83be2738030c54fc7fd56d139652937cdca875ee61b51904a1d0d0588a6acd6168d7be2909d693"
815          }
816        "#;
817        let event: Event = serde_json::from_str(note)?;
818        assert!(event.verify_delegation().is_err());
819        assert!(event
820            .verify_delegation()
821            .unwrap_err()
822            .to_string()
823            .contains("older"));
824
825        Ok(())
826    }
827
828    #[test]
829    fn create() -> Result<()> {
830        let mut rng = thread_rng();
831        let key_pair = Keypair::new_global(&mut rng);
832        let event = Event::create(&key_pair, 0, 1, vec![], "".to_owned())?;
833        assert!(event.verify_sign().is_ok());
834        assert!(event.verify_id().is_ok());
835        Ok(())
836    }
837}