Skip to content

Commit

Permalink
fix: review fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
frnandu committed Oct 21, 2024
1 parent dc404dd commit b145c41
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 108 deletions.
2 changes: 1 addition & 1 deletion alby/alby_oauth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.
scopes,
false,
nil,
svc.keys.GetBIP32ChildKey,
svc.keys.GetAppWalletKey,
)

if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
createAppRequest.Scopes,
createAppRequest.Isolated,
createAppRequest.Metadata,
api.svc.GetKeys().GetBIP32ChildKey,
api.svc.GetKeys().GetAppWalletKey,
)

if err != nil {
Expand All @@ -105,7 +105,7 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
if err == nil {
query := returnToUrl.Query()
query.Add("relay", relayUrl)
query.Add("pubkey", app.WalletChildPubkey)
query.Add("pubkey", app.WalletPubkey)
if lightningAddress != "" && !app.Isolated {
query.Add("lud16", lightningAddress)
}
Expand All @@ -118,7 +118,7 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
if lightningAddress != "" && !app.Isolated {
lud16 = fmt.Sprintf("&lud16=%s", lightningAddress)
}
responseBody.PairingUri = fmt.Sprintf("nostr+walletconnect://%s?relay=%s&secret=%s%s", app.WalletChildPubkey, relayUrl, pairingSecretKey, lud16)
responseBody.PairingUri = fmt.Sprintf("nostr+walletconnect://%s?relay=%s&secret=%s%s", app.WalletPubkey, relayUrl, pairingSecretKey, lud16)

return responseBody, nil
}
Expand Down
18 changes: 9 additions & 9 deletions db/db_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,17 @@ func (svc *dbService) CreateApp(
}
}

appWalletChildPrivKey, err := walletChildPrivKeyGeneratorFunc(uint32(app.ID))
appWalletPrivKey, err := walletChildPrivKeyGeneratorFunc(uint32(app.ID))
if err != nil {
return fmt.Errorf("error generating wallet child private key: %w", err)
}

app.WalletChildPubkey, err = nostr.GetPublicKey(appWalletChildPrivKey)
app.WalletPubkey, err = nostr.GetPublicKey(appWalletPrivKey)
if err != nil {
return fmt.Errorf("error generating wallet child public key: %w", err)
}

err = tx.Model(&App{}).Where("id", app.ID).Update("wallet_child_pubkey", app.WalletChildPubkey).Error
err = tx.Model(&App{}).Where("id", app.ID).Update("wallet_pubkey", app.WalletPubkey).Error
if err != nil {
return err
}
Expand All @@ -119,9 +119,9 @@ func (svc *dbService) CreateApp(
svc.eventPublisher.Publish(&events.Event{
Event: "app_created",
Properties: map[string]interface{}{
"name": name,
"id": app.ID,
"walletChildPubkey": app.WalletChildPubkey,
"name": name,
"id": app.ID,
"walletPubkey": app.WalletPubkey,
},
})

Expand All @@ -137,9 +137,9 @@ func (svc *dbService) DeleteApp(app *App) error {
svc.eventPublisher.Publish(&events.Event{
Event: "app_deleted",
Properties: map[string]interface{}{
"name": app.Name,
"id": app.ID,
"walletChildPubkey": app.WalletChildPubkey,
"name": app.Name,
"id": app.ID,
"walletPubkey": app.WalletPubkey,
},
})
return nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
"gorm.io/gorm"
)

var _202410141503_wallet_child_pubkey = &gormigrate.Migration{
ID: "202410141503_wallet_child_pubkey",
var _202410141503_add_wallet_pubkey = &gormigrate.Migration{
ID: "202410141503_add_wallet_pubkey",
Migrate: func(tx *gorm.DB) error {

if err := tx.Exec(`
ALTER TABLE apps ADD COLUMN wallet_child_pubkey TEXT;
ALTER TABLE apps ADD COLUMN wallet_pubkey TEXT;
`).Error; err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion db/migrations/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func Migrate(gormDB *gorm.DB) error {
_202408061737_add_boostagrams_and_use_json,
_202408191242_transaction_failure_reason,
_202408291715_app_metadata,
_202410141503_wallet_child_pubkey,
_202410141503_add_wallet_pubkey,
})

return m.Migrate()
Expand Down
18 changes: 9 additions & 9 deletions db/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ type UserConfig struct {
}

type App struct {
ID uint
Name string `validate:"required"`
Description string
NostrPubkey string `validate:"required"`
WalletChildPubkey string
CreatedAt time.Time
UpdatedAt time.Time
Isolated bool
Metadata datatypes.JSON
ID uint
Name string `validate:"required"`
Description string
NostrPubkey string `validate:"required"`
WalletPubkey string
CreatedAt time.Time
UpdatedAt time.Time
Isolated bool
Metadata datatypes.JSON
}

type AppPermission struct {
Expand Down
15 changes: 2 additions & 13 deletions nip47/event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
}).Error("invalid event signature")
return
}
pTag := event.Tags.GetFirst([]string{"p"})
if pTag == nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
"eventKind": event.Kind,
}).Error("invalid event, missing p tag")
return
}

ss, err := nip04.ComputeSharedSecret(event.PubKey, svc.keys.GetNostrSecretKey())
if err != nil {
logger.Logger.WithFields(logrus.Fields{
Expand Down Expand Up @@ -93,18 +84,16 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
svc.publishResponseEvent(ctx, relay, &requestEvent, resp, nil)
return
}
appWalletPubKey := pTag.Value()

app := db.App{}
err = svc.db.First(&app, &db.App{
NostrPubkey: event.PubKey,
}).Error

appWalletPrivKey := svc.keys.GetNostrSecretKey()

if appWalletPubKey != svc.keys.GetNostrPublicKey() {
if app.WalletPubkey != "" {
// This is a new child key derived from master using app ID as index
appWalletPrivKey, err = svc.keys.GetBIP32ChildKey(uint32(app.ID))
appWalletPrivKey, err = svc.keys.GetAppWalletKey(uint32(app.ID))
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"appId": app.ID,
Expand Down
4 changes: 2 additions & 2 deletions nip47/notifications/nip47_notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ func (notifier *Nip47Notifier) notifySubscriber(ctx context.Context, app *db.App
}).Debug("Notifying subscriber")

appWalletPrivKey := notifier.keys.GetNostrSecretKey()
if app.WalletChildPubkey != "" {
appWalletPrivKey, _ = notifier.keys.GetBIP32ChildKey(uint32(app.ID))
if app.WalletPubkey != "" {
appWalletPrivKey, _ = notifier.keys.GetAppWalletKey(uint32(app.ID))
}

ss, err := nip04.ComputeSharedSecret(app.NostrPubkey, appWalletPrivKey)
Expand Down
6 changes: 3 additions & 3 deletions service/keys/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ type Keys interface {
GetNostrPublicKey() string
// Wallet Service Nostr secret key
GetNostrSecretKey() string
// GetBIP32ChildKey derives a BIP32 child key from the nostrSecretKey given a child key index
GetBIP32ChildKey(childIndex uint32) (string, error)
// Derives a BIP32 child key from the nostrSecretKey given a child key index
GetAppWalletKey(childIndex uint32) (string, error)
}

type keys struct {
Expand Down Expand Up @@ -58,7 +58,7 @@ func (keys *keys) GetNostrSecretKey() string {
return keys.nostrSecretKey
}

func (keys *keys) GetBIP32ChildKey(childIndex uint32) (string, error) {
func (keys *keys) GetAppWalletKey(childIndex uint32) (string, error) {
// Convert nostrSecretKey to btcec private key
privKeyBytes, err := hex.DecodeString(keys.nostrSecretKey)
if err != nil {
Expand Down
123 changes: 59 additions & 64 deletions service/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,84 +122,87 @@ type createAppSubscriber struct {
}

func (s *createAppSubscriber) ConsumeEvent(ctx context.Context, event *events.Event, globalProperties map[string]interface{}) {
switch event.Event {
case "app_created":
properties, ok := event.Properties.(map[string]interface{})
if !ok {
logger.Logger.WithField("event", event).Error("Failed to cast event.Properties to map")
return
}
walletChildPubkey, ok := properties["walletChildPubkey"].(string)
if !ok {
logger.Logger.WithField("event", event).Error("Failed to get app walletChildPubkey")
return
}
id, ok := properties["id"].(uint)
if !ok {
logger.Logger.WithField("event", event).Error("Failed to get app id")
return
}
if walletChildPubkey != "" {
go func() {
appWalletPrivKey, err := s.svc.keys.GetBIP32ChildKey(uint32(id))
if err != nil {
logger.Logger.WithError(err).Error("Failed to calculate app wallet priv key")
}
err = s.svc.startAppWalletSubscription(ctx, s.relay, walletChildPubkey, appWalletPrivKey)
if err != nil {
logger.Logger.WithError(err).Error("Failed to subscribe to wallet")
}
// TODO what should we do?
}()
}
if event.Event != "app_created" {
return
}
properties, ok := event.Properties.(map[string]interface{})
if !ok {
logger.Logger.WithField("event", event).Error("Failed to cast event.Properties to map")
return
}
walletPubkey, ok := properties["walletPubkey"].(string)
if !ok {
logger.Logger.WithField("event", event).Error("Failed to get app walletPubkey")
return
}
id, ok := properties["id"].(uint)
if !ok {
logger.Logger.WithField("event", event).Error("Failed to get app id")
return
}
if walletPubkey != "" {
go func() {
walletPrivkey, err := s.svc.keys.GetAppWalletKey(uint32(id))
if err != nil {
logger.Logger.WithError(err).Error("Failed to calculate app wallet priv key")
}
err = s.svc.startAppWalletSubscription(ctx, s.relay, walletPubkey, walletPrivkey)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"app_id": id}).Error("Failed to subscribe to wallet")
}
logger.Logger.WithFields(logrus.Fields{
"app_id": id}).Info("App Nostr Subscription ended")
}()
}
}

type deleteAppSubscriber struct {
events.EventSubscriber
walletChildPubkey string
walletPubkey string
relay *nostr.Relay
nostrSubscription *nostr.Subscription
svc *service
infoEventId string
}

func (s *deleteAppSubscriber) ConsumeEvent(ctx context.Context, event *events.Event, globalProperties map[string]interface{}) {
switch event.Event {
case "app_deleted":
properties, ok := event.Properties.(map[string]interface{})
if !ok {
logger.Logger.WithField("event", event).Error("Failed to cast event.Properties to map")
return
}
if event.Event != "app_deleted" {
return
}
properties, ok := event.Properties.(map[string]interface{})
if !ok {
logger.Logger.WithField("event", event).Error("Failed to cast event.Properties to map")
return
}

walletChildPubkey, ok := properties["walletChildPubkey"].(string)
if s.walletChildPubkey == walletChildPubkey {
id, _ := properties["id"].(uint)
s.nostrSubscription.Unsub()
appWalletPrivKey, _ := s.svc.keys.GetBIP32ChildKey(uint32(id))
err := s.svc.nip47Service.PublishNip47InfoDeletion(ctx, s.relay, walletChildPubkey, appWalletPrivKey, s.infoEventId)
if err != nil {
logger.Logger.WithField("event", event).Error("Failed to publish nip47 info deletion")
}
walletChildPubkey, ok := properties["walletPubkey"].(string)
if s.walletPubkey == walletChildPubkey {
id, _ := properties["id"].(uint)
s.nostrSubscription.Unsub()
appWalletPrivKey, _ := s.svc.keys.GetAppWalletKey(uint32(id))
err := s.svc.nip47Service.PublishNip47InfoDeletion(ctx, s.relay, walletChildPubkey, appWalletPrivKey, s.infoEventId)
if err != nil {
logger.Logger.WithField("event", event).Error("Failed to publish nip47 info deletion")
}
}
}

func (svc *service) startAllExistingAppsWalletSubscriptions(ctx context.Context, relay *nostr.Relay) {
var apps []db.App
result := svc.db.Where("wallet_child_pubkey != ?", "").Find(&apps)
result := svc.db.Where("wallet_pubkey != ?", "").Find(&apps)
if result.Error != nil {
logger.Logger.WithError(result.Error).Error("Failed to fetch App records with non-empty WalletChildPubkey")
logger.Logger.WithError(result.Error).Error("Failed to fetch App records with non-empty WalletPubkey")
return
}

for _, app := range apps {
go func(app db.App) {
if app.WalletChildPubkey != "" {
err := svc.startAppWalletSubscription(ctx, relay, app.WalletChildPubkey, "")
if app.WalletPubkey != "" {
err := svc.startAppWalletSubscription(ctx, relay, app.WalletPubkey, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to subscribe to wallet")
logger.Logger.WithError(err).WithFields(logrus.Fields{
"app_id": app.ID}).Error("Failed to subscribe to wallet")
}
}
}(app)
Expand All @@ -216,13 +219,14 @@ func (svc *service) startAppWalletSubscription(ctx context.Context, relay *nostr
infoEventId = infoEvent.ID
}

sub, err := svc.subscribeToRequests(ctx, relay, appWalletPubKey)
logger.Logger.Info("Subscribing to events for wallet ", appWalletPubKey)
sub, err := relay.Subscribe(ctx, svc.createFilters(appWalletPubKey))
if err != nil {
logger.Logger.WithError(err).Error("Failed to subscribe to app requests")
logger.Logger.WithError(err).Error("Failed to subscribe to events")
}

// register a subscriber for "app_deleted" events, which handles nostr subscription cancel and nip47 info event deletion
svc.eventPublisher.RegisterSubscriber(&deleteAppSubscriber{nostrSubscription: sub, walletChildPubkey: appWalletPubKey, svc: svc, relay: relay, infoEventId: infoEventId})
svc.eventPublisher.RegisterSubscriber(&deleteAppSubscriber{nostrSubscription: sub, walletPubkey: appWalletPubKey, svc: svc, relay: relay, infoEventId: infoEventId})

err = svc.StartSubscription(sub.Context, sub)
if err != nil {
Expand All @@ -232,15 +236,6 @@ func (svc *service) startAppWalletSubscription(ctx context.Context, relay *nostr
return nil
}

func (svc *service) subscribeToRequests(ctx context.Context, relay *nostr.Relay, appWalletPubKey string) (*nostr.Subscription, error) {
logger.Logger.Info("Subscribing to events for wallet ", appWalletPubKey)
sub, err := relay.Subscribe(ctx, svc.createFilters(appWalletPubKey))
if err != nil {
logger.Logger.WithError(err).Error("Failed to subscribe to events")
}
return sub, nil
}

func (svc *service) StartApp(encryptionKey string) error {
if svc.lnClient != nil {
return errors.New("app already started")
Expand Down

0 comments on commit b145c41

Please sign in to comment.