define a nostr.Kind type for event kinds, make adjustments everywhere and fix some horrible bugs with mmm, lmdb and badger querying and deleting.

This commit is contained in:
fiatjaf
2025-04-20 11:14:39 -03:00
parent 27f40c2cf2
commit 15c6093c9b
74 changed files with 689 additions and 404 deletions

View File

@@ -11,7 +11,7 @@ import (
// AddEvent sends an event through then normal add pipeline, as if it was received from a websocket.
func (rl *Relay) AddEvent(ctx context.Context, evt nostr.Event) (skipBroadcast bool, writeError error) {
if nostr.IsEphemeralKind(evt.Kind) {
if evt.Kind.IsEphemeral() {
return false, rl.handleEphemeral(ctx, evt)
} else {
return rl.handleNormal(ctx, evt)
@@ -31,7 +31,7 @@ func (rl *Relay) handleNormal(ctx context.Context, evt nostr.Event) (skipBroadca
// will store
// regular kinds are just saved directly
if nostr.IsRegularKind(evt.Kind) {
if evt.Kind.IsRegular() {
if nil != rl.StoreEvent {
if err := rl.StoreEvent(ctx, evt); err != nil {
switch err {

View File

@@ -18,7 +18,7 @@ type EventStoreBlobIndexWrapper struct {
func (es EventStoreBlobIndexWrapper) Keep(ctx context.Context, blob BlobDescriptor, pubkey nostr.PubKey) error {
next, stop := iter.Pull(
es.Store.QueryEvents(nostr.Filter{Authors: []nostr.PubKey{pubkey}, Kinds: []uint16{24242}, Tags: nostr.TagMap{"x": []string{blob.SHA256}}}),
es.Store.QueryEvents(nostr.Filter{Authors: []nostr.PubKey{pubkey}, Kinds: []nostr.Kind{24242}, Tags: nostr.TagMap{"x": []string{blob.SHA256}}}),
)
defer stop()
@@ -45,7 +45,7 @@ func (es EventStoreBlobIndexWrapper) List(ctx context.Context, pubkey nostr.PubK
return func(yield func(BlobDescriptor) bool) {
for evt := range es.Store.QueryEvents(nostr.Filter{
Authors: []nostr.PubKey{pubkey},
Kinds: []uint16{24242},
Kinds: []nostr.Kind{24242},
}) {
yield(es.parseEvent(evt))
}
@@ -54,7 +54,7 @@ func (es EventStoreBlobIndexWrapper) List(ctx context.Context, pubkey nostr.PubK
func (es EventStoreBlobIndexWrapper) Get(ctx context.Context, sha256 string) (*BlobDescriptor, error) {
next, stop := iter.Pull(
es.Store.QueryEvents(nostr.Filter{Tags: nostr.TagMap{"x": []string{sha256}}, Kinds: []uint16{24242}, Limit: 1}),
es.Store.QueryEvents(nostr.Filter{Tags: nostr.TagMap{"x": []string{sha256}}, Kinds: []nostr.Kind{24242}, Limit: 1}),
)
defer stop()
@@ -72,7 +72,7 @@ func (es EventStoreBlobIndexWrapper) Delete(ctx context.Context, sha256 string,
es.Store.QueryEvents(nostr.Filter{
Authors: []nostr.PubKey{pubkey},
Tags: nostr.TagMap{"x": []string{sha256}},
Kinds: []uint16{24242},
Kinds: []nostr.Kind{24242},
Limit: 1,
},
),

View File

@@ -38,7 +38,7 @@ func (rl *Relay) handleDeleteRequest(ctx context.Context, evt nostr.Event) error
identifier := spl[2]
f = nostr.Filter{
Kinds: []uint16{uint16(kind)},
Kinds: []nostr.Kind{nostr.Kind(kind)},
Authors: []nostr.PubKey{author},
Tags: nostr.TagMap{"d": []string{identifier}},
Until: &evt.CreatedAt,

View File

@@ -214,7 +214,7 @@ func (rl *Relay) HandleWebsocket(w http.ResponseWriter, r *http.Request) {
if env.Event.Kind == 5 {
// this always returns "blocked: " whenever it returns an error
writeErr = srl.handleDeleteRequest(ctx, env.Event)
} else if nostr.IsEphemeralKind(env.Event.Kind) {
} else if env.Event.Kind.IsEphemeral() {
// this will also always return a prefixed reason
writeErr = srl.handleEphemeral(ctx, env.Event)
} else {
@@ -229,7 +229,7 @@ func (rl *Relay) HandleWebsocket(w http.ResponseWriter, r *http.Request) {
n := srl.notifyListeners(env.Event)
// the number of notified listeners matters in ephemeral events
if nostr.IsEphemeralKind(env.Event.Kind) {
if env.Event.Kind.IsEphemeral() {
if n == 0 {
ok = false
reason = "mute: no one was listening for this"

View File

@@ -17,7 +17,7 @@ func FuzzRandomListenerClientRemoving(f *testing.F) {
rl := NewRelay()
f := nostr.Filter{Kinds: []uint16{1}}
f := nostr.Filter{Kinds: []nostr.Kind{1}}
cancel := func(cause error) {}
websockets := make([]*WebSocket, 0, totalWebsockets*baseSubs)
@@ -71,7 +71,7 @@ func FuzzRandomListenerIdRemoving(f *testing.F) {
rl := NewRelay()
f := nostr.Filter{Kinds: []uint16{1}}
f := nostr.Filter{Kinds: []nostr.Kind{1}}
cancel := func(cause error) {}
websockets := make([]*WebSocket, 0, totalWebsockets)
@@ -150,7 +150,7 @@ func FuzzRouterListenersPabloCrash(f *testing.F) {
rl.clients[ws] = make([]listenerSpec, 0, subIterations)
}
f := nostr.Filter{Kinds: []uint16{1}}
f := nostr.Filter{Kinds: []nostr.Kind{1}}
cancel := func(cause error) {}
type wsid struct {

View File

@@ -29,9 +29,9 @@ func TestListenerSetupAndRemoveOnce(t *testing.T) {
ws1 := &WebSocket{}
ws2 := &WebSocket{}
f1 := nostr.Filter{Kinds: []uint16{1}}
f2 := nostr.Filter{Kinds: []uint16{2}}
f3 := nostr.Filter{Kinds: []uint16{3}}
f1 := nostr.Filter{Kinds: []nostr.Kind{1}}
f2 := nostr.Filter{Kinds: []nostr.Kind{2}}
f3 := nostr.Filter{Kinds: []nostr.Kind{3}}
rl.clients[ws1] = nil
rl.clients[ws2] = nil
@@ -86,9 +86,9 @@ func TestListenerMoreConvolutedCase(t *testing.T) {
ws3 := &WebSocket{}
ws4 := &WebSocket{}
f1 := nostr.Filter{Kinds: []uint16{1}}
f2 := nostr.Filter{Kinds: []uint16{2}}
f3 := nostr.Filter{Kinds: []uint16{3}}
f1 := nostr.Filter{Kinds: []nostr.Kind{1}}
f2 := nostr.Filter{Kinds: []nostr.Kind{2}}
f3 := nostr.Filter{Kinds: []nostr.Kind{3}}
rl.clients[ws1] = nil
rl.clients[ws2] = nil
@@ -205,9 +205,9 @@ func TestListenerMoreStuffWithMultipleRelays(t *testing.T) {
ws3 := &WebSocket{}
ws4 := &WebSocket{}
f1 := nostr.Filter{Kinds: []uint16{1}}
f2 := nostr.Filter{Kinds: []uint16{2}}
f3 := nostr.Filter{Kinds: []uint16{3}}
f1 := nostr.Filter{Kinds: []nostr.Kind{1}}
f2 := nostr.Filter{Kinds: []nostr.Kind{2}}
f3 := nostr.Filter{Kinds: []nostr.Kind{3}}
rlx := NewRelay()
rly := NewRelay()
@@ -424,7 +424,7 @@ func TestListenerMoreStuffWithMultipleRelays(t *testing.T) {
func TestRandomListenerClientRemoving(t *testing.T) {
rl := NewRelay()
f := nostr.Filter{Kinds: []uint16{1}}
f := nostr.Filter{Kinds: []nostr.Kind{1}}
cancel := func(cause error) {}
websockets := make([]*WebSocket, 0, 20)
@@ -463,7 +463,7 @@ func TestRandomListenerClientRemoving(t *testing.T) {
func TestRandomListenerIdRemoving(t *testing.T) {
rl := NewRelay()
f := nostr.Filter{Kinds: []uint16{1}}
f := nostr.Filter{Kinds: []nostr.Kind{1}}
cancel := func(cause error) {}
websockets := make([]*WebSocket, 0, 20)
@@ -531,7 +531,7 @@ func TestRouterListenersPabloCrash(t *testing.T) {
rl.clients[ws2] = nil
rl.clients[ws3] = nil
f := nostr.Filter{Kinds: []uint16{1}}
f := nostr.Filter{Kinds: []nostr.Kind{1}}
cancel := func(cause error) {}
rl.addListener(ws1, ":1", rla, f, cancel)

View File

@@ -16,19 +16,19 @@ import (
//
// If ignoreKinds is given this restriction will not apply to these kinds (useful for allowing a bigger).
// If onlyKinds is given then all other kinds will be ignored.
func PreventTooManyIndexableTags(max int, ignoreKinds []uint16, onlyKinds []uint16) func(context.Context, nostr.Event) (bool, string) {
func PreventTooManyIndexableTags(max int, ignoreKinds []nostr.Kind, onlyKinds []nostr.Kind) func(context.Context, nostr.Event) (bool, string) {
slices.Sort(ignoreKinds)
slices.Sort(onlyKinds)
ignore := func(kind uint16) bool { return false }
ignore := func(kind nostr.Kind) bool { return false }
if len(ignoreKinds) > 0 {
ignore = func(kind uint16) bool {
ignore = func(kind nostr.Kind) bool {
_, isIgnored := slices.BinarySearch(ignoreKinds, kind)
return isIgnored
}
}
if len(onlyKinds) > 0 {
ignore = func(kind uint16) bool {
ignore = func(kind nostr.Kind) bool {
_, isApplicable := slices.BinarySearch(onlyKinds, kind)
return !isApplicable
}
@@ -68,16 +68,16 @@ func PreventLargeTags(maxTagValueLen int) func(context.Context, nostr.Event) (bo
// RestrictToSpecifiedKinds returns a function that can be used as a RejectFilter that will reject
// any events with kinds different than the specified ones.
func RestrictToSpecifiedKinds(allowEphemeral bool, kinds ...uint16) func(context.Context, nostr.Event) (bool, string) {
func RestrictToSpecifiedKinds(allowEphemeral bool, kinds ...nostr.Kind) func(context.Context, nostr.Event) (bool, string) {
// sort the kinds in increasing order
slices.Sort(kinds)
return func(ctx context.Context, event nostr.Event) (reject bool, msg string) {
if allowEphemeral && nostr.IsEphemeralKind(event.Kind) {
if allowEphemeral && event.Kind.IsEphemeral() {
return false, ""
}
if _, allowed := slices.BinarySearch(kinds, uint16(event.Kind)); allowed {
if _, allowed := slices.BinarySearch(kinds, nostr.Kind(event.Kind)); allowed {
return false, ""
}

View File

@@ -60,12 +60,12 @@ func RemoveSearchQueries(ctx context.Context, filter *nostr.Filter) {
}
}
func RemoveAllButKinds(kinds ...uint16) func(context.Context, *nostr.Filter) {
func RemoveAllButKinds(kinds ...nostr.Kind) func(context.Context, *nostr.Filter) {
return func(ctx context.Context, filter *nostr.Filter) {
if n := len(filter.Kinds); n > 0 {
newKinds := make([]uint16, 0, n)
newKinds := make([]nostr.Kind, 0, n)
for i := 0; i < n; i++ {
if k := filter.Kinds[i]; slices.Contains(kinds, uint16(k)) {
if k := filter.Kinds[i]; slices.Contains(kinds, nostr.Kind(k)) {
newKinds = append(newKinds, k)
}
}

View File

@@ -37,7 +37,7 @@ func FuzzReplaceableEvents(f *testing.F) {
pk1 := nostr.GetPublicKey(sk1)
// helper to create signed events
createEvent := func(sk nostr.SecretKey, kind uint16, content string, tags nostr.Tags) nostr.Event {
createEvent := func(sk nostr.SecretKey, kind nostr.Kind, content string, tags nostr.Tags) nostr.Event {
pk := nostr.GetPublicKey(sk)
evt := nostr.Event{
PubKey: pk,
@@ -87,7 +87,7 @@ func FuzzReplaceableEvents(f *testing.F) {
// query to verify only the newest event exists
sub, err := client2.Subscribe(ctx, nostr.Filter{
Authors: []nostr.PubKey{pk1},
Kinds: []uint16{0},
Kinds: []nostr.Kind{0},
}, nostr.SubscriptionOptions{})
if err != nil {
t.Fatalf("failed to subscribe: %v", err)

View File

@@ -30,7 +30,7 @@ func TestBasicRelayFunctionality(t *testing.T) {
pk2 := nostr.GetPublicKey(sk2)
// helper to create signed events
createEvent := func(sk nostr.SecretKey, kind uint16, content string, tags nostr.Tags) nostr.Event {
createEvent := func(sk nostr.SecretKey, kind nostr.Kind, content string, tags nostr.Tags) nostr.Event {
pk := nostr.GetPublicKey(sk)
evt := nostr.Event{
PubKey: pk,
@@ -71,7 +71,7 @@ func TestBasicRelayFunctionality(t *testing.T) {
// Query the event back
sub, err := client2.Subscribe(ctx, nostr.Filter{
Authors: []nostr.PubKey{pk1},
Kinds: []uint16{1},
Kinds: []nostr.Kind{1},
}, nostr.SubscriptionOptions{})
if err != nil {
t.Fatalf("failed to subscribe: %v", err)
@@ -97,7 +97,7 @@ func TestBasicRelayFunctionality(t *testing.T) {
// Setup subscription first
sub, err := client1.Subscribe(ctx, nostr.Filter{
Authors: []nostr.PubKey{pk2},
Kinds: []uint16{1},
Kinds: []nostr.Kind{1},
}, nostr.SubscriptionOptions{})
if err != nil {
t.Fatalf("failed to subscribe: %v", err)
@@ -202,7 +202,7 @@ func TestBasicRelayFunctionality(t *testing.T) {
// query to verify only the newest event exists
sub, err := client2.Subscribe(ctx, nostr.Filter{
Authors: []nostr.PubKey{pk1},
Kinds: []uint16{0},
Kinds: []nostr.Kind{0},
}, nostr.SubscriptionOptions{})
if err != nil {
t.Fatalf("failed to subscribe: %v", err)