Skip to content

Commit

Permalink
Drop support for NIP-26 because no one uses it literally and it seems…
Browse files Browse the repository at this point in the history
… not even planning
  • Loading branch information
viktorvsk committed Nov 19, 2023
1 parent ac53acf commit 1d902ad
Show file tree
Hide file tree
Showing 17 changed files with 34 additions and 254 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ This is an implementation of the [Nostr protocol](https://github.com/nostr-proto
* [NIP-09: Event Deletion](https://github.com/nostr-protocol/nips/blob/master/09.md)
* [NIP-11: Relay Information Document](https://github.com/nostr-protocol/nips/blob/master/11.md)
* [NIP-13: Proof of Work](https://github.com/nostr-protocol/nips/blob/master/13.md)
* [NIP-26: Delegated Event Signing](https://github.com/nostr-protocol/nips/blob/master/26.md)
* [NIP-28: Public Chat](https://github.com/nostr-protocol/nips/blob/master/28.md) Treats kind 41 event as replaceable
* [NIP-40: Expiration Timestamp](https://github.com/nostr-protocol/nips/blob/master/40.md)
* [NIP-42: Authentication of clients to relays](https://github.com/nostr-protocol/nips/blob/master/42.md)
Expand Down
2 changes: 1 addition & 1 deletion app/jobs/delete_expired_event_nip40.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ class DeleteExpiredEventNip40
sidekiq_options queue: "nostr.nip40"

def perform(sha256)
Event.includes(:event_delegator, :searchable_content).where("LOWER(events.sha256) = ?", sha256).destroy_all
Event.includes(:searchable_content).where("LOWER(events.sha256) = ?", sha256).destroy_all
end
end
39 changes: 5 additions & 34 deletions app/models/concerns/nostr/nip1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def delete_older_replaceable
Event.where(author_id: author_id, kind: kind, created_at: created_at).where("LOWER(events.sha256) > ?", sha256.downcase).pluck(:id)
].flatten.reject(&:blank?)

Event.includes(:event_delegator, :searchable_content).where(id: to_delete.uniq).destroy_all if to_delete.present?
Event.includes(:searchable_content).where(id: to_delete.uniq).destroy_all if to_delete.present?
end

def must_not_be_ephemeral
Expand Down Expand Up @@ -193,7 +193,7 @@ def delete_older_parameterized_replaceable
Event.joins(:searchable_tags).where("LOWER(searchable_tags.value) = ?", d_tag_value.downcase).where(author_id: author_id, kind: kind, created_at: created_at, searchable_tags: {name: "d"}).where("LOWER(events.sha256) > ?", sha256.downcase).pluck(:id)
].flatten.reject(&:blank?)

Event.includes(:event_delegator, :searchable_content).where(id: to_delete).destroy_all
Event.includes(:searchable_content).where(id: to_delete).destroy_all
end

def must_be_newer_than_existing_parameterized_replaceable
Expand Down Expand Up @@ -247,24 +247,18 @@ def by_nostr_filters(filter_set, subscriber_pubkey = nil, count_request = nil)
where_clause = <<~SQL
events.kind IN (:kinds) OR
(
events.kind = 4 AND (LOWER(authors.pubkey) = :pubkey OR LOWER(delegator_authors.pubkey) = :pubkey OR LOWER(p_tags.value) = :pubkey)
events.kind = 4 AND (LOWER(authors.pubkey) = :pubkey OR LOWER(p_tags.value) = :pubkey)
)
SQL
# NIP-26
# TODO: check performance
rel
.joins(:author)
.joins("LEFT JOIN searchable_tags AS p_tags ON p_tags.event_id = events.id AND p_tags.name = 'p'")
.joins("LEFT JOIN event_delegators ON event_delegators.event_id = events.id")
.joins("LEFT JOIN authors AS delegator_authors ON delegator_authors.id = event_delegators.author_id")
.where(where_clause, kinds: value, pubkey: subscriber_pubkey.downcase)
else
rel
.joins(:author)
.joins("LEFT JOIN searchable_tags AS p_tags ON p_tags.event_id = events.id AND p_tags.name = 'p'")
.joins("LEFT JOIN event_delegators ON event_delegators.event_id = events.id")
.joins("LEFT JOIN authors AS delegator_authors ON delegator_authors.id = event_delegators.author_id")
.where("events.kind = 4 AND (LOWER(authors.pubkey) = :pubkey OR LOWER(delegator_authors.pubkey) = :pubkey OR LOWER(p_tags.value) = :pubkey)", pubkey: subscriber_pubkey.downcase)
.where("events.kind = 4 AND (LOWER(authors.pubkey) = :pubkey OR LOWER(p_tags.value) = :pubkey)", pubkey: subscriber_pubkey.downcase)
end
else
rel.where(kind: value)
Expand Down Expand Up @@ -311,30 +305,7 @@ def by_nostr_filters(filter_set, subscriber_pubkey = nil, count_request = nil)
RELAY_CONFIG.default_filter_limit
end

if filter_set.key?("authors")

# NIP-26

# pubkey max length is 64 so we don't need a predicate match in this case
where_clause = filter_set["authors"].map { |pubkey| "LOWER(delegator_authors.pubkey) = ?" }.join(" OR ")

delegator_rel = by_nostr_filters(filter_set.except("authors"), subscriber_pubkey, count_request).joins(:author)
.joins("LEFT JOIN event_delegators ON event_delegators.event_id = events.id")
.joins("LEFT JOIN authors AS delegator_authors ON delegator_authors.id = event_delegators.author_id")
.where(where_clause, *filter_set["authors"].map(&:downcase))
union = <<~SQL
(#{rel.limit(filter_limit).to_sql})
UNION
(#{delegator_rel.limit(filter_limit).to_sql})
SQL

LazySql.new(klass: "Event", sql: union)

else
rel.limit(filter_limit)
end
rel.limit(filter_limit)
end
end
end
Expand Down
70 changes: 0 additions & 70 deletions app/models/concerns/nostr/nip26.rb

This file was deleted.

2 changes: 1 addition & 1 deletion app/models/concerns/nostr/nip9.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def process_delete_event_nip_9
if events_ids_to_delete.present?
DeleteEvent.upsert_all(delete_events_to_upsert, unique_by: %i[sha256 author_id])
to_delete_events_ids = Event.where(author_id: author.id).where("LOWER(events.sha256) IN (?)", events_ids_to_delete).where.not(kind: 5).pluck(:id)
Event.includes(:event_delegator, :searchable_content).where(id: to_delete_events_ids).destroy_all
Event.includes(:searchable_content).where(id: to_delete_events_ids).destroy_all
end
end
end
Expand Down
1 change: 0 additions & 1 deletion app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ class Event < ApplicationRecord
include Nostr::Nip1
include Nostr::Nip9
include Nostr::Nip13
include Nostr::Nip26
include Nostr::Nip40
include Nostr::Nip42
include Nostr::Nip50
Expand Down
1 change: 0 additions & 1 deletion app/models/subscription_matcher_query_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class SubscriptionMatcherQueryBuilder
def initialize(event)
authors = [
event.pubkey,
event.delegation_tag_pubkey,
SubscriptionQueryBuilder::REDIS_SEARCH_TAG_ANY_VALUE
].reject(&:blank?).join(" | ")

Expand Down
16 changes: 16 additions & 0 deletions db/migrate/20231119170827_drop_event_delegators_table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class DropEventDelegatorsTable < ActiveRecord::Migration[7.0]
def up
drop_table :event_delegators
end

def down
create_table :event_delegators do |t|
t.references :event, index: false, foreign_key: true, null: false
t.references :author, index: false, foreign_key: true, null: false
end

add_index :event_delegators, :event_id, unique: true
add_index :event_delegators, %i[event_id author_id]
execute("CLUSTER event_delegators USING index_event_delegators_on_event_id_and_author_id")
end
end
80 changes: 2 additions & 78 deletions db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -125,36 +125,6 @@ CREATE TABLE public.delete_events (
);


--
-- Name: event_delegators; Type: TABLE; Schema: public; Owner: -
--

CREATE TABLE public.event_delegators (
id bigint NOT NULL,
event_id bigint NOT NULL,
author_id bigint NOT NULL
);


--
-- Name: event_delegators_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--

CREATE SEQUENCE public.event_delegators_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;


--
-- Name: event_delegators_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--

ALTER SEQUENCE public.event_delegators_id_seq OWNED BY public.event_delegators.id;


--
-- Name: events; Type: TABLE; Schema: public; Owner: -
--
Expand Down Expand Up @@ -447,13 +417,6 @@ ALTER TABLE ONLY public.author_subscriptions ALTER COLUMN id SET DEFAULT nextval
ALTER TABLE ONLY public.authors ALTER COLUMN id SET DEFAULT nextval('public.authors_id_seq'::regclass);


--
-- Name: event_delegators id; Type: DEFAULT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.event_delegators ALTER COLUMN id SET DEFAULT nextval('public.event_delegators_id_seq'::regclass);


--
-- Name: events id; Type: DEFAULT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -527,14 +490,6 @@ ALTER TABLE ONLY public.authors
ADD CONSTRAINT authors_pkey PRIMARY KEY (id);


--
-- Name: event_delegators event_delegators_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.event_delegators
ADD CONSTRAINT event_delegators_pkey PRIMARY KEY (id);


--
-- Name: events events_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -650,22 +605,6 @@ CREATE UNIQUE INDEX index_delete_events_on_sha256_and_author_id ON public.delete
ALTER TABLE public.delete_events CLUSTER ON index_delete_events_on_sha256_and_author_id;


--
-- Name: index_event_delegators_on_event_id; Type: INDEX; Schema: public; Owner: -
--

CREATE UNIQUE INDEX index_event_delegators_on_event_id ON public.event_delegators USING btree (event_id);


--
-- Name: index_event_delegators_on_event_id_and_author_id; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX index_event_delegators_on_event_id_and_author_id ON public.event_delegators USING btree (event_id, author_id);

ALTER TABLE public.event_delegators CLUSTER ON index_event_delegators_on_event_id_and_author_id;


--
-- Name: index_events_for_replaceable; Type: INDEX; Schema: public; Owner: -
--
Expand Down Expand Up @@ -869,22 +808,6 @@ ALTER TABLE ONLY public.invoices
ADD CONSTRAINT fk_rails_32fc3ccfac FOREIGN KEY (author_id) REFERENCES public.authors(id);


--
-- Name: event_delegators fk_rails_3df25f44ef; Type: FK CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.event_delegators
ADD CONSTRAINT fk_rails_3df25f44ef FOREIGN KEY (author_id) REFERENCES public.authors(id);


--
-- Name: event_delegators fk_rails_5f94d04b9b; Type: FK CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.event_delegators
ADD CONSTRAINT fk_rails_5f94d04b9b FOREIGN KEY (event_id) REFERENCES public.events(id);


--
-- Name: user_pubkeys fk_rails_66431c7d01; Type: FK CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -978,6 +901,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20230827170307'),
('20231025122455'),
('20231105000145'),
('20231105000543');
('20231105000543'),
('20231119170827');


2 changes: 1 addition & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Mirrors is a process that is responsible to launch Websocket Clients that connec
### Database
Tested against 14,15 and 16 versions of PostgreSQL but at the moment there are no version-specific SQL so in theory many versions should be compatible.

Database currently has the following core tables: `authors`, `delete_events`, `events`, `searchable_tags`, `event_delegators`, `trusted_authors` which are slightly optimized for storage (by normalizing `authors` public keys for example).
Database currently has the following core tables: `authors`, `delete_events`, `events`, `searchable_tags`, `trusted_authors` which are slightly optimized for storage (by normalizing `authors` public keys for example).
And secondary, not Nostr-specific tables: `users`, `user_pubkeys`, `relay_mirrors`, `invoices`, `author_subscriptions`.
Proper indexing strategy is a subject to change.

Expand Down
6 changes: 0 additions & 6 deletions spec/factories/event_delegators.rb

This file was deleted.

4 changes: 0 additions & 4 deletions spec/factories/events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
content { "" }
created_at { Time.now }

trait :delegated_event do
tags { [["delegation", NIP_26_TAG[:pk], NIP_26_TAG[:conditions], NIP_26_TAG[:sig]]] }
end

after(:build) do |event|
if event.pubkey.blank?
_random_fake_signer_name, credentials = FAKE_CREDENTIALS.to_a.sample
Expand Down
4 changes: 2 additions & 2 deletions spec/models/event_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

it "destroys event" do
kind2_event.save!
kind2_event_with_event_delegators_included = Event.includes(:event_delegator, :searchable_content).where(id: kind2_event).first
expect { kind2_event_with_event_delegators_included.destroy }.to change { kind2_event_with_event_delegators_included.persisted? }.from(true).to(false)
kind2_event_with_searchable_content_included = Event.includes(:searchable_content).where(id: kind2_event).first
expect { kind2_event_with_searchable_content_included.destroy }.to change { kind2_event_with_searchable_content_included.persisted? }.from(true).to(false)
end

context "raises ActiveRecord::ReadOnlyRecord when" do
Expand Down
6 changes: 3 additions & 3 deletions spec/nips/nip01_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
# expect(Event.by_nostr_filters({"ids" => ["bf84a73d1e6a1708b1c4dc5555a78f342ef29abfd469a091ca4f34533399c95f", event_with_tagsith_searchable_tags.sha256.first(5)]}).count).to eq(1)

expect(Event.by_nostr_filters({"authors" => ["8e0d3"]}).count).to eq(0)
expect(Event.by_nostr_filters({"authors" => ["8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd"]}).count).to eq(1)
expect(Event.by_nostr_filters({"authors" => ["8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd"]}).count).to eq(0)
expect(Event.by_nostr_filters({"authors" => ["09cd08d"]}).count).to eq(0)
expect(Event.by_nostr_filters({"authors" => ["09cd08d416b78dd3e1d6c00c9e14087d803df6360fbf0acdb30106ca042ee81e"]}).count).to eq(1)
expect(Event.by_nostr_filters({}).count).to eq(3)
Expand Down Expand Up @@ -343,14 +343,14 @@
expect(MemStore.matching_pubsubs_for(event)).to match_array("C1:S1")
end

it "matches author filter when author is delegated" do
it "does not match author filter when author is delegated" do
parsed_json = JSON.parse(File.read(Rails.root.join(*%w[spec support nostr_event_delegated.json])))
delegated_event_params = parsed_json.merge("sha256" => parsed_json.delete("id"), "created_at" => Time.at(parsed_json["created_at"]))
delegated_event = Event.new(delegated_event_params)
MemStore.subscribe(cid: "C1", sid: "S1", filters: ["authors" => ["09cd08d416b78dd3e1d6c00c9e14087d803df6360fbf0acdb30106ca042ee81e"]])
MemStore.subscribe(cid: "C1", sid: "S2", filters: ["authors" => ["8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd"]])

expect(MemStore.matching_pubsubs_for(delegated_event)).to match_array(["C1:S1", "C1:S2"])
expect(MemStore.matching_pubsubs_for(delegated_event)).to match_array(["C1:S1"])
end

it "matches #e and #p filters" do
Expand Down
Loading

0 comments on commit 1d902ad

Please sign in to comment.