diff --git a/nip46/bunker_session.go b/nip46/bunker_session.go index 0089813..ffcf698 100644 --- a/nip46/bunker_session.go +++ b/nip46/bunker_session.go @@ -1,7 +1,9 @@ package nip46 import ( + "errors" "fmt" + "slices" "fiatjaf.com/nostr" "fiatjaf.com/nostr/nip44" @@ -10,6 +12,9 @@ import ( type Session struct { PublicKey nostr.PubKey ConversationKey [32]byte + + duplicatesBuf [6]string + serial int } type RelayReadWrite struct { @@ -17,7 +22,9 @@ type RelayReadWrite struct { Write bool `json:"write"` } -func (s Session) ParseRequest(event nostr.Event) (Request, error) { +var AlreadyHandled = errors.New("already handled this request") + +func (s *Session) ParseRequest(event nostr.Event) (Request, error) { var req Request plain, err := nip44.Decrypt(event.Content, s.ConversationKey) @@ -26,6 +33,15 @@ func (s Session) ParseRequest(event nostr.Event) (Request, error) { } err = json.Unmarshal([]byte(plain), &req) + + // discard duplicates + if slices.Contains(s.duplicatesBuf[:], req.ID) { + return req, AlreadyHandled + } + + s.duplicatesBuf[s.serial%len(s.duplicatesBuf)] = req.ID + s.serial++ + return req, err } diff --git a/nip46/dynamic-signer.go b/nip46/dynamic-signer.go index 8b8fca6..8c5683b 100644 --- a/nip46/dynamic-signer.go +++ b/nip46/dynamic-signer.go @@ -14,7 +14,7 @@ var _ Signer = (*DynamicSigner)(nil) type DynamicSigner struct { // { [handlePubkey]: {[clientKey]: Session} } - sessions map[nostr.PubKey]map[nostr.PubKey]Session + sessions map[nostr.PubKey]map[nostr.PubKey]*Session // used for switch_relays call DefaultRelays []string @@ -47,7 +47,7 @@ type DynamicSigner struct { } func (p *DynamicSigner) Init() { - p.sessions = make(map[nostr.PubKey]map[nostr.PubKey]Session) + p.sessions = make(map[nostr.PubKey]map[nostr.PubKey]*Session) } func (p *DynamicSigner) HandleRequest(ctx context.Context, event nostr.Event) ( @@ -85,14 +85,14 @@ func (p *DynamicSigner) HandleRequest(ctx context.Context, event nostr.Event) ( handlerSessions, exists := p.sessions[handlerPubkey] if !exists { - handlerSessions = make(map[nostr.PubKey]Session) + handlerSessions = make(map[nostr.PubKey]*Session) p.sessions[handlerPubkey] = handlerSessions } session, exists := handlerSessions[event.PubKey] if !exists { // create session if it doesn't exist - session = Session{} + session = &Session{} session.ConversationKey, err = nip44.GenerateConversationKey(event.PubKey, handlerSecret) if err != nil { diff --git a/nip46/static-key-signer.go b/nip46/static-key-signer.go index 560e385..0aae6dc 100644 --- a/nip46/static-key-signer.go +++ b/nip46/static-key-signer.go @@ -15,8 +15,8 @@ import ( var _ Signer = (*StaticKeySigner)(nil) type StaticKeySigner struct { - secretKey [32]byte - sessions map[nostr.PubKey]Session + secretKey nostr.SecretKey + sessions map[nostr.PubKey]*Session sync.Mutex @@ -29,11 +29,11 @@ type StaticKeySigner struct { func NewStaticKeySigner(secretKey [32]byte) StaticKeySigner { return StaticKeySigner{ secretKey: secretKey, - sessions: make(map[nostr.PubKey]Session), + sessions: make(map[nostr.PubKey]*Session), } } -func (p *StaticKeySigner) getOrCreateSession(clientPubkey nostr.PubKey) (Session, error) { +func (p *StaticKeySigner) getOrCreateSession(clientPubkey nostr.PubKey) (*Session, error) { p.Lock() defer p.Unlock() @@ -44,17 +44,16 @@ func (p *StaticKeySigner) getOrCreateSession(clientPubkey nostr.PubKey) (Session ck, err := nip44.GenerateConversationKey(clientPubkey, p.secretKey) if err != nil { - return Session{}, fmt.Errorf("failed to compute shared secret: %w", err) + return nil, fmt.Errorf("failed to compute shared secret: %w", err) } - pubkey := nostr.GetPublicKey(p.secretKey) - session = Session{ - PublicKey: pubkey, + session = &Session{ + PublicKey: p.secretKey.Public(), ConversationKey: ck, } // add to pool - p.sessions[pubkey] = session + p.sessions[clientPubkey] = session return session, nil }