serialization tests for events and filters.

This commit is contained in:
fiatjaf 2022-02-09 13:40:26 -03:00
parent 5266482b2a
commit 41955a0601
4 changed files with 149 additions and 5 deletions

View File

@ -38,14 +38,13 @@ type Event struct {
type Time time.Time
func (tm *Time) UnmarshalJSON(payload []byte) error {
var unix int64
err := json.Unmarshal(payload, &unix)
unix, err := strconv.ParseInt(string(payload), 10, 64)
if err != nil {
return fmt.Errorf("time must be a unix timestamp as an integer, not '%s': %w",
string(payload), err)
}
t := Time(time.Unix(unix, 0))
tm = &t
*tm = t
return nil
}
@ -53,6 +52,12 @@ func (t Time) MarshalJSON() ([]byte, error) {
return []byte(strconv.FormatInt(time.Time(t).Unix(), 10)), nil
}
// GetID serializes and returns the event ID as a string
func (evt *Event) GetID() string {
h := sha256.Sum256(evt.Serialize())
return hex.EncodeToString(h[:])
}
// Serialize outputs a byte array that can be hashed/signed to identify/authenticate
func (evt *Event) Serialize() []byte {
// the serialization process is just putting everything into a JSON array

34
event_test.go Normal file
View File

@ -0,0 +1,34 @@
package nostr
import (
"encoding/json"
"testing"
)
func TestEventParsingAndVerifying(t *testing.T) {
raw := `{"id":"dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962","pubkey":"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d","created_at":1644271588,"kind":1,"tags":[],"content":"now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?","sig":"230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524"}`
var ev Event
err := json.Unmarshal([]byte(raw), &ev)
if err != nil {
t.Errorf("failed to parse event json: %w", err)
}
if ev.GetID() != ev.ID {
t.Errorf("error serializing event id: %s != %s", ev.GetID(), ev.ID)
}
if ok, _ := ev.CheckSignature(); !ok {
t.Error("signature verification failed when it should have succeeded")
}
asjson, err := json.Marshal(ev)
if err != nil {
t.Errorf("failed to re marshal event as json: %w", err)
}
if string(asjson) != raw {
t.Log(string(asjson))
t.Error("json serialization broken")
}
}

105
filter_test.go Normal file
View File

@ -0,0 +1,105 @@
package nostr
import (
"encoding/json"
"testing"
"time"
)
func TestFilterUnmarshal(t *testing.T) {
raw := `{"ids": ["abc"],"#e":["zzz"],"#something":["nothing","bab"],"since":1644254609}`
var f Filter
err := json.Unmarshal([]byte(raw), &f)
if err != nil {
t.Errorf("failed to parse filter json: %w", err)
}
if f.Since == nil || f.Since.Format("2006-01-02") != "2022-02-07" ||
f.Until != nil ||
f.Tags == nil || len(f.Tags) != 2 || !f.Tags["something"].Contains("bab") {
t.Error("failed to parse filter correctly")
}
}
func TestFilterMarshal(t *testing.T) {
tm := time.Unix(12345678, 0)
filterj, err := json.Marshal(Filter{
Kinds: IntList{1, 2, 4},
Tags: map[string]StringList{"fruit": {"banana", "mango"}},
Until: &tm,
})
if err != nil {
t.Errorf("failed to marshal filter json: %w", err)
}
expected := `{"kinds":[1,2,4],"until":12345678,"#fruit":["banana","mango"]}`
if string(filterj) != expected {
t.Errorf("filter json was wrong: %s != %s", string(filterj), expected)
}
}
func TestFilterMatching(t *testing.T) {
if (Filter{Kinds: IntList{4, 5}}).Matches(&Event{Kind: 6}) {
t.Error("matched event that shouldn't have matched")
}
if !(Filter{Kinds: IntList{4, 5}}).Matches(&Event{Kind: 4}) {
t.Error("failed to match event by kind")
}
if !(Filter{
Kinds: IntList{4, 5},
Tags: map[string]StringList{
"p": {"ooo"},
},
IDs: StringList{"prefix"},
}).Matches(&Event{
Kind: 4,
Tags: Tags{{"p", "ooo", ",x,x,"}, {"m", "yywyw", "xxx"}},
ID: "prefix123",
}) {
t.Error("failed to match event by kind+tags+id prefix")
}
}
func TestFilterEquality(t *testing.T) {
if !FilterEqual(
Filter{Kinds: IntList{4, 5}},
Filter{Kinds: IntList{4, 5}},
) {
t.Error("kinds filters should be equal")
}
if !FilterEqual(
Filter{Kinds: IntList{4, 5}, Tags: map[string]StringList{"letter": {"a", "b"}}},
Filter{Kinds: IntList{4, 5}, Tags: map[string]StringList{"letter": {"b", "a"}}},
) {
t.Error("kind+tags filters should be equal")
}
tm := time.Now()
if !FilterEqual(
Filter{
Kinds: IntList{4, 5},
Tags: map[string]StringList{"letter": {"a", "b"}, "fruit": {"banana"}},
Since: &tm,
IDs: StringList{"aaaa", "bbbb"},
},
Filter{
Kinds: IntList{5, 4},
Tags: map[string]StringList{"letter": {"a", "b"}, "fruit": {"banana"}},
Since: &tm,
IDs: StringList{"aaaa", "bbbb"},
},
) {
t.Error("kind+2tags+since+ids filters should be equal")
}
if FilterEqual(
Filter{Kinds: IntList{1, 4, 5}},
Filter{Kinds: IntList{4, 5, 6}},
) {
t.Error("kinds filters shouldn't be equal")
}
}

4
go.mod
View File

@ -3,10 +3,10 @@ module github.com/fiatjaf/go-nostr
go 1.15
require (
github.com/btcsuite/btcd v0.20.1-beta // indirect
github.com/btcsuite/btcd v0.20.1-beta
github.com/fiatjaf/bip340 v1.1.1
github.com/gorilla/websocket v1.4.2
github.com/tyler-smith/go-bip32 v1.0.0
github.com/tyler-smith/go-bip39 v1.1.0
github.com/valyala/fastjson v1.6.3 // indirect
github.com/valyala/fastjson v1.6.3
)