Skip to content

Commit

Permalink
database: not save invalid event deletion
Browse files Browse the repository at this point in the history
Signed-off-by: Yuki Kishimoto <[email protected]>
  • Loading branch information
yukibtc committed Oct 1, 2024
1 parent 38f960a commit 3cf1a38
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 41 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
88 changes: 48 additions & 40 deletions crates/nostr-database/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,45 +281,54 @@ 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);
}
}
}

// 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));
}
}
}
Expand All @@ -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());

Expand Down Expand Up @@ -611,8 +618,8 @@ impl InternalDatabaseHelper {
I: IntoIterator<Item = Filter>,
{
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())),
}
}

Expand Down Expand Up @@ -767,12 +774,13 @@ impl DatabaseHelper {

/// Query
#[tracing::instrument(skip_all, level = "trace")]
pub async fn query<I>(&self, filters: I) -> Vec<Event>
pub async fn query<I>(&self, filters: I) -> Events
where
I: IntoIterator<Item = Filter>,
{
let inner = self.inner.read().await;
inner.query(filters).cloned().collect()
let set: BTreeSet<Event> = inner.query(filters).cloned().collect();
Events::from(set)
}

/// Query
Expand Down Expand Up @@ -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(),
Expand All @@ -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
Expand Down

0 comments on commit 3cf1a38

Please sign in to comment.