Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: app child key derived from wallet master key #736

Merged
merged 55 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
83de003
feat(appwalletKey): add GetBIP32ChildKey
frnandu Oct 14, 2024
546322c
feat: fix interface
frnandu Oct 14, 2024
8cbe566
feat: adding subscription WiP
frnandu Oct 15, 2024
853beed
feat: handle nostr subscriptions for lifecycle of apps
frnandu Oct 18, 2024
8cb135d
Delete .idea/.gitignore
frnandu Oct 18, 2024
616a69b
Delete .idea/hub.iml
frnandu Oct 18, 2024
55113ce
Delete .idea/modules.xml
frnandu Oct 18, 2024
78c2faa
Delete .idea/vcs.xml
frnandu Oct 18, 2024
e7ae82c
fix: remove unnecessary
frnandu Oct 18, 2024
dc404dd
fix: missing handling legacy app
frnandu Oct 18, 2024
b145c41
fix: review fixes
frnandu Oct 21, 2024
23b35c8
fix: use app.ID for key calculation instead of passing in event
frnandu Oct 21, 2024
b64c8cf
fix: add TODO
frnandu Oct 21, 2024
d0b0354
fix: remove unnecessary check
frnandu Oct 25, 2024
0c5949c
fix: improve err handling and remove check
frnandu Oct 25, 2024
324f113
Merge remote-tracking branch 'origin/master' into feat/wallet-child-k…
rolznz Oct 28, 2024
b4d1f3e
chore: store master nostr key to avoid deriving each time
rolznz Oct 29, 2024
a1dc936
chore: rename app nostr_pubkey to app_pubkey, extract app consumers i…
rolznz Oct 29, 2024
bedc82d
chore: finish renaming
rolznz Oct 29, 2024
200c172
fix: update app wallet pubkey on app creation
rolznz Oct 29, 2024
aef3142
fix: not NULL check
rolznz Oct 29, 2024
96a71bc
fix: fix HandleEvent
frnandu Oct 29, 2024
b359339
fix: error handling
frnandu Oct 29, 2024
aa2c3c1
fix: error handling
frnandu Oct 29, 2024
9f69b1a
fix: move StartSubscription to start.go
frnandu Oct 29, 2024
0d61bb2
fix: remove duplicated error check
frnandu Oct 29, 2024
b530632
fix: make tests use AppsService for creating apps
frnandu Oct 29, 2024
d4c6a60
chore: remove unused code
rolznz Oct 29, 2024
63c3fd9
chore: minor event handler improvements
rolznz Oct 29, 2024
1d79b8a
fix: add event_handler tests for legacy app
frnandu Oct 29, 2024
55d9515
chore: add comment about legacy apps in deleteAppConsumer
rolznz Oct 29, 2024
b1bcc58
Merge branch 'feat/wallet-child-key-per-connection' of github.com:get…
rolznz Oct 29, 2024
c56d1d1
fix: remove unused app from tests
rolznz Oct 29, 2024
bc923eb
fix: error handling in startAppWalletSubscription
rolznz Oct 29, 2024
606fb32
fix: only create event info and nostr subscription for master key if …
frnandu Oct 30, 2024
932a9fb
fix: add legacy tests
frnandu Oct 31, 2024
17c9c0b
fix: move fetching of Nip47 event info to deleteAppConsumer
frnandu Oct 31, 2024
8127fea
fix: fixed arguments
frnandu Oct 31, 2024
7cff2a7
fix: use require instead of assert
frnandu Nov 1, 2024
339d420
Merge branch 'master' into feat/wallet-child-key-per-connection
frnandu Nov 1, 2024
606c33b
fix: adapt GetAppWalletKey to use DeriveKey with path 1'
frnandu Nov 1, 2024
877509e
fix: for backends that don't use a mnemonic, create appKey from nostr…
frnandu Nov 4, 2024
c47d923
fix: cleanup eventPublisher Subscribers when relay reconnects
frnandu Nov 4, 2024
7bfd140
fix: bip32.FirstHardenedChild + appID
frnandu Nov 6, 2024
ce4c5cf
fix: remove unused env vars
frnandu Nov 6, 2024
8c1ef4b
fix: generate new mnemonic if empty
frnandu Nov 6, 2024
aea59f0
fix: add tests.CreateTestServiceWithMnemonic to fix TestEncryptedBackup
frnandu Nov 6, 2024
78f59bc
fix: handle both relay and main ctx Done
frnandu Nov 6, 2024
b322f4c
Merge branch 'master' into feat/wallet-child-key-per-connection
rolznz Nov 7, 2024
b4bf53f
chore: add keys tests
rolznz Nov 7, 2024
caed3b3
chore: add extra assertions to keys test
rolznz Nov 7, 2024
2b14d3c
chore: log when legacy app subscription is created
rolznz Nov 7, 2024
dc54213
chore: remove unnecessary break
rolznz Nov 7, 2024
0be7e32
chore: add log when relay is successfully connected
rolznz Nov 7, 2024
287607d
fix: only auto-start node if it has been started before
rolznz Nov 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions alby/alby_oauth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ func (svc *albyOAuthService) LinkAccount(ctx context.Context, lnClient lnclient.
scopes,
false,
nil,
svc.keys.GetAppWalletKey,
)

if err != nil {
Expand Down
11 changes: 7 additions & 4 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
expiresAt,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up issue: The expiresAt, scopes checks above are to be shifted to CreateApp method in apps_service and UpdateApp, GetApp, ListApps, TopupIsolatedApp methods need to be added there. I think we can also GetAppByPubkey directly in those methods so we don't have to call it separately in http_service and wails_service

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@im-adithya could you create an issue and link some code?

createAppRequest.Scopes,
createAppRequest.Isolated,
createAppRequest.Metadata)
createAppRequest.Metadata,
api.svc.GetKeys().GetAppWalletKey,
)

if err != nil {
return nil, err
Expand All @@ -103,7 +105,7 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
if err == nil {
query := returnToUrl.Query()
query.Add("relay", relayUrl)
query.Add("pubkey", api.keys.GetNostrPublicKey())
query.Add("pubkey", app.WalletPubkey)
if lightningAddress != "" && !app.Isolated {
query.Add("lud16", lightningAddress)
}
Expand All @@ -116,7 +118,8 @@ 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", api.keys.GetNostrPublicKey(), 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 Expand Up @@ -215,7 +218,7 @@ func (api *api) UpdateApp(userApp *db.App, updateAppRequest *UpdateAppRequest) e
}

func (api *api) DeleteApp(userApp *db.App) error {
return api.db.Delete(userApp).Error
return api.dbSvc.DeleteApp(userApp)
}

func (api *api) GetApp(dbApp *db.App) *App {
Expand Down
44 changes: 43 additions & 1 deletion db/db_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,17 @@ func NewDBService(db *gorm.DB, eventPublisher events.EventPublisher) *dbService
}
}

func (svc *dbService) CreateApp(name string, pubkey string, maxAmountSat uint64, budgetRenewal string, expiresAt *time.Time, scopes []string, isolated bool, metadata map[string]interface{}) (*App, string, error) {
func (svc *dbService) CreateApp(
name string,
pubkey string,
maxAmountSat uint64,
budgetRenewal string,
expiresAt *time.Time,
scopes []string,
isolated bool,
metadata map[string]interface{},
walletChildPrivKeyGeneratorFunc func(appId uint32) (string, error),
rolznz marked this conversation as resolved.
Show resolved Hide resolved
) (*App, string, error) {
if isolated && (slices.Contains(scopes, constants.SIGN_MESSAGE_SCOPE)) {
// cannot sign messages because the isolated app is a custodial subaccount
return nil, "", errors.New("isolated app cannot have sign_message scope")
Expand Down Expand Up @@ -82,6 +92,21 @@ func (svc *dbService) CreateApp(name string, pubkey string, maxAmountSat uint64,
}
}

appWalletPrivKey, err := walletChildPrivKeyGeneratorFunc(uint32(app.ID))
frnandu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return fmt.Errorf("error generating wallet child private key: %w", err)
}

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_pubkey", app.WalletPubkey).Error
if err != nil {
return err
}

// commit transaction
return nil
})
Expand All @@ -95,8 +120,25 @@ func (svc *dbService) CreateApp(name string, pubkey string, maxAmountSat uint64,
Event: "app_created",
Properties: map[string]interface{}{
"name": name,
"id": app.ID,
},
})

return &app, pairingSecretKey, nil
}

func (svc *dbService) DeleteApp(app *App) error {

err := svc.db.Delete(app).Error
if err != nil {
return err
}
svc.eventPublisher.Publish(&events.Event{
Event: "app_deleted",
Properties: map[string]interface{}{
"name": app.Name,
"id": app.ID,
},
})
return nil
}
25 changes: 25 additions & 0 deletions db/migrations/202410141503_add_wallet_pubkey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package migrations

import (
_ "embed"

"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)

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_pubkey TEXT;
`).Error; err != nil {
return err
}

return nil
},
Rollback: func(tx *gorm.DB) error {
return nil
},
}
1 change: 1 addition & 0 deletions db/migrations/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func Migrate(gormDB *gorm.DB) error {
_202408061737_add_boostagrams_and_use_json,
_202408191242_transaction_failure_reason,
_202408291715_app_metadata,
_202410141503_add_wallet_pubkey,
})

return m.Migrate()
Expand Down
15 changes: 9 additions & 6 deletions db/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ type App struct {
ID uint
Name string `validate:"required"`
Description string
NostrPubkey string `validate:"required"`
CreatedAt time.Time
UpdatedAt time.Time
Isolated bool
Metadata datatypes.JSON
// TODO rename to AppPubKey
NostrPubkey string `validate:"required"`
WalletPubkey string
CreatedAt time.Time
UpdatedAt time.Time
Isolated bool
Metadata datatypes.JSON
}

type AppPermission struct {
Expand Down Expand Up @@ -87,7 +89,8 @@ type Transaction struct {
}

type DBService interface {
CreateApp(name string, pubkey string, maxAmountSat uint64, budgetRenewal string, expiresAt *time.Time, scopes []string, isolated bool, metadata map[string]interface{}) (*App, string, error)
CreateApp(name string, pubkey string, maxAmountSat uint64, budgetRenewal string, expiresAt *time.Time, scopes []string, isolated bool, metadata map[string]interface{}, walletChildPrivKeyGeneratorFunc func(uint32) (string, error)) (*App, string, error)
DeleteApp(app *App) error
}

const (
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/DataDog/datadog-go/v5 v5.3.0 // indirect
github.com/DataDog/gostackparse v0.7.0 // indirect
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
Expand Down Expand Up @@ -168,6 +170,7 @@ require (
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tkrajina/go-reflector v0.5.6 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/
github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM=
github.com/DataDog/sketches-go v1.4.5 h1:ki7VfeNz7IcNafq7yI/j5U/YCkO3LJiMDtXz9OMQbyE=
github.com/DataDog/sketches-go v1.4.5/go.mod h1:7Y8GN8Jf66DLyDhc94zuWA3uHEt/7ttt8jHOBWWrSOg=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
Expand Down Expand Up @@ -106,6 +110,7 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
Expand Down Expand Up @@ -601,6 +606,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand Down Expand Up @@ -634,6 +640,8 @@ github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQ
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
Expand Down Expand Up @@ -720,6 +728,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down Expand Up @@ -947,6 +956,7 @@ gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk=
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA=
Expand Down
34 changes: 24 additions & 10 deletions nip47/event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
}).Error("invalid event signature")
return
}

ss, err := nip04.ComputeSharedSecret(event.PubKey, svc.keys.GetNostrSecretKey())
frnandu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
logger.Logger.WithFields(logrus.Fields{
Expand Down Expand Up @@ -75,7 +74,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
Message: fmt.Sprintf("Failed to save nostr event: %s", err.Error()),
},
}
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss)
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss, svc.keys.GetNostrSecretKey())
frnandu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand All @@ -85,11 +84,24 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
svc.publishResponseEvent(ctx, relay, &requestEvent, resp, nil)
return
}

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

appWalletPrivKey := svc.keys.GetNostrSecretKey()

if app.WalletPubkey != "" {
// This is a new child key derived from master using app ID as index
appWalletPrivKey, err = svc.keys.GetAppWalletKey(uint32(app.ID))
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"appId": app.ID,
}).WithError(err).Error("error deriving child key")
return
}
}

if err != nil {
logger.Logger.WithFields(logrus.Fields{
"nostrPubkey": event.PubKey,
Expand All @@ -101,7 +113,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
Message: "The public key does not have a wallet connected.",
},
}
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss)
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss, svc.keys.GetNostrSecretKey())
frnandu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand Down Expand Up @@ -133,7 +145,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
Message: fmt.Sprintf("Failed to save app to nostr event: %s", err.Error()),
},
}
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss)
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss, svc.keys.GetNostrSecretKey())
rolznz marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand All @@ -160,7 +172,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
}).Debug("App found for nostr event")

//to be extra safe, decrypt using the key found from the app
ss, err = nip04.ComputeSharedSecret(app.NostrPubkey, svc.keys.GetNostrSecretKey())
ss, err = nip04.ComputeSharedSecret(app.NostrPubkey, appWalletPrivKey)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand Down Expand Up @@ -225,7 +237,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
// TODO: replace with a channel
// TODO: update all previous occurences of svc.publishResponseEvent to also use the channel
publishResponse := func(nip47Response *models.Response, tags nostr.Tags) {
resp, err := svc.CreateResponse(event, nip47Response, tags, ss)
resp, err := svc.CreateResponse(event, nip47Response, tags, ss, appWalletPrivKey)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand Down Expand Up @@ -356,7 +368,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
}
}

func (svc *nip47Service) CreateResponse(initialEvent *nostr.Event, content interface{}, tags nostr.Tags, ss []byte) (result *nostr.Event, err error) {
func (svc *nip47Service) CreateResponse(initialEvent *nostr.Event, content interface{}, tags nostr.Tags, ss []byte, appWalletPrivKey string) (result *nostr.Event, err error) {
payloadBytes, err := json.Marshal(content)
if err != nil {
return nil, err
Expand All @@ -369,14 +381,16 @@ func (svc *nip47Service) CreateResponse(initialEvent *nostr.Event, content inter
allTags := nostr.Tags{[]string{"p", initialEvent.PubKey}, []string{"e", initialEvent.ID}}
allTags = append(allTags, tags...)

appWalletPubKey, _ := nostr.GetPublicKey(appWalletPrivKey)
frnandu marked this conversation as resolved.
Show resolved Hide resolved
frnandu marked this conversation as resolved.
Show resolved Hide resolved

resp := &nostr.Event{
PubKey: svc.keys.GetNostrPublicKey(),
PubKey: appWalletPubKey,
CreatedAt: nostr.Now(),
Kind: models.RESPONSE_KIND,
Tags: allTags,
Content: msg,
}
err = resp.Sign(svc.keys.GetNostrSecretKey())
err = resp.Sign(appWalletPrivKey)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion nip47/event_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestCreateResponse(t *testing.T) {

nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)

res, err := nip47svc.CreateResponse(reqEvent, nip47Response, nostr.Tags{}, ss)
res, err := nip47svc.CreateResponse(reqEvent, nip47Response, nostr.Tags{}, ss, svc.Keys.GetNostrSecretKey())
frnandu marked this conversation as resolved.
Show resolved Hide resolved
assert.NoError(t, err)
assert.Equal(t, reqPubkey, res.Tags.GetFirst([]string{"p"}).Value())
assert.Equal(t, reqEvent.ID, res.Tags.GetFirst([]string{"e"}).Value())
Expand Down
6 changes: 3 additions & 3 deletions nip47/nip47_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package nip47

import (
"context"

"github.com/getAlby/hub/config"
"github.com/getAlby/hub/events"
"github.com/getAlby/hub/lnclient"
Expand All @@ -29,8 +28,9 @@ type Nip47Service interface {
events.EventSubscriber
StartNotifier(ctx context.Context, relay *nostr.Relay, lnClient lnclient.LNClient)
HandleEvent(ctx context.Context, relay nostrmodels.Relay, event *nostr.Event, lnClient lnclient.LNClient)
PublishNip47Info(ctx context.Context, relay nostrmodels.Relay, lnClient lnclient.LNClient) error
CreateResponse(initialEvent *nostr.Event, content interface{}, tags nostr.Tags, ss []byte) (result *nostr.Event, err error)
PublishNip47Info(ctx context.Context, relay nostrmodels.Relay, appWalletPubKey string, appWalletPrivKey string, lnClient lnclient.LNClient) (*nostr.Event, error)
PublishNip47InfoDeletion(ctx context.Context, relay nostrmodels.Relay, appWalletPubKey string, appWalletPrivKey string, infoEventId string) error
im-adithya marked this conversation as resolved.
Show resolved Hide resolved
CreateResponse(initialEvent *nostr.Event, content interface{}, tags nostr.Tags, ss []byte, walletPrivKey string) (result *nostr.Event, err error)
}

func NewNip47Service(db *gorm.DB, cfg config.Config, keys keys.Keys, eventPublisher events.EventPublisher) *nip47Service {
Expand Down
Loading
Loading