From ac2350c722a36e629a0e2391adc9833afff12b68 Mon Sep 17 00:00:00 2001 From: Kay Date: Mon, 21 Aug 2023 20:17:25 +0800 Subject: [PATCH] style: using effective go and refactoring --- Makefile | 8 ++++++++ envelopes.go | 14 ++++++------- event.go | 6 +++--- log_normal.go | 1 - nip05/nip05.go | 8 +++++--- nip11/fetch.go | 4 +--- nip19/nip19.go | 10 ++++----- nip26/nip26.go | 49 ++++++++++++++++++++++++--------------------- nip26/nip26_test.go | 10 ++++----- nip42/nip42.go | 8 ++++---- nson/nson.go | 9 +++++---- nson/nson_test.go | 1 - relay.go | 5 ++--- sdk/input.go | 4 ++-- sdk/references.go | 2 +- subscription.go | 2 +- tags.go | 8 ++++++-- 17 files changed, 81 insertions(+), 68 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d4f860b --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +### Tools needed for development +devtools: + @echo "Installing devtools" + go install mvdan.cc/gofumpt@latest + +### Formatting, linting, and vetting +fmt: + gofumpt -l -w . diff --git a/envelopes.go b/envelopes.go index aa7675a..57b311f 100644 --- a/envelopes.go +++ b/envelopes.go @@ -54,8 +54,8 @@ type Envelope interface { } type EventEnvelope struct { - SubscriptionID *string - Event + SubscriptionID *string `json:"subscription_id"` + Event `json:"event"` } var ( @@ -266,9 +266,9 @@ func (v CloseEnvelope) MarshalJSON() ([]byte, error) { } type OKEnvelope struct { - EventID string - OK bool - Reason *string + EventID string `json:"event_id"` + OK bool `json:"ok"` + Reason *string `json:"reason"` } func (_ OKEnvelope) Label() string { return "OK" } @@ -307,8 +307,8 @@ func (v OKEnvelope) MarshalJSON() ([]byte, error) { } type AuthEnvelope struct { - Challenge *string - Event Event + Challenge *string `json:"challenge"` + Event Event `json:"event"` } func (_ AuthEnvelope) Label() string { return "AUTH" } diff --git a/event.go b/event.go index 74f57a1..52c2cf1 100644 --- a/event.go +++ b/event.go @@ -58,13 +58,13 @@ const ( KindApplicationSpecificData int = 30078 ) -// Event Stringer interface, just returns the raw JSON as a string +// Event Stringer interface, just returns the raw JSON as a string. func (evt Event) String() string { j, _ := easyjson.Marshal(evt) return string(j) } -// GetID serializes and returns the event ID as a string +// GetID serializes and returns the event ID as a string. func (evt *Event) GetID() string { h := sha256.Sum256(evt.Serialize()) return hex.EncodeToString(h[:]) @@ -128,7 +128,7 @@ func (evt Event) CheckSignature() (bool, error) { return sig.Verify(hash[:], pubkey), nil } -// Sign signs an event with a given privateKey +// Sign signs an event with a given privateKey. func (evt *Event) Sign(privateKey string) error { s, err := hex.DecodeString(privateKey) if err != nil { diff --git a/log_normal.go b/log_normal.go index 0e3c4af..af79930 100644 --- a/log_normal.go +++ b/log_normal.go @@ -3,5 +3,4 @@ package nostr func debugLogf(str string, args ...any) { - return } diff --git a/nip05/nip05.go b/nip05/nip05.go index 6056963..8a02e8b 100644 --- a/nip05/nip05.go +++ b/nip05/nip05.go @@ -40,7 +40,8 @@ func QueryIdentifier(ctx context.Context, fullname string) (*nostr.ProfilePointe return nil, fmt.Errorf("hostname doesn't have a dot") } - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://%s/.well-known/nostr.json?name=%s", domain, name), nil) + req, err := http.NewRequestWithContext(ctx, "GET", + fmt.Sprintf("https://%s/.well-known/nostr.json?name=%s", domain, name), nil) if err != nil { return nil, fmt.Errorf("failed to create a request: %w", err) } @@ -54,6 +55,7 @@ func QueryIdentifier(ctx context.Context, fullname string) (*nostr.ProfilePointe if err != nil { return nil, fmt.Errorf("request failed: %w", err) } + defer res.Body.Close() var result WellKnownResponse if err := json.NewDecoder(res.Body).Decode(&result); err != nil { @@ -62,12 +64,12 @@ func QueryIdentifier(ctx context.Context, fullname string) (*nostr.ProfilePointe pubkey, ok := result.Names[name] if !ok { - return nil, nil + return &nostr.ProfilePointer{}, nil } if len(pubkey) == 64 { if _, err := hex.DecodeString(pubkey); err != nil { - return nil, nil + return &nostr.ProfilePointer{}, nil } } diff --git a/nip11/fetch.go b/nip11/fetch.go index 5de7820..a79159b 100644 --- a/nip11/fetch.go +++ b/nip11/fetch.go @@ -4,15 +4,12 @@ import ( "context" "encoding/json" "fmt" - "net/http" "net/url" "strings" - "time" ) - // Fetch fetches the NIP-11 RelayInformationDocument. func Fetch(ctx context.Context, u string) (info *RelayInformationDocument, err error) { if _, ok := ctx.Deadline(); !ok { @@ -47,6 +44,7 @@ func Fetch(ctx context.Context, u string) (info *RelayInformationDocument, err e if err != nil { return nil, err } + defer resp.Body.Close() info = &RelayInformationDocument{} dec := json.NewDecoder(resp.Body) err = dec.Decode(info) diff --git a/nip19/nip19.go b/nip19/nip19.go index b66b012..74cf0a0 100644 --- a/nip19/nip19.go +++ b/nip19/nip19.go @@ -144,8 +144,8 @@ func EncodePublicKey(publicKeyHex string) (string, error) { return bech32.Encode("npub", bits5) } -func EncodeNote(eventIdHex string) (string, error) { - b, err := hex.DecodeString(eventIdHex) +func EncodeNote(eventIDHex string) (string, error) { + b, err := hex.DecodeString(eventIDHex) if err != nil { return "", fmt.Errorf("failed to decode event id hex: %w", err) } @@ -178,11 +178,11 @@ func EncodeProfile(publicKeyHex string, relays []string) (string, error) { return bech32.Encode("nprofile", bits5) } -func EncodeEvent(eventIdHex string, relays []string, author string) (string, error) { +func EncodeEvent(eventIDHex string, relays []string, author string) (string, error) { buf := &bytes.Buffer{} - id, err := hex.DecodeString(eventIdHex) + id, err := hex.DecodeString(eventIDHex) if err != nil || len(id) != 32 { - return "", fmt.Errorf("invalid id '%s': %w", eventIdHex, err) + return "", fmt.Errorf("invalid id '%s': %w", eventIDHex, err) } writeTLVEntry(buf, TLVDefault, id) diff --git a/nip26/nip26.go b/nip26/nip26.go index ca08933..6e80c11 100644 --- a/nip26/nip26.go +++ b/nip26/nip26.go @@ -55,15 +55,14 @@ func CheckDelegation(ev *nostr.Event) (ok bool, err error) { d := new(DelegationToken) if ok, err := d.Parse(ev); ok == true && (err == nil || err == NoDelegationTag) { return true, nil - } else { - return false, err } + return false, err } // Import verifies that t is NIP-26 delegation token for the given delegatee. // The returned DelegationToken object can be used in DelegatedSign. // If the token signature verification fails, the error VerificationFailed will be returned. -func Import(t nostr.Tag, delegatee_pk string) (d *DelegationToken, e error) { +func Import(t nostr.Tag, delegateePk string) (d *DelegationToken, e error) { d = new(DelegationToken) if len(t) == 4 && t[0] == "delegation" { copy(d.tag[:], t) @@ -81,16 +80,16 @@ func Import(t nostr.Tag, delegatee_pk string) (d *DelegationToken, e error) { } // compute the digest - h := sha256.Sum256([]byte(fmt.Sprintf("nostr:delegation:%s:%s", delegatee_pk, d.tag[2]))) + h := sha256.Sum256([]byte(fmt.Sprintf("nostr:delegation:%s:%s", delegateePk, d.tag[2]))) sig, err := schnorr.ParseSignature(d.token[:]) if err != nil { - return nil, fmt.Errorf("Error: %s", err.Error()) + return nil, fmt.Errorf("error: %s", err.Error()) } pubkey, err := schnorr.ParsePubKey(d.delegator[:]) if err != nil { - return nil, fmt.Errorf("Error: %s", err.Error()) + return nil, fmt.Errorf("error: %s", err.Error()) } if !sig.Verify(h[:], pubkey) { return nil, VerificationFailed @@ -131,15 +130,15 @@ jump1: goto jump2 } } - return false, fmt.Errorf("Event kind %d is not allowed in delegation conditions.", ev.Kind) + return false, fmt.Errorf("event kind %d is not allowed in delegation condition", ev.Kind) } jump2: if d.since != nil && ev.CreatedAt.Time().Before(*d.since) { - return false, fmt.Errorf("Event is created before delegation conditions allow.") + return false, fmt.Errorf("event is created before delegation conditions allow") } if d.until != nil && ev.CreatedAt.Time().After(*d.until) { - return false, fmt.Errorf("Event is created after delegation conditions allow.") + return false, fmt.Errorf("event is created after delegation conditions allow") } // compute the digest @@ -147,12 +146,12 @@ jump2: sig, err := schnorr.ParseSignature(d.token[:]) if err != nil { - return false, fmt.Errorf("Error: %s", err.Error()) + return false, fmt.Errorf("error: %s", err.Error()) } pubkey, err := schnorr.ParsePubKey(d.delegator[:]) if err != nil { - return false, fmt.Errorf("Error: %s", err.Error()) + return false, fmt.Errorf("error: %s", err.Error()) } return sig.Verify(h[:], pubkey), nil @@ -160,14 +159,16 @@ jump2: // DelegatedSign performs a delegated signature on the event ev. // The delegation signature is not verified. If desired, the caller can ensure the delegation signature is correct by calling d.Parse(ev) or CheckDelegation(ev) afterwards. -func DelegatedSign(ev *nostr.Event, d *DelegationToken, delegatee_sk string) error { +func DelegatedSign(ev *nostr.Event, + d *DelegationToken, delegateeSk string, +) error { for _, t := range ev.Tags { if t[0] == "delegation" { return fmt.Errorf("event already has delegation token") } } if d.since != nil && ev.CreatedAt.Time().Before(*d.since) || d.until != nil && ev.CreatedAt.Time().After(*d.until) { - return fmt.Errorf("event created_at field is not compatible with delegation token time conditions.") + return fmt.Errorf("event created_at field is not compatible with delegation token time conditions") } if len(d.kinds) > 0 { for _, k := range d.kinds { @@ -175,34 +176,36 @@ func DelegatedSign(ev *nostr.Event, d *DelegationToken, delegatee_sk string) err goto jump } } - return fmt.Errorf("event kind %d is not compatible with delegation token conditions.", ev.Kind) + return fmt.Errorf("event kind %d is not compatible with delegation token conditions", ev.Kind) } jump: - if pk, e := nostr.GetPublicKey(delegatee_sk); e != nil { - return fmt.Errorf("invalid delegatee secret key.") + if pk, e := nostr.GetPublicKey(delegateeSk); e != nil { + return fmt.Errorf("invalid delegatee secret key") } else { ev.PubKey = pk } ev.Tags = append(ev.Tags, d.Tag()) - return ev.Sign(delegatee_sk) + return ev.Sign(delegateeSk) } // CreateToken creates a DelegationToken according to NIP-26. -func CreateToken(delegator_sk string, delegatee_pk string, kinds []int, since *time.Time, until *time.Time) (d *DelegationToken, e error) { +func CreateToken(delegator_sk string, delegatee_pk string, kinds []int, + since *time.Time, until *time.Time, +) (d *DelegationToken, e error) { d = new(DelegationToken) s, e := hex.DecodeString(delegator_sk) if e != nil { return nil, fmt.Errorf("invalid delegator secret key") } - tee_pk, e := hex.DecodeString(delegatee_pk) - if len(tee_pk) != 32 || e != nil { + teePk, e := hex.DecodeString(delegatee_pk) + if len(teePk) != 32 || e != nil { return nil, fmt.Errorf("invalid delegatee pubkey") } // set delegator - sk, tor_pk := btcec.PrivKeyFromBytes(s) - copy(d.delegator[:], schnorr.SerializePubKey(tor_pk)) + sk, torPk := btcec.PrivKeyFromBytes(s) + copy(d.delegator[:], schnorr.SerializePubKey(torPk)) d.kinds = kinds d.since = since @@ -213,7 +216,7 @@ func CreateToken(delegator_sk string, delegatee_pk string, kinds []int, since *t d.tag[1] = fmt.Sprintf("%x", d.delegator) d.tag[2] = d.Conditions() - h := sha256.Sum256([]byte(fmt.Sprintf("nostr:delegation:%x:%s", tee_pk, d.tag[2]))) + h := sha256.Sum256([]byte(fmt.Sprintf("nostr:delegation:%x:%s", teePk, d.tag[2]))) if sig, err := schnorr.Sign(sk, h[:]); err != nil { panic(err) diff --git a/nip26/nip26_test.go b/nip26/nip26_test.go index d5e59a9..653e8c3 100644 --- a/nip26/nip26_test.go +++ b/nip26/nip26_test.go @@ -10,9 +10,9 @@ import ( func TestDelegateSign(t *testing.T) { since := time.Unix(1600000000, 0) until := time.Unix(1600000100, 0) - delegator_secret_key, delegatee_secret_key := "3f0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459da", "e9142f724955c5854de36324dab0434f97b15ec6b33464d56ebe491e3f559d1b" - delegatee_pubkey, _ := nostr.GetPublicKey(delegatee_secret_key) - d1, err := CreateToken(delegator_secret_key, delegatee_pubkey, []int{1, 2, 3}, &since, &until) + delegatorSecretKey, delegatee_secret_key := "3f0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459da", "e9142f724955c5854de36324dab0434f97b15ec6b33464d56ebe491e3f559d1b" + delegateePubkey, _ := nostr.GetPublicKey(delegatee_secret_key) + d1, err := CreateToken(delegatorSecretKey, delegateePubkey, []int{1, 2, 3}, &since, &until) if err != nil { t.Error(err) } @@ -23,7 +23,7 @@ func TestDelegateSign(t *testing.T) { if err != nil { t.Error(err) } - d2, err := Import(d1.Tag(), delegatee_pubkey) + d2, err := Import(d1.Tag(), delegateePubkey) if err != nil { t.Error(err) } @@ -36,7 +36,7 @@ func TestDelegateSign(t *testing.T) { } tag := []string{"delegation", "9ea72be3fcfe38103195a41b67b6f96c14ed92d2091d6d9eb8166a5c27b0c35d", "kind=1&kind=2&kind=3&created_at>1600000000", "8432b8c86f789c2783ef3becb0fabf4def6031c6a615fa7a622f31329d80ed1b2a79ab753c0462f1440503c94e1829158a3a854a1d418ad256ae2cf8aa19fa9a"} - d3, err := Import(tag, delegatee_pubkey) + d3, err := Import(tag, delegateePubkey) if err != nil { t.Error(err) } diff --git a/nip42/nip42.go b/nip42/nip42.go index 9fd8d3e..a430874 100644 --- a/nip42/nip42.go +++ b/nip42/nip42.go @@ -23,8 +23,8 @@ func CreateUnsignedAuthEvent(challenge, pubkey, relayURL string) nostr.Event { } } -// helper function for ValidateAuthEvent -func parseUrl(input string) (*url.URL, error) { +// helper function for ValidateAuthEvent. +func parseURL(input string) (*url.URL, error) { return url.Parse( strings.ToLower( strings.TrimSuffix(input, "/"), @@ -43,12 +43,12 @@ func ValidateAuthEvent(event *nostr.Event, challenge string, relayURL string) (p return "", false } - expected, err := parseUrl(relayURL) + expected, err := parseURL(relayURL) if err != nil { return "", false } - found, err := parseUrl(event.Tags.GetFirst([]string{"relay", ""}).Value()) + found, err := parseURL(event.Tags.GetFirst([]string{"relay", ""}).Value()) if err != nil { return "", false } diff --git a/nson/nson.go b/nson/nson.go index 03e9fa5..daa1f93 100644 --- a/nson/nson.go +++ b/nson/nson.go @@ -43,13 +43,13 @@ const ( NSON_MARKER_END = 317 // it's just the `,"nson":` (including ,": garbage to reduce false positives) part ) -var NotNSON = fmt.Errorf("not nson") +var ErrNotNSON = fmt.Errorf("not nson") func UnmarshalBytes(data []byte, evt *nostr.Event) (err error) { return Unmarshal(unsafe.String(unsafe.SliceData(data), len(data)), evt) } -// Unmarshal turns a NSON string into a nostr.Event struct +// Unmarshal turns a NSON string into a nostr.Event struct. func Unmarshal(data string, evt *nostr.Event) (err error) { defer func() { if r := recover(); r != nil { @@ -59,7 +59,7 @@ func Unmarshal(data string, evt *nostr.Event) (err error) { // check if it's nson if data[NSON_MARKER_START:NSON_MARKER_END] != ",\"nson\":" { - return NotNSON + return ErrNotNSON } // nson values @@ -168,7 +168,8 @@ func Marshal(evt *nostr.Event) (string, error) { 9 + tagBuilder.Len() + // tags and its label 2, // the end ) - base.WriteString(`{"id":"` + evt.ID + `","pubkey":"` + evt.PubKey + `","sig":"` + evt.Sig + `","created_at":` + strconv.FormatInt(int64(evt.CreatedAt), 10) + `,"nson":"`) + base.WriteString(`{"id":"` + evt.ID + `","pubkey":"` + evt.PubKey + `","sig":"` + evt.Sig + + `","created_at":` + strconv.FormatInt(int64(evt.CreatedAt), 10) + `,"nson":"`) nsonSizeBytes := len(nsonBuf) if nsonSizeBytes > 255 { diff --git a/nson/nson_test.go b/nson/nson_test.go index 24cfc45..0915515 100644 --- a/nson/nson_test.go +++ b/nson/nson_test.go @@ -72,7 +72,6 @@ func checkParsedCorrectly(t *testing.T, evt *nostr.Event, jevt string) (isBad bo err := json.Unmarshal([]byte(jevt), &canonical) if err != nil { t.Fatalf("error unmarshaling normal json: %s", err) - return } if evt.ID != canonical.ID { diff --git a/relay.go b/relay.go index 57ee75d..cb4c2b8 100644 --- a/relay.go +++ b/relay.go @@ -23,7 +23,7 @@ const ( PublishStatusSucceeded Status = 1 ) -var subscriptionIdCounter atomic.Int32 +var subscriptionIDCounter atomic.Int32 func (s Status) String() string { switch s { @@ -204,7 +204,6 @@ func (r *Relay) Connect(ctx context.Context) error { go sub.Unsub() return true }) - return }() // queue all write operations here so we don't do mutex spaghetti @@ -479,7 +478,7 @@ func (r *Relay) PrepareSubscription(ctx context.Context, filters Filters, opts . panic(fmt.Errorf("must call .Connect() first before calling .Subscribe()")) } - current := subscriptionIdCounter.Add(1) + current := subscriptionIDCounter.Add(1) ctx, cancel := context.WithCancel(ctx) sub := &Subscription{ diff --git a/sdk/input.go b/sdk/input.go index 7aa21fb..81bb587 100644 --- a/sdk/input.go +++ b/sdk/input.go @@ -9,7 +9,7 @@ import ( "github.com/nbd-wtf/go-nostr/nip19" ) -// InputToProfile turns any npub/nprofile/hex/nip05 input into a ProfilePointer (or nil) +// InputToProfile turns any npub/nprofile/hex/nip05 input into a ProfilePointer (or nil). func InputToProfile(ctx context.Context, input string) *nostr.ProfilePointer { // handle if it is a hex string if len(input) == 64 { @@ -38,7 +38,7 @@ func InputToProfile(ctx context.Context, input string) *nostr.ProfilePointer { return nil } -// InputToEventPointer turns any note/nevent/hex input into a EventPointer (or nil) +// InputToEventPointer turns any note/nevent/hex input into a EventPointer (or nil). func InputToEventPointer(input string) *nostr.EventPointer { // handle if it is a hex string if len(input) == 64 { diff --git a/sdk/references.go b/sdk/references.go index 72f3724..3c73be5 100644 --- a/sdk/references.go +++ b/sdk/references.go @@ -33,7 +33,7 @@ func ParseReferences(evt *nostr.Event) []*Reference { } if ref[6] == -1 { - // didn't find a NIP-10 #[0] reference, so it's it's a NIP-27 mention + // didn't find a NIP-10 #[0] reference, so it's a NIP-27 mention nip19code := content[ref[2]:ref[3]] if prefix, data, err := nip19.Decode(nip19code); err == nil { diff --git a/subscription.go b/subscription.go index 9a3f413..381de5d 100644 --- a/subscription.go +++ b/subscription.go @@ -117,7 +117,7 @@ func (sub *Subscription) Close() { // Sub sets sub.Filters and then calls sub.Fire(ctx). // The subscription will be closed if the context expires. -func (sub *Subscription) Sub(ctx context.Context, filters Filters) { +func (sub *Subscription) Sub(_ context.Context, filters Filters) { sub.Filters = filters sub.Fire() } diff --git a/tags.go b/tags.go index 4a3f0ff..56849f3 100644 --- a/tags.go +++ b/tags.go @@ -12,10 +12,15 @@ type Tag []string // StartsWith checks if a tag contains a prefix. // for example, +// // ["p", "abcdef...", "wss://relay.com"] +// // would match against +// // ["p", "abcdef..."] +// // or even +// // ["p", "abcdef...", "wss://"] func (tag Tag) StartsWith(prefix []string) bool { prefixLen := len(prefix) @@ -109,9 +114,8 @@ func (tags Tags) AppendUnique(tag Tag) Tags { if tags.GetFirst(tag[:n]) == nil { return append(tags, tag) - } else { - return tags } + return tags } func (t *Tags) Scan(src any) error {