From 0c71e191963bec729c3ca13c212b231af7582f06 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Mon, 23 Feb 2026 13:42:57 +0000 Subject: fix: rewrite deletion integration tests to avoid shared-state side effects The previous tests deleted purgatory announcements (kind 30617) and checked for bare-repo absence via git ls-remote, which would corrupt shared-mode test state by destroying repos other tests depend on. New approach tests deletion of purgatory state events (kind 30618) instead: - e-tag test: promotes a repo, creates a unique commit locally, submits a state event pointing to it (enters purgatory), deletes the state event by event ID, then verifies git push of that commit is rejected. - a-tag coordinate test: promotes a repo, generates a fresh maintainer keypair, sends a replacement announcement adding that maintainer, submits a state event signed by the new maintainer (enters purgatory), deletes by coordinate 30618::, then verifies git push is rejected. Also extends DeletionPolicy to handle kind 30618 state events in purgatory for both e-tag (event ID) and a-tag (coordinate) deletion paths. --- grasp-audit/src/specs/grasp01/purgatory.rs | 329 +++++++++++++++++++---------- src/nostr/policy/deletion.rs | 138 +++++++----- tests/purgatory.rs | 4 +- 3 files changed, 307 insertions(+), 164 deletions(-) diff --git a/grasp-audit/src/specs/grasp01/purgatory.rs b/grasp-audit/src/specs/grasp01/purgatory.rs index 9d97d3b..29eabad 100644 --- a/grasp-audit/src/specs/grasp01/purgatory.rs +++ b/grasp-audit/src/specs/grasp01/purgatory.rs @@ -27,9 +27,11 @@ //! - `test_pr_event_in_purgatory_git_push_accepted` - Git push to refs/nostr/ succeeds //! - `test_pr_event_served_after_git_push` - Event becomes queryable after git data +use crate::fixtures::{clone_repo, create_commit, try_push}; use crate::specs::grasp01::SpecRef; use crate::{AuditClient, AuditResult, FixtureKind, TestContext, TestResult}; use nostr_sdk::prelude::*; +use std::fs; use std::time::Duration; /// Test suite for GRASP-01 purgatory behavior @@ -47,9 +49,9 @@ impl PurgatoryTests { results.add(Self::test_state_event_accepted_for_purgatory_announcement(client).await); // Deletion event tests (NIP-09) - results.add(Self::test_deletion_by_event_id_removes_purgatory_announcement(client).await); + results.add(Self::test_deletion_by_event_id_removes_purgatory_state_event(client).await); results.add( - Self::test_deletion_by_coordinate_removes_purgatory_announcement(client).await, + Self::test_deletion_by_coordinate_removes_purgatory_state_event(client).await, ); // State event purgatory tests (already implemented) @@ -656,192 +658,293 @@ impl PurgatoryTests { // Deletion Event Tests (NIP-09) // ============================================================ - /// Test: Kind 5 deletion event by event ID removes purgatory announcement + /// Test: Kind 5 deletion event by event ID removes a purgatory state event /// /// Spec: NIP-09 /// "A special event with kind 5... having a list of one or more `e` or `a` tags, /// each referencing an event the author is requesting to be deleted." /// /// This test verifies: - /// 1. Send a valid repository announcement (enters purgatory) - /// 2. Send a kind 5 deletion event referencing the announcement by event ID - /// 3. The announcement is no longer in purgatory (git push would fail) - /// 4. The deletion event itself is accepted by the relay - pub async fn test_deletion_by_event_id_removes_purgatory_announcement( + /// 1. Get a promoted repo (OwnerStateDataPushed) so git pushes are possible + /// 2. Clone the repo and create a unique commit (not yet pushed) + /// 3. Submit a state event pointing to that unique commit (enters purgatory) + /// 4. Send a kind 5 deletion event referencing the state event by event ID + /// 5. Attempt to push the unique commit — MUST be rejected (no authorized state event) + pub async fn test_deletion_by_event_id_removes_purgatory_state_event( client: &AuditClient, ) -> TestResult { TestResult::new( - "deletion_by_event_id_removes_purgatory_announcement", + "deletion_by_event_id_removes_purgatory_state_event", SpecRef::PurgatoryAcceptUntilGitData, - "Kind 5 deletion by event ID SHOULD remove a purgatory announcement", + "Kind 5 deletion by event ID SHOULD remove a purgatory state event, causing push rejection", ) .run(|| async { let ctx = TestContext::new(client); - // Send announcement to purgatory - let repo = ctx - .get_fixture(FixtureKind::ValidRepoSent) + // Stage 1: get a promoted repo with git data already on the relay + let existing_state = ctx + .get_fixture(FixtureKind::OwnerStateDataPushed) .await - .map_err(|e| format!("Failed to create repo announcement: {}", e))?; + .map_err(|e| format!("Failed to get promoted repo: {}", e))?; - let repo_id = repo + let repo_id = existing_state .tags .iter() .find(|t| t.kind() == TagKind::d()) .and_then(|t| t.content()) - .ok_or("Missing d tag in repo announcement")? + .ok_or("Missing d tag in state event")? .to_string(); - // Verify it's in purgatory (not served) - tokio::time::sleep(Duration::from_millis(300)).await; - if client.is_event_on_relay(repo.id).await.map_err(|e| e.to_string())? { - return Err( - "Announcement was served immediately - purgatory not working".to_string(), - ); + let relay_domain = client + .relay_url() + .await + .map_err(|e| e.to_string())? + .trim_start_matches("ws://") + .trim_start_matches("wss://") + .to_string(); + + let npub = client + .public_key() + .to_bech32() + .map_err(|e| e.to_string())?; + + // Stage 2: clone the repo and create a unique commit (not pushed yet) + let clone_path = clone_repo(&relay_domain, &npub, &repo_id) + .map_err(|e| format!("Failed to clone repo: {}", e))?; + + let cleanup = || { let _ = fs::remove_dir_all(&clone_path); }; + + let unique_commit = match create_commit(&clone_path, "deletion test unique commit") { + Ok(h) => h, + Err(e) => { cleanup(); return Err(format!("Failed to create commit: {}", e)); } + }; + + // Stage 3: submit a state event pointing to the unique commit (enters purgatory) + let state_event = client + .event_builder(Kind::RepoState, "") + .tag(Tag::identifier(&repo_id)) + .tag(Tag::custom( + TagKind::custom("refs/heads/main"), + vec![unique_commit.clone()], + )) + .tag(Tag::custom( + TagKind::custom("HEAD"), + vec!["ref: refs/heads/main".to_string()], + )) + .build(client.keys()) + .map_err(|e| { cleanup(); format!("Failed to build state event: {}", e) })?; + + let (_, in_purgatory) = client + .send_event_and_note_purgatory(state_event.clone()) + .await + .map_err(|e| { cleanup(); format!("Failed to send state event: {}", e) })?; + + if !in_purgatory { + cleanup(); + return Err(format!( + "State event was served immediately (not in purgatory). \ + Commit {} may already exist on relay.", + unique_commit + )); } - // Build and send kind 5 deletion event referencing the announcement by event ID + // Stage 4: send kind 5 deletion event referencing the state event by event ID let deletion = client .event_builder(Kind::EventDeletion, "") - .tag(Tag::event(repo.id)) - .tag(Tag::custom( - TagKind::custom("k"), - vec!["30617"], - )) + .tag(Tag::event(state_event.id)) + .tag(Tag::custom(TagKind::custom("k"), vec!["30618"])) .build(client.keys()) - .map_err(|e| format!("Failed to build deletion event: {}", e))?; + .map_err(|e| { cleanup(); format!("Failed to build deletion event: {}", e) })?; client .send_event(deletion) .await - .map_err(|e| format!("Relay rejected deletion event: {}", e))?; + .map_err(|e| { cleanup(); format!("Relay rejected deletion event: {}", e) })?; tokio::time::sleep(Duration::from_millis(300)).await; - // Verify the announcement can no longer be promoted by attempting a git push. - // We check this indirectly: if the purgatory entry was removed, a subsequent - // git push to the repo path should fail (no bare repo). - // For the integration test we verify the announcement is still not served - // (it was never promoted) and that the deletion event was accepted. - // The bare-repo deletion is verified by attempting a git clone. - let http_url = AuditClient::ws_to_http_url(&client.relay_url().await.map_err(|e| e.to_string())?) - .map_err(|e| e.to_string())?; - let clone_url = format!( - "{}/{}/{}.git", - http_url, - client.public_key().to_bech32().map_err(|e| e.to_string())?, - repo_id - ); - - // git ls-remote should fail (bare repo deleted) - let output = std::process::Command::new("git") - .args(["ls-remote", &clone_url]) - .output() - .map_err(|e| format!("Failed to run git ls-remote: {}", e))?; - - if output.status.success() { - return Err(format!( - "Bare repo still exists after deletion event. \ - Expected git ls-remote to fail for {}", - clone_url - )); + // Stage 5: attempt to push the unique commit — must be rejected + let push_result = try_push(&clone_path); + cleanup(); + + match push_result { + Ok(false) => Ok(()), // push rejected as expected + Ok(true) => Err(format!( + "Push was accepted but should have been rejected. \ + The state event (id={}) was deleted, so commit {} \ + should not be authorized.", + state_event.id, unique_commit + )), + Err(e) => Err(format!("Git push error: {}", e)), } - - Ok(()) }) .await } - /// Test: Kind 5 deletion event by `a` tag coordinate removes purgatory announcement + /// Test: Kind 5 deletion event by `a` tag coordinate removes a purgatory state event /// /// Spec: NIP-09 /// "When an `a` tag is used, relays SHOULD delete all versions of the replaceable /// event up to the `created_at` timestamp of the deletion request event." /// /// This test verifies: - /// 1. Send a valid repository announcement (enters purgatory) - /// 2. Send a kind 5 deletion event referencing the announcement by coordinate - /// (`30617::`) - /// 3. The announcement is no longer in purgatory - pub async fn test_deletion_by_coordinate_removes_purgatory_announcement( + /// 1. Get a promoted repo (OwnerStateDataPushed) so git pushes are possible + /// 2. Generate a fresh keypair for a new maintainer + /// 3. Send a replacement owner announcement adding the new maintainer (goes to DB) + /// 4. Send a state event signed by the new maintainer pointing to a unique commit + /// (enters purgatory — maintainer is authorized but commit doesn't exist yet) + /// 5. Delete by coordinate `30618::` + /// 6. Clone repo, create that unique commit, attempt to push — MUST be rejected + /// (the state event was deleted, so the commit is no longer authorized) + pub async fn test_deletion_by_coordinate_removes_purgatory_state_event( client: &AuditClient, ) -> TestResult { TestResult::new( - "deletion_by_coordinate_removes_purgatory_announcement", + "deletion_by_coordinate_removes_purgatory_state_event", SpecRef::PurgatoryAcceptUntilGitData, - "Kind 5 deletion by `a` coordinate SHOULD remove a purgatory announcement", + "Kind 5 deletion by `a` coordinate SHOULD remove a purgatory state event, causing push rejection", ) .run(|| async { let ctx = TestContext::new(client); - // Send announcement to purgatory - let repo = ctx - .get_fixture(FixtureKind::ValidRepoSent) + // Stage 1: get a promoted repo with git data already on the relay + let existing_state = ctx + .get_fixture(FixtureKind::OwnerStateDataPushed) .await - .map_err(|e| format!("Failed to create repo announcement: {}", e))?; + .map_err(|e| format!("Failed to get promoted repo: {}", e))?; - let repo_id = repo + let repo_id = existing_state .tags .iter() .find(|t| t.kind() == TagKind::d()) .and_then(|t| t.content()) - .ok_or("Missing d tag in repo announcement")? + .ok_or("Missing d tag in state event")? .to_string(); - // Verify it's in purgatory (not served) - tokio::time::sleep(Duration::from_millis(300)).await; - if client.is_event_on_relay(repo.id).await.map_err(|e| e.to_string())? { - return Err( - "Announcement was served immediately - purgatory not working".to_string(), - ); - } + // Stage 2: generate a fresh keypair for a new maintainer + let new_maintainer_keys = Keys::generate(); + let new_maintainer_hex = new_maintainer_keys.public_key().to_hex(); - // Build coordinate: `30617::` - let coord = format!( - "30617:{}:{}", - client.public_key().to_hex(), - repo_id - ); + // Stage 3: send a replacement owner announcement that adds the new maintainer. + // This is a replacement (same pubkey + identifier already in DB) so it goes + // straight to the database without entering purgatory. + let relay_url = client + .relay_url() + .await + .map_err(|e| e.to_string())?; + let http_url = relay_url + .replace("ws://", "http://") + .replace("wss://", "https://"); + let npub = client + .public_key() + .to_bech32() + .map_err(|e| e.to_string())?; - // Build and send kind 5 deletion event referencing by coordinate - let deletion = client - .event_builder(Kind::EventDeletion, "") - .tag(Tag::custom(TagKind::custom("a"), vec![coord])) - .tag(Tag::custom(TagKind::custom("k"), vec!["30617"])) + let replacement_announcement = client + .event_builder(Kind::GitRepoAnnouncement, "") + .tag(Tag::identifier(&repo_id)) + .tag(Tag::custom( + TagKind::custom("clone"), + vec![format!("{}/{}/{}.git", http_url, npub, repo_id)], + )) + .tag(Tag::custom( + TagKind::custom("relays"), + vec![relay_url.clone()], + )) + .tag(Tag::custom( + TagKind::custom("maintainers"), + vec![new_maintainer_hex.clone()], + )) .build(client.keys()) - .map_err(|e| format!("Failed to build deletion event: {}", e))?; + .map_err(|e| format!("Failed to build replacement announcement: {}", e))?; client - .send_event(deletion) + .send_event(replacement_announcement) .await - .map_err(|e| format!("Relay rejected deletion event: {}", e))?; + .map_err(|e| format!("Relay rejected replacement announcement: {}", e))?; - tokio::time::sleep(Duration::from_millis(300)).await; + tokio::time::sleep(Duration::from_millis(200)).await; - // Verify bare repo was deleted - let http_url = AuditClient::ws_to_http_url(&client.relay_url().await.map_err(|e| e.to_string())?) - .map_err(|e| e.to_string())?; - let clone_url = format!( - "{}/{}/{}.git", - http_url, - client.public_key().to_bech32().map_err(|e| e.to_string())?, - repo_id - ); + // Stage 4: clone the repo and create a unique commit (not pushed yet) + let relay_domain = relay_url + .trim_start_matches("ws://") + .trim_start_matches("wss://") + .to_string(); + + let clone_path = clone_repo(&relay_domain, &npub, &repo_id) + .map_err(|e| format!("Failed to clone repo: {}", e))?; + + let cleanup = || { let _ = fs::remove_dir_all(&clone_path); }; - let output = std::process::Command::new("git") - .args(["ls-remote", &clone_url]) - .output() - .map_err(|e| format!("Failed to run git ls-remote: {}", e))?; + let unique_commit = match create_commit(&clone_path, "deletion coordinate test unique commit") { + Ok(h) => h, + Err(e) => { cleanup(); return Err(format!("Failed to create commit: {}", e)); } + }; - if output.status.success() { + // Stage 5: submit a state event signed by the new maintainer pointing to the + // unique commit. The new maintainer is now authorized (listed in the replacement + // announcement), so the state event should enter purgatory (commit doesn't exist). + let state_event = client + .event_builder(Kind::RepoState, "") + .tag(Tag::identifier(&repo_id)) + .tag(Tag::custom( + TagKind::custom("refs/heads/main"), + vec![unique_commit.clone()], + )) + .tag(Tag::custom( + TagKind::custom("HEAD"), + vec!["ref: refs/heads/main".to_string()], + )) + .build(&new_maintainer_keys) + .map_err(|e| { cleanup(); format!("Failed to build state event: {}", e) })?; + + let (_, in_purgatory) = client + .send_event_and_note_purgatory(state_event.clone()) + .await + .map_err(|e| { cleanup(); format!("Failed to send state event: {}", e) })?; + + if !in_purgatory { + cleanup(); return Err(format!( - "Bare repo still exists after deletion event. \ - Expected git ls-remote to fail for {}", - clone_url + "State event was served immediately (not in purgatory). \ + Commit {} may already exist on relay.", + unique_commit )); } - Ok(()) + // Stage 6: send kind 5 deletion event signed by the new maintainer, + // referencing their state event by coordinate `30618::` + let coord = format!("30618:{}:{}", new_maintainer_hex, repo_id); + + let deletion = client + .event_builder(Kind::EventDeletion, "") + .tag(Tag::custom(TagKind::custom("a"), vec![coord])) + .tag(Tag::custom(TagKind::custom("k"), vec!["30618"])) + .build(&new_maintainer_keys) + .map_err(|e| { cleanup(); format!("Failed to build deletion event: {}", e) })?; + + client + .send_event(deletion) + .await + .map_err(|e| { cleanup(); format!("Relay rejected deletion event: {}", e) })?; + + tokio::time::sleep(Duration::from_millis(300)).await; + + // Stage 7: attempt to push the unique commit — must be rejected because + // the new maintainer's state event was deleted from purgatory + let push_result = try_push(&clone_path); + cleanup(); + + match push_result { + Ok(false) => Ok(()), // push rejected as expected + Ok(true) => Err(format!( + "Push was accepted but should have been rejected. \ + The new maintainer's state event (id={}) was deleted by coordinate, \ + so commit {} should not be authorized.", + state_event.id, unique_commit + )), + Err(e) => Err(format!("Git push error: {}", e)), + } }) .await } diff --git a/src/nostr/policy/deletion.rs b/src/nostr/policy/deletion.rs index 69a5758..01241c9 100644 --- a/src/nostr/policy/deletion.rs +++ b/src/nostr/policy/deletion.rs @@ -1,7 +1,7 @@ /// Deletion Policy - NIP-09 event deletion request handling /// -/// Handles kind 5 (EventDeletion) events that request removal of repository -/// announcements (kind 30617) from purgatory. +/// Handles kind 5 (EventDeletion) events that request removal of purgatory entries +/// for repository announcements (kind 30617) and state events (kind 30618). /// /// ## NIP-09 Rules Enforced /// @@ -13,9 +13,9 @@ /// /// ## Purgatory Interaction /// -/// When a valid deletion request targets a kind 30617 announcement that is currently -/// in purgatory (not yet promoted to the database), the purgatory entry is removed -/// and the bare repository is deleted from disk. +/// - Kind 30617 (announcement) in purgatory: entry removed, bare repo deleted from disk +/// - Kind 30618 (state event) in purgatory: matching state event(s) removed by event ID +/// or by (author, identifier) coordinate use nostr_relay_builder::prelude::{Event, WritePolicyResult}; use super::PolicyContext; @@ -48,13 +48,13 @@ impl DeletionPolicy { WritePolicyResult::Accept } - /// Remove any purgatory announcements targeted by this deletion event. + /// Remove any purgatory entries targeted by this deletion event. /// /// Handles both reference styles from NIP-09: - /// - `e` tags: event ID references — match against purgatory entry event IDs - /// - `a` tags: addressable coordinate references — `30617::` + /// - `e` tags: event ID references — match against announcement or state event IDs + /// - `a` tags: addressable coordinate references — `30617:…` or `30618:…` /// - /// Only removes entries where the purgatory entry's owner matches the deletion + /// Only removes entries where the purgatory entry's author matches the deletion /// event's pubkey (enforces author-only deletion). fn remove_purgatory_targets(&self, event: &Event) { let author = &event.pubkey; @@ -81,17 +81,19 @@ impl DeletionPolicy { } } - /// Remove a purgatory announcement matched by event ID. + /// Remove a purgatory entry (announcement or state event) matched by event ID. /// - /// Scans all purgatory announcements owned by `author` and removes the one - /// whose event ID hex matches `target_id_hex`. - fn remove_by_event_id(&self, author: &nostr_relay_builder::prelude::PublicKey, target_id_hex: &str, _deletion_created_at: u64) { - // Scan announcements owned by this author for a matching event ID - // We use get_announcements_by_identifier would require knowing the identifier, - // so instead we iterate via find_announcement after collecting all entries. + /// Checks announcements first (kind 30617), then state events (kind 30618). + /// Only removes entries whose author matches `author`. + fn remove_by_event_id( + &self, + author: &nostr_relay_builder::prelude::PublicKey, + target_id_hex: &str, + _deletion_created_at: u64, + ) { + // --- Check announcements (kind 30617) --- // The DashMap doesn't expose a direct "find by event ID" method, so we use - // the announcements_for_sync snapshot to get all (repo_id, _) pairs and then - // look up each one. + // the announcements_for_sync snapshot to enumerate all (repo_id, _) pairs. let all = self.ctx.purgatory.announcements_for_sync(); for (repo_id, _) in all { // repo_id format: "30617:{pubkey_hex}:{identifier}" @@ -102,7 +104,6 @@ impl DeletionPolicy { let entry_pubkey_hex = parts[1]; let identifier = parts[2]; - // Only check entries owned by the deletion event author if entry_pubkey_hex != author.to_hex() { continue; } @@ -116,18 +117,37 @@ impl DeletionPolicy { "Deletion request: removing purgatory announcement by event ID" ); self.evict_purgatory_entry(author, identifier); - return; // event IDs are unique, no need to continue + return; // event IDs are unique + } + } + } + + // --- Check state events (kind 30618) --- + // State events are keyed by identifier; scan all identifiers for a match. + let state_identifiers = self.ctx.purgatory.get_all_identifiers(); + for identifier in state_identifiers { + let entries = self.ctx.purgatory.find_state(&identifier); + for entry in entries { + if entry.author == *author && entry.event.id.to_hex() == target_id_hex { + tracing::info!( + event_id = %target_id_hex, + identifier = %identifier, + author = %author.to_hex(), + "Deletion request: removing purgatory state event by event ID" + ); + self.ctx.purgatory.remove_state_event(&identifier, &entry.event.id); + return; // event IDs are unique } } } } - /// Remove a purgatory announcement matched by addressable coordinate. + /// Remove a purgatory entry matched by addressable coordinate. + /// + /// The coordinate format is `::`. + /// Handles kind 30617 (announcements) and kind 30618 (state events). /// - /// The coordinate format is `::`. Only kind 30617 - /// coordinates are relevant here. Per NIP-09, all versions up to `deletion_created_at` - /// are considered deleted — since purgatory entries are always a single event per - /// (owner, identifier), we delete if the entry's `created_at` ≤ `deletion_created_at`. + /// Per NIP-09, all versions up to `deletion_created_at` are considered deleted. fn remove_by_coordinate( &self, author: &nostr_relay_builder::prelude::PublicKey, @@ -144,11 +164,6 @@ impl DeletionPolicy { let coord_pubkey_hex = parts[1]; let identifier = parts[2]; - // Only handle kind 30617 (GitRepoAnnouncement) - if kind_str != "30617" { - return; - } - // The coordinate pubkey must match the deletion event author if coord_pubkey_hex != author.to_hex() { tracing::debug!( @@ -159,25 +174,50 @@ impl DeletionPolicy { return; } - if let Some(entry) = self.ctx.purgatory.find_announcement(author, identifier) { - // Per NIP-09: delete all versions up to deletion_created_at - if entry.event.created_at.as_secs() <= deletion_created_at { - tracing::info!( - identifier = %identifier, - author = %author.to_hex(), - entry_created_at = entry.event.created_at.as_secs(), - deletion_created_at = %deletion_created_at, - "Deletion request: removing purgatory announcement by coordinate" - ); - self.evict_purgatory_entry(author, identifier); - } else { - tracing::debug!( - identifier = %identifier, - author = %author.to_hex(), - entry_created_at = entry.event.created_at.as_secs(), - deletion_created_at = %deletion_created_at, - "Ignoring deletion: purgatory entry is newer than deletion request" - ); + match kind_str { + "30617" => { + // Announcement purgatory entry + if let Some(entry) = self.ctx.purgatory.find_announcement(author, identifier) { + if entry.event.created_at.as_secs() <= deletion_created_at { + tracing::info!( + identifier = %identifier, + author = %author.to_hex(), + "Deletion request: removing purgatory announcement by coordinate" + ); + self.evict_purgatory_entry(author, identifier); + } else { + tracing::debug!( + identifier = %identifier, + author = %author.to_hex(), + "Ignoring deletion: purgatory announcement is newer than deletion request" + ); + } + } + } + "30618" => { + // State event purgatory entries for this (author, identifier). + // Remove all entries authored by `author` with created_at ≤ deletion_created_at. + let entries = self.ctx.purgatory.find_state(identifier); + let mut removed = 0usize; + for entry in entries { + if entry.author == *author + && entry.event.created_at.as_secs() <= deletion_created_at + { + self.ctx.purgatory.remove_state_event(identifier, &entry.event.id); + removed += 1; + } + } + if removed > 0 { + tracing::info!( + identifier = %identifier, + author = %author.to_hex(), + removed = %removed, + "Deletion request: removed purgatory state event(s) by coordinate" + ); + } + } + _ => { + // Other kinds not handled } } } diff --git a/tests/purgatory.rs b/tests/purgatory.rs index 553271f..73f85ca 100644 --- a/tests/purgatory.rs +++ b/tests/purgatory.rs @@ -70,8 +70,8 @@ isolated_purgatory_test!(test_state_event_accepted_for_purgatory_announcement); // Deletion Event Tests (NIP-09) // ============================================================ -isolated_purgatory_test!(test_deletion_by_event_id_removes_purgatory_announcement); -isolated_purgatory_test!(test_deletion_by_coordinate_removes_purgatory_announcement); +isolated_purgatory_test!(test_deletion_by_event_id_removes_purgatory_state_event); +isolated_purgatory_test!(test_deletion_by_coordinate_removes_purgatory_state_event); // ============================================================ // State Event Purgatory Tests (already implemented) -- cgit v1.2.3