diff --git a/CHANGELOG.md b/CHANGELOG.md index 6be7854dd..d4ee3bf73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,8 @@ * pool: deprecate `RelayPool::remove_all_relays` ([Yuki Kishimoto]) * sdk: deprecate `Client::get_events_of` and `Client::get_events_from` methods ([Yuki Kishimoto]) * database: improve `BTreeCappedSet` ([Yuki Kishimoto]) -* lmdb: not save event deletion if contains not owned events ([Yuki Kishimoto]) +* database: not save invalid event deletion ([Yuki Kishimoto]) +* lmdb: not save event deletion ([Yuki Kishimoto]) * lmdb: return iterator instead of vector in `Lmdb::single_filter_query` ([Yuki Kishimoto]) * signer: bootstrap NIP-46 signer on demand ([Yuki Kishimoto]) * bindings(nostr): adj. `tag` module ([Yuki Kishimoto]) diff --git a/crates/nostr-database/src/helper.rs b/crates/nostr-database/src/helper.rs index c2e48467b..f0184ff2f 100644 --- a/crates/nostr-database/src/helper.rs +++ b/crates/nostr-database/src/helper.rs @@ -281,7 +281,13 @@ impl InternalDatabaseHelper { // Check `e` tags for id in event.tags.event_ids() { if let Some(ev) = self.ids.get(id) { - if ev.pubkey == author && ev.created_at <= created_at { + if ev.pubkey != author { + to_discard.insert(event.id); + should_insert = false; + break; + } + + if ev.created_at <= created_at { to_discard.insert(ev.id); } } @@ -289,37 +295,40 @@ impl InternalDatabaseHelper { // Check `a` tags for coordinate in event.tags.coordinates() { - if coordinate.public_key == author { - // Save deleted coordinate at certain timestamp - self.deleted_coordinates - .entry(coordinate.clone()) - .and_modify(|t| { - // Update only if newer - if created_at > *t { - *t = created_at - } - }) - .or_insert(created_at); - - // Not check if ev.pubkey match the author because assume that query - // returned only the events owned by author - if !coordinate.identifier.is_empty() { - let mut params: QueryByParamReplaceable = QueryByParamReplaceable::new( - coordinate.kind, - coordinate.public_key, - coordinate.identifier.clone(), - ); - params.until = Some(created_at); - if let Some(ev) = self.internal_query_param_replaceable(params) { - to_discard.insert(ev.id); + if coordinate.public_key != author { + to_discard.insert(event.id); + should_insert = false; + break; + } + + // Save deleted coordinate at certain timestamp + self.deleted_coordinates + .entry(coordinate.clone()) + .and_modify(|t| { + // Update only if newer + if created_at > *t { + *t = created_at } - } else { - let mut params: QueryByKindAndAuthorParams = - QueryByKindAndAuthorParams::new(coordinate.kind, coordinate.public_key); - params.until = Some(created_at); - to_discard - .extend(self.internal_query_by_kind_and_author(params).map(|e| e.id)); + }) + .or_insert(created_at); + + // Not check if ev.pubkey match the author because assume that query + // returned only the events owned by author + if !coordinate.identifier.is_empty() { + let mut params: QueryByParamReplaceable = QueryByParamReplaceable::new( + coordinate.kind, + coordinate.public_key, + coordinate.identifier.clone(), + ); + params.until = Some(created_at); + if let Some(ev) = self.internal_query_param_replaceable(params) { + to_discard.insert(ev.id); } + } else { + let mut params: QueryByKindAndAuthorParams = + QueryByKindAndAuthorParams::new(coordinate.kind, coordinate.public_key); + params.until = Some(created_at); + to_discard.extend(self.internal_query_by_kind_and_author(params).map(|e| e.id)); } } } @@ -329,9 +338,7 @@ impl InternalDatabaseHelper { // Insert event if should_insert { - let e: DatabaseEvent = DatabaseEvent { - event: Arc::new(event.clone()), - }; // TODO: avoid clone? + let e: DatabaseEvent = Arc::new(event.clone()); // TODO: avoid clone? let InsertResult { inserted, pop } = self.events.insert(e.clone()); @@ -611,8 +618,8 @@ impl InternalDatabaseHelper { I: IntoIterator, { match self.internal_query(filters) { - InternalQueryResult::All => Box::new(self.events.iter().map(|ev| ev.deref())), - InternalQueryResult::Set(set) => Box::new(set.into_iter().map(|ev| ev.deref())), + InternalQueryResult::All => Box::new(self.events.iter().map(|ev| ev.as_ref())), + InternalQueryResult::Set(set) => Box::new(set.into_iter().map(|ev| ev.as_ref())), } } @@ -767,12 +774,13 @@ impl DatabaseHelper { /// Query #[tracing::instrument(skip_all, level = "trace")] - pub async fn query(&self, filters: I) -> Vec + pub async fn query(&self, filters: I) -> Events where I: IntoIterator, { let inner = self.inner.read().await; - inner.query(filters).cloned().collect() + let set: BTreeSet = inner.query(filters).cloned().collect(); + Events::from(set) } /// Query @@ -885,11 +893,11 @@ mod tests { let expected_output = vec![ Event::from_json(EVENTS[13]).unwrap(), Event::from_json(EVENTS[12]).unwrap(), - Event::from_json(EVENTS[11]).unwrap(), + // Event 11 is invalid deletion // Event 10 deleted by event 12 // Event 9 replaced by event 10 Event::from_json(EVENTS[8]).unwrap(), - Event::from_json(EVENTS[7]).unwrap(), + // Event 7 is invalid deletion Event::from_json(EVENTS[6]).unwrap(), Event::from_json(EVENTS[5]).unwrap(), Event::from_json(EVENTS[4]).unwrap(), @@ -899,7 +907,7 @@ mod tests { Event::from_json(EVENTS[0]).unwrap(), ]; assert_eq!(indexes.query([Filter::new()]).await, expected_output); - assert_eq!(indexes.count([Filter::new()]).await, 10); + assert_eq!(indexes.count([Filter::new()]).await, 8); // Test get previously deleted replaceable event (check if was deleted by indexes) assert!(indexes