improve/refactor websocket connections hoping this will fix the undetected disconnections we're seeing.
this commit also remove all the sonic envelope parsing and reintroduces filters in REQ as a slice instead of as a singleton. why? well, the sonic stuff wasn't really that fast, it was a little bit but only got fast enough once I introduced unsafe conversions between []byte and string and did weird unsafe reuse of []byte in order to save the values of tags, which would definitely cause issues in the future if the caller wasn't aware of it (and even if they were, like myself). and the filters stuff is because we abandoned the idea of changing NIP-01 to only accept one filter per REQ.
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
//go:build sonic
|
||||
|
||||
package nostr
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -34,17 +32,17 @@ func TestParseMessage(t *testing.T) {
|
||||
{
|
||||
Name: "EVENT envelope with subscription id",
|
||||
Message: `["EVENT","_",{"kind":1,"id":"dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962","pubkey":"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d","created_at":1644271588,"tags":[],"content":"now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?","sig":"230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524"}]`,
|
||||
ExpectedEnvelope: &EventEnvelope{SubscriptionID: ptr("_"), Event: Event{Kind: 1, ID: "dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962", PubKey: "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d", CreatedAt: 1644271588, Tags: Tags{}, Content: "now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?", Sig: "230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524"}},
|
||||
ExpectedEnvelope: &EventEnvelope{SubscriptionID: ptr("_"), Event: Event{Kind: 1, ID: MustIDFromHex("dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962"), PubKey: MustPubKeyFromHex("3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"), CreatedAt: 1644271588, Tags: Tags{}, Content: "now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?", Sig: mustSigFromHex("230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524")}},
|
||||
},
|
||||
{
|
||||
Name: "EVENT envelope without subscription id",
|
||||
Message: `["EVENT",{"kind":1,"id":"dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962","pubkey":"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d","created_at":1644271588,"tags":[],"content":"now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?","sig":"230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524"}]`,
|
||||
ExpectedEnvelope: &EventEnvelope{Event: Event{Kind: 1, ID: "dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962", PubKey: "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d", CreatedAt: 1644271588, Tags: Tags{}, Content: "now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?", Sig: "230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524"}},
|
||||
ExpectedEnvelope: &EventEnvelope{Event: Event{Kind: 1, ID: MustIDFromHex("dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962"), PubKey: MustPubKeyFromHex("3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"), CreatedAt: 1644271588, Tags: Tags{}, Content: "now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?", Sig: mustSigFromHex("230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524")}},
|
||||
},
|
||||
{
|
||||
Name: "EVENT envelope with tags",
|
||||
Message: `["EVENT",{"kind":3,"id":"9e662bdd7d8abc40b5b15ee1ff5e9320efc87e9274d8d440c58e6eed2dddfbe2","pubkey":"373ebe3d45ec91977296a178d9f19f326c70631d2a1b0bbba5c5ecc2eb53b9e7","created_at":1644844224,"tags":[["p","3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"],["e","75fc5ac2487363293bd27fb0d14fb966477d0f1dbc6361d37806a6a740eda91e"],["p","46d0dfd3a724a302ca9175163bdf788f3606b3fd1bb12d5fe055d1e418cb60ea"]],"content":"{\"wss://nostr-pub.wellorder.net\":{\"read\":true,\"write\":true},\"wss://nostr.bitcoiner.social\":{\"read\":false,\"write\":true},\"wss://expensive-relay.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relayer.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relay.bitid.nz\":{\"read\":true,\"write\":true},\"wss://nostr.rocks\":{\"read\":true,\"write\":true}}","sig":"811355d3484d375df47581cb5d66bed05002c2978894098304f20b595e571b7e01b2efd906c5650080ffe49cf1c62b36715698e9d88b9e8be43029a2f3fa66be"}]`,
|
||||
ExpectedEnvelope: &EventEnvelope{Event: Event{Kind: 3, ID: "9e662bdd7d8abc40b5b15ee1ff5e9320efc87e9274d8d440c58e6eed2dddfbe2", PubKey: "373ebe3d45ec91977296a178d9f19f326c70631d2a1b0bbba5c5ecc2eb53b9e7", CreatedAt: 1644844224, Tags: Tags{Tag{"p", "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"}, Tag{"e", "75fc5ac2487363293bd27fb0d14fb966477d0f1dbc6361d37806a6a740eda91e"}, Tag{"p", "46d0dfd3a724a302ca9175163bdf788f3606b3fd1bb12d5fe055d1e418cb60ea"}}, Content: "{\"wss://nostr-pub.wellorder.net\":{\"read\":true,\"write\":true},\"wss://nostr.bitcoiner.social\":{\"read\":false,\"write\":true},\"wss://expensive-relay.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relayer.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relay.bitid.nz\":{\"read\":true,\"write\":true},\"wss://nostr.rocks\":{\"read\":true,\"write\":true}}", Sig: "811355d3484d375df47581cb5d66bed05002c2978894098304f20b595e571b7e01b2efd906c5650080ffe49cf1c62b36715698e9d88b9e8be43029a2f3fa66be"}},
|
||||
ExpectedEnvelope: &EventEnvelope{Event: Event{Kind: 3, ID: MustIDFromHex("9e662bdd7d8abc40b5b15ee1ff5e9320efc87e9274d8d440c58e6eed2dddfbe2"), PubKey: MustPubKeyFromHex("373ebe3d45ec91977296a178d9f19f326c70631d2a1b0bbba5c5ecc2eb53b9e7"), CreatedAt: 1644844224, Tags: Tags{Tag{"p", "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"}, Tag{"e", "75fc5ac2487363293bd27fb0d14fb966477d0f1dbc6361d37806a6a740eda91e"}, Tag{"p", "46d0dfd3a724a302ca9175163bdf788f3606b3fd1bb12d5fe055d1e418cb60ea"}}, Content: "{\"wss://nostr-pub.wellorder.net\":{\"read\":true,\"write\":true},\"wss://nostr.bitcoiner.social\":{\"read\":false,\"write\":true},\"wss://expensive-relay.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relayer.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relay.bitid.nz\":{\"read\":true,\"write\":true},\"wss://nostr.rocks\":{\"read\":true,\"write\":true}}", Sig: mustSigFromHex("811355d3484d375df47581cb5d66bed05002c2978894098304f20b595e571b7e01b2efd906c5650080ffe49cf1c62b36715698e9d88b9e8be43029a2f3fa66be")}},
|
||||
},
|
||||
{
|
||||
Name: "NOTICE envelope",
|
||||
@@ -59,22 +57,22 @@ func TestParseMessage(t *testing.T) {
|
||||
{
|
||||
Name: "COUNT envelope",
|
||||
Message: `["COUNT","z",{"count":12}]`,
|
||||
ExpectedEnvelope: &CountEnvelope{SubscriptionID: "z", Count: ptr(int64(12))},
|
||||
ExpectedEnvelope: &CountEnvelope{SubscriptionID: "z", Count: ptr(uint32(12))},
|
||||
},
|
||||
{
|
||||
Name: "COUNT envelope with HLL",
|
||||
Message: `["COUNT","sub1",{"count":42, "hll": "0100000101000000000000040000000001020000000002000000000200000003000002040000000101020001010000000000000007000004010000000200040000020400000000000102000002000004010000010000000301000102030002000301000300010000070000000001000004000102010000000400010002000000000103000100010001000001040100020001000000000000010000020000000000030100000001000400010000000000000901010100000000040000000b030000010100010000010000010000000003000000000000010003000100020000000000010000010100000100000104000200030001000300000001000101000102"}]`,
|
||||
ExpectedEnvelope: &CountEnvelope{SubscriptionID: "sub1", Count: ptr(int64(42)), HyperLogLog: []byte{1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 2, 4, 0, 0, 0, 1, 1, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 4, 1, 0, 0, 0, 2, 0, 4, 0, 0, 2, 4, 0, 0, 0, 0, 0, 1, 2, 0, 0, 2, 0, 0, 4, 1, 0, 0, 1, 0, 0, 0, 3, 1, 0, 1, 2, 3, 0, 2, 0, 3, 1, 0, 3, 0, 1, 0, 0, 7, 0, 0, 0, 0, 1, 0, 0, 4, 0, 1, 2, 1, 0, 0, 0, 4, 0, 1, 0, 2, 0, 0, 0, 0, 1, 3, 0, 1, 0, 1, 0, 1, 0, 0, 1, 4, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 1, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 9, 1, 1, 1, 0, 0, 0, 0, 4, 0, 0, 0, 11, 3, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 4, 0, 2, 0, 3, 0, 1, 0, 3, 0, 0, 0, 1, 0, 1, 1, 0, 1, 2}},
|
||||
ExpectedEnvelope: &CountEnvelope{SubscriptionID: "sub1", Count: ptr(uint32(42)), HyperLogLog: []byte{1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 2, 4, 0, 0, 0, 1, 1, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 4, 1, 0, 0, 0, 2, 0, 4, 0, 0, 2, 4, 0, 0, 0, 0, 0, 1, 2, 0, 0, 2, 0, 0, 4, 1, 0, 0, 1, 0, 0, 0, 3, 1, 0, 1, 2, 3, 0, 2, 0, 3, 1, 0, 3, 0, 1, 0, 0, 7, 0, 0, 0, 0, 1, 0, 0, 4, 0, 1, 2, 1, 0, 0, 0, 4, 0, 1, 0, 2, 0, 0, 0, 0, 1, 3, 0, 1, 0, 1, 0, 1, 0, 0, 1, 4, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 1, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 9, 1, 1, 1, 0, 0, 0, 0, 4, 0, 0, 0, 11, 3, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 4, 0, 2, 0, 3, 0, 1, 0, 3, 0, 0, 0, 1, 0, 1, 1, 0, 1, 2}},
|
||||
},
|
||||
{
|
||||
Name: "OK envelope success",
|
||||
Message: `["OK","3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa",true,""]`,
|
||||
ExpectedEnvelope: &OKEnvelope{EventID: "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa", OK: true, Reason: ""},
|
||||
ExpectedEnvelope: &OKEnvelope{EventID: MustIDFromHex("3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa"), OK: true, Reason: ""},
|
||||
},
|
||||
{
|
||||
Name: "OK envelope failure",
|
||||
Message: `["OK","3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa",false,"error: could not connect to the database"]`,
|
||||
ExpectedEnvelope: &OKEnvelope{EventID: "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa", OK: false, Reason: "error: could not connect to the database"},
|
||||
ExpectedEnvelope: &OKEnvelope{EventID: MustIDFromHex("3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa"), OK: false, Reason: "error: could not connect to the database"},
|
||||
},
|
||||
{
|
||||
Name: "CLOSED envelope with underscore",
|
||||
@@ -94,12 +92,12 @@ func TestParseMessage(t *testing.T) {
|
||||
{
|
||||
Name: "AUTH envelope with event",
|
||||
Message: `["AUTH",{"kind":1,"id":"ae1fc7154296569d87ca4663f6bdf448c217d1590d28c85d158557b8b43b4d69","pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","created_at":1683660344,"tags":[],"content":"hello world","sig":"94e10947814b1ebe38af42300ecd90c7642763896c4f69506ae97bfdf54eec3c0c21df96b7d95daa74ff3d414b1d758ee95fc258125deebc31df0c6ba9396a51"}]`,
|
||||
ExpectedEnvelope: &AuthEnvelope{Event: Event{Kind: 1, ID: "ae1fc7154296569d87ca4663f6bdf448c217d1590d28c85d158557b8b43b4d69", PubKey: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", CreatedAt: 1683660344, Tags: Tags{}, Content: "hello world", Sig: "94e10947814b1ebe38af42300ecd90c7642763896c4f69506ae97bfdf54eec3c0c21df96b7d95daa74ff3d414b1d758ee95fc258125deebc31df0c6ba9396a51"}},
|
||||
ExpectedEnvelope: &AuthEnvelope{Event: Event{Kind: 1, ID: MustIDFromHex("ae1fc7154296569d87ca4663f6bdf448c217d1590d28c85d158557b8b43b4d69"), PubKey: MustPubKeyFromHex("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"), CreatedAt: 1683660344, Tags: Tags{}, Content: "hello world", Sig: mustSigFromHex("94e10947814b1ebe38af42300ecd90c7642763896c4f69506ae97bfdf54eec3c0c21df96b7d95daa74ff3d414b1d758ee95fc258125deebc31df0c6ba9396a51")}},
|
||||
},
|
||||
{
|
||||
Name: "REQ envelope",
|
||||
Message: `["REQ","million", {"kinds": [1]}, {"kinds": [30023 ], "#d": ["buteko", "batuke"]}]`,
|
||||
ExpectedEnvelope: &ReqEnvelope{SubscriptionID: "million", Filters: Filters{{Kinds: []Kind{1}}, {Kinds: []Kind{30023}, Tags: TagMap{"d": []string{"buteko", "batuke"}}}}},
|
||||
ExpectedEnvelope: &ReqEnvelope{SubscriptionID: "million", Filters: []Filter{{Kinds: []Kind{1}}, {Kinds: []Kind{30023}, Tags: TagMap{"d": []string{"buteko", "batuke"}}}}},
|
||||
},
|
||||
{
|
||||
Name: "CLOSE envelope",
|
||||
@@ -114,36 +112,14 @@ func TestParseMessage(t *testing.T) {
|
||||
{
|
||||
Name: "REQ from jumble",
|
||||
Message: `["REQ","sub:1",{"kinds":[1,6],"limit":100}]`,
|
||||
ExpectedEnvelope: &ReqEnvelope{SubscriptionID: "sub:1", Filters: Filters{{Kinds: []int{1, 6}, Limit: 100}}},
|
||||
ExpectedEnvelope: &ReqEnvelope{SubscriptionID: "sub:1", Filters: []Filter{{Kinds: []Kind{1, 6}, Limit: 100}}},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("standard", func(t *testing.T) {
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
envelope := ParseMessage(testCase.Message)
|
||||
if testCase.ExpectedEnvelope == nil && envelope == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if testCase.ExpectedEnvelope == nil {
|
||||
require.Nil(t, envelope, "expected nil but got %v", envelope)
|
||||
return
|
||||
}
|
||||
|
||||
require.NotNil(t, envelope, "expected non-nil envelope but got nil")
|
||||
require.Equal(t, testCase.ExpectedEnvelope.String(), envelope.String())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("sonic", func(t *testing.T) {
|
||||
smp := NewSonicMessageParser()
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
envelope, err := smp.ParseMessage(testCase.Message)
|
||||
|
||||
envelope, err := ParseMessage(testCase.Message)
|
||||
if testCase.ExpectedEnvelope == nil && envelope == nil {
|
||||
return
|
||||
}
|
||||
@@ -155,45 +131,14 @@ func TestParseMessage(t *testing.T) {
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, envelope, "expected non-nil envelope but got nil")
|
||||
require.Equal(t, testCase.ExpectedEnvelope, envelope)
|
||||
require.Equal(t, testCase.ExpectedEnvelope.String(), envelope.String())
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseMessagesFromFile(t *testing.T) {
|
||||
file, err := os.Open("testdata/messages.jsonl")
|
||||
if err != nil {
|
||||
t.Skipf("Skipping test because testdata/messages.jsonl could not be opened: %v", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
smp := NewSonicMessageParser()
|
||||
lineNum := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
lineNum++
|
||||
line := scanner.Bytes()
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
standardEnvelope := ParseMessage(string(line))
|
||||
sonicEnvelope, err := smp.ParseMessage(string(line))
|
||||
|
||||
if standardEnvelope == nil {
|
||||
require.Nil(t, sonicEnvelope, "line %d: standard parser returned nil but sonic parser didn't", lineNum)
|
||||
continue
|
||||
}
|
||||
|
||||
require.NoError(t, err, "line %d: sonic parser returned error", lineNum)
|
||||
require.NotNil(t, sonicEnvelope, "line %d: standard parser returned non-nil but sonic parser returned nil", lineNum)
|
||||
|
||||
require.Equal(t, standardEnvelope, sonicEnvelope,
|
||||
"line %d: parsers returned different results", lineNum)
|
||||
}
|
||||
|
||||
require.NoError(t, scanner.Err(), "error reading file")
|
||||
func mustSigFromHex(sigStr string) [64]byte {
|
||||
var sig [64]byte
|
||||
hex.Decode(sig[:], unsafe.Slice(unsafe.StringData(sigStr), 128))
|
||||
return sig
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user