From d9b25c0e116865171e4f6dd6c13a21e370693858 Mon Sep 17 00:00:00 2001 From: Yuki Kishimoto Date: Mon, 23 Sep 2024 15:03:50 -0400 Subject: [PATCH] nostr: add `pow` field to `Filter` * nostr: check `pow` in `Filter::match_event` * lmdb: check `pow` in `DatabaseFilter::match_event` Signed-off-by: Yuki Kishimoto --- crates/nostr-lmdb/src/store/types/filter.rs | 12 ++++++++++++ crates/nostr/src/types/filter.rs | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/crates/nostr-lmdb/src/store/types/filter.rs b/crates/nostr-lmdb/src/store/types/filter.rs index 6a31aea30..ea0236a8a 100644 --- a/crates/nostr-lmdb/src/store/types/filter.rs +++ b/crates/nostr-lmdb/src/store/types/filter.rs @@ -5,6 +5,7 @@ use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::str::FromStr; +use nostr::nips::nip13; use nostr::{Filter, SingleLetterTag, Timestamp}; use nostr_database::flatbuffers::event_fbs::Fixed32Bytes; @@ -18,6 +19,7 @@ pub struct DatabaseFilter { pub search: Option, pub since: Option, pub until: Option, + pub pow: Option, pub generic_tags: BTreeMap>, } @@ -78,6 +80,14 @@ impl DatabaseFilter { } } + #[inline] + fn pow_match(&self, event: &DatabaseEvent) -> bool { + match self.pow { + Some(difficulty) => nip13::get_leading_zero_bits(event.id.0) >= difficulty, + None => true, + } + } + #[inline] pub fn match_event(&self, event: &DatabaseEvent) -> bool { self.ids_match(event) @@ -86,6 +96,7 @@ impl DatabaseFilter { && self.since.map_or(true, |t| event.created_at >= t) && self.until.map_or(true, |t| event.created_at <= t) && self.tag_match(event) + && self.pow_match(event) && self.search_match(event) } } @@ -121,6 +132,7 @@ impl From for DatabaseFilter { }), since: filter.since, until: filter.until, + pow: filter.pow, generic_tags: filter.generic_tags, } } diff --git a/crates/nostr/src/types/filter.rs b/crates/nostr/src/types/filter.rs index 08b47433b..42a0db01a 100644 --- a/crates/nostr/src/types/filter.rs +++ b/crates/nostr/src/types/filter.rs @@ -291,6 +291,12 @@ pub struct Filter { #[serde(skip_serializing_if = "Option::is_none")] #[serde(default)] pub limit: Option, + /// Minimum POW difficulty + /// + /// + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub pow: Option, /// Generic tag queries #[serde( flatten, @@ -768,6 +774,14 @@ impl Filter { } } + #[inline] + fn pow_match(&self, event: &Event) -> bool { + match self.pow { + Some(difficulty) => event.id.check_pow(difficulty), + None => true, + } + } + /// Determine if [Filter] match given [Event]. #[inline] pub fn match_event(&self, event: &Event) -> bool { @@ -777,6 +791,7 @@ impl Filter { && self.since.map_or(true, |t| event.created_at >= t) && self.until.map_or(true, |t| event.created_at <= t) && self.tag_match(event) + && self.pow_match(event) && self.search_match(event) } }