From 89b8948195f24df127b7ae656ab3f60bd1b49ac7 Mon Sep 17 00:00:00 2001 From: bndw Date: Fri, 13 Feb 2026 20:36:12 -0800 Subject: refactor: simplify deletion handling (remove NIP-09 processing) Remove deletion processing logic in favor of simpler approach: - Remove deletions table from schema - Delete deletions.go and deletions_test.go - Remove ProcessDeletion from EventStore interface - Kind 5 events now stored like any other event (no special handling) - Update storage test to expect 2 tables instead of 3 - All 41 tests passing --- internal/storage/deletions.go | 70 -------------- internal/storage/deletions_test.go | 184 ------------------------------------- internal/storage/storage.go | 12 --- internal/storage/storage_test.go | 6 +- 4 files changed, 3 insertions(+), 269 deletions(-) delete mode 100644 internal/storage/deletions.go delete mode 100644 internal/storage/deletions_test.go (limited to 'internal/storage') diff --git a/internal/storage/deletions.go b/internal/storage/deletions.go deleted file mode 100644 index 1a07e3c..0000000 --- a/internal/storage/deletions.go +++ /dev/null @@ -1,70 +0,0 @@ -package storage - -import ( - "context" - "fmt" - - pb "northwest.io/nostr-grpc/api/nostr/v1" -) - -const KindDeletion = 5 - -func (s *Storage) ProcessDeletion(ctx context.Context, deletionEvent *pb.Event) error { - if deletionEvent.Kind != KindDeletion { - return fmt.Errorf("not a deletion event") - } - - var eventIDsToDelete []string - for _, tag := range deletionEvent.Tags { - if len(tag.Values) >= 2 && tag.Values[0] == "e" { - eventIDsToDelete = append(eventIDsToDelete, tag.Values[1]) - } - } - - if len(eventIDsToDelete) == 0 { - return nil - } - - tx, err := s.db.BeginTx(ctx, nil) - if err != nil { - return fmt.Errorf("failed to begin transaction: %w", err) - } - defer tx.Rollback() - - for _, eventID := range eventIDsToDelete { - var eventPubkey string - err := tx.QueryRowContext(ctx, - "SELECT pubkey FROM events WHERE id = ? AND deleted = 0", - eventID, - ).Scan(&eventPubkey) - - if err != nil { - continue - } - - if eventPubkey != deletionEvent.Pubkey { - continue - } - - _, err = tx.ExecContext(ctx, - "UPDATE events SET deleted = 1 WHERE id = ?", - eventID, - ) - if err != nil { - return fmt.Errorf("failed to mark event as deleted: %w", err) - } - - _, err = tx.ExecContext(ctx, - "INSERT OR IGNORE INTO deletions (deleted_event_id, deletion_event_id, pubkey, created_at) VALUES (?, ?, ?, ?)", - eventID, - deletionEvent.Id, - deletionEvent.Pubkey, - deletionEvent.CreatedAt, - ) - if err != nil { - return fmt.Errorf("failed to record deletion: %w", err) - } - } - - return tx.Commit() -} diff --git a/internal/storage/deletions_test.go b/internal/storage/deletions_test.go deleted file mode 100644 index 47e6547..0000000 --- a/internal/storage/deletions_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package storage - -import ( - "context" - "fmt" - "testing" - "time" - - pb "northwest.io/nostr-grpc/api/nostr/v1" -) - -func TestProcessDeletion(t *testing.T) { - store, err := New(":memory:") - if err != nil { - t.Fatalf("failed to create storage: %v", err) - } - defer store.Close() - - ctx := context.Background() - - event := &pb.Event{ - Id: "event123", - Pubkey: "alice", - CreatedAt: time.Now().Unix(), - Kind: 1, - Tags: []*pb.Tag{}, - Content: "to be deleted", - Sig: "sig1", - } - - err = store.StoreEvent(ctx, &EventData{ - Event: event, - CanonicalJSON: []byte(`[0,"alice",1234567890,1,[],"to be deleted"]`), - }) - if err != nil { - t.Fatalf("failed to store event: %v", err) - } - - retrieved, err := store.GetEvent(ctx, "event123") - if err != nil { - t.Fatalf("event should exist before deletion: %v", err) - } - if retrieved.Id != "event123" { - t.Errorf("expected event123, got %s", retrieved.Id) - } - - deletionEvent := &pb.Event{ - Id: "deletion123", - Pubkey: "alice", - CreatedAt: time.Now().Unix(), - Kind: KindDeletion, - Tags: []*pb.Tag{ - {Values: []string{"e", "event123"}}, - }, - Content: "deleting my event", - Sig: "sig2", - } - - err = store.ProcessDeletion(ctx, deletionEvent) - if err != nil { - t.Fatalf("failed to process deletion: %v", err) - } - - _, err = store.GetEvent(ctx, "event123") - if err != ErrEventNotFound { - t.Errorf("event should be deleted, got error: %v", err) - } -} - -func TestProcessDeletionWrongAuthor(t *testing.T) { - store, err := New(":memory:") - if err != nil { - t.Fatalf("failed to create storage: %v", err) - } - defer store.Close() - - ctx := context.Background() - - event := &pb.Event{ - Id: "event456", - Pubkey: "alice", - CreatedAt: time.Now().Unix(), - Kind: 1, - Tags: []*pb.Tag{}, - Content: "alice's event", - Sig: "sig1", - } - - err = store.StoreEvent(ctx, &EventData{ - Event: event, - CanonicalJSON: []byte(`[0,"alice",1234567890,1,[],"alice's event"]`), - }) - if err != nil { - t.Fatalf("failed to store event: %v", err) - } - - deletionEvent := &pb.Event{ - Id: "deletion456", - Pubkey: "bob", - CreatedAt: time.Now().Unix(), - Kind: KindDeletion, - Tags: []*pb.Tag{ - {Values: []string{"e", "event456"}}, - }, - Content: "trying to delete alice's event", - Sig: "sig2", - } - - err = store.ProcessDeletion(ctx, deletionEvent) - if err != nil { - t.Fatalf("process deletion should succeed but not delete: %v", err) - } - - retrieved, err := store.GetEvent(ctx, "event456") - if err != nil { - t.Fatalf("event should still exist: %v", err) - } - if retrieved.Id != "event456" { - t.Errorf("expected event456, got %s", retrieved.Id) - } -} - -func TestProcessDeletionMultipleEvents(t *testing.T) { - store, err := New(":memory:") - if err != nil { - t.Fatalf("failed to create storage: %v", err) - } - defer store.Close() - - ctx := context.Background() - - for i := 1; i <= 3; i++ { - event := &pb.Event{ - Id: fmt.Sprintf("event%d", i), - Pubkey: "alice", - CreatedAt: time.Now().Unix(), - Kind: 1, - Tags: []*pb.Tag{}, - Content: fmt.Sprintf("event %d", i), - Sig: fmt.Sprintf("sig%d", i), - } - - err = store.StoreEvent(ctx, &EventData{ - Event: event, - CanonicalJSON: []byte(fmt.Sprintf(`[0,"alice",1234567890,1,[],"event %d"]`, i)), - }) - if err != nil { - t.Fatalf("failed to store event: %v", err) - } - } - - deletionEvent := &pb.Event{ - Id: "deletion789", - Pubkey: "alice", - CreatedAt: time.Now().Unix(), - Kind: KindDeletion, - Tags: []*pb.Tag{ - {Values: []string{"e", "event1"}}, - {Values: []string{"e", "event2"}}, - }, - Content: "deleting multiple events", - Sig: "sig_del", - } - - err = store.ProcessDeletion(ctx, deletionEvent) - if err != nil { - t.Fatalf("failed to process deletion: %v", err) - } - - _, err = store.GetEvent(ctx, "event1") - if err != ErrEventNotFound { - t.Error("event1 should be deleted") - } - - _, err = store.GetEvent(ctx, "event2") - if err != ErrEventNotFound { - t.Error("event2 should be deleted") - } - - _, err = store.GetEvent(ctx, "event3") - if err != nil { - t.Error("event3 should still exist") - } -} diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 806acac..d00d7bf 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -99,18 +99,6 @@ func (s *Storage) initSchema(ctx context.Context) error { ON events(tags) WHERE deleted = 0; - -- Deletion events (NIP-09) - CREATE TABLE IF NOT EXISTS deletions ( - deleted_event_id TEXT PRIMARY KEY, -- ID of event being deleted - deletion_event_id TEXT NOT NULL, -- ID of deletion event - pubkey TEXT NOT NULL, -- Who requested deletion - created_at INTEGER NOT NULL, - FOREIGN KEY (deleted_event_id) REFERENCES events(id) - ) STRICT; - - CREATE INDEX IF NOT EXISTS idx_deleted_event - ON deletions(deleted_event_id); - -- Replaceable events tracking (NIP-16, NIP-33) CREATE TABLE IF NOT EXISTS replaceable_events ( kind INTEGER NOT NULL, diff --git a/internal/storage/storage_test.go b/internal/storage/storage_test.go index f2fe401..89369f4 100644 --- a/internal/storage/storage_test.go +++ b/internal/storage/storage_test.go @@ -19,14 +19,14 @@ func TestNew(t *testing.T) { // Verify schema was created by checking if tables exist var count int - query := `SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name IN ('events', 'deletions', 'replaceable_events')` + query := `SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name IN ('events', 'replaceable_events')` err = store.DB().QueryRow(query).Scan(&count) if err != nil { t.Fatalf("failed to query tables: %v", err) } - if count != 3 { - t.Errorf("expected 3 main tables, got %d", count) + if count != 2 { + t.Errorf("expected 2 main tables, got %d", count) } } -- cgit v1.2.3