event_handler_test.go raw
1 package nip47
2
3 import (
4 "context"
5 "encoding/json"
6 "slices"
7 "testing"
8 "time"
9
10 "github.com/getAlby/go-nostr"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/require"
13
14 "github.com/getAlby/hub/alby"
15 "github.com/getAlby/hub/constants"
16 "github.com/getAlby/hub/db"
17 "github.com/getAlby/hub/nip47/cipher"
18 "github.com/getAlby/hub/nip47/models"
19 "github.com/getAlby/hub/nip47/permissions"
20 "github.com/getAlby/hub/tests"
21 )
22
23 // TODO: test if an app doesn't exist it returns the right error code
24
25 func TestCreateResponse_Nip04(t *testing.T) {
26 svc, err := tests.CreateTestService(t)
27 require.NoError(t, err)
28 defer svc.Remove()
29
30 doTestCreateResponse(t, svc, constants.ENCRYPTION_TYPE_NIP04)
31 }
32
33 func TestCreateResponse_Nip44(t *testing.T) {
34 svc, err := tests.CreateTestService(t)
35 require.NoError(t, err)
36 defer svc.Remove()
37
38 doTestCreateResponse(t, svc, constants.ENCRYPTION_TYPE_NIP44_V2)
39 }
40
41 func doTestCreateResponse(t *testing.T, svc *tests.TestService, nip47Encryption string) {
42 reqPrivateKey := nostr.GeneratePrivateKey()
43 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
44 assert.NoError(t, err)
45
46 reqEvent := &nostr.Event{
47 Kind: models.REQUEST_KIND,
48 PubKey: reqPubkey,
49 Content: "1",
50 }
51
52 reqEvent.ID = "12345"
53
54 nip47Cipher, err := cipher.NewNip47Cipher(nip47Encryption, reqPubkey, svc.Keys.GetNostrSecretKey())
55 assert.NoError(t, err)
56
57 type dummyResponse struct {
58 Foo int
59 }
60
61 nip47Response := &models.Response{
62 ResultType: "dummy_method",
63 Result: dummyResponse{
64 Foo: 1000,
65 },
66 }
67
68 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
69 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
70
71 res, err := nip47svc.CreateResponse(reqEvent, nip47Response, nostr.Tags{}, nip47Cipher, svc.Keys.GetNostrSecretKey())
72 assert.NoError(t, err)
73 assert.Equal(t, reqPubkey, res.Tags.Find("p")[1])
74 assert.Equal(t, reqEvent.ID, res.Tags.Find("e")[1])
75 assert.Equal(t, svc.Keys.GetNostrPublicKey(), res.PubKey)
76
77 decrypted, err := nip47Cipher.Decrypt(res.Content)
78 assert.NoError(t, err)
79 unmarshalledResponse := models.Response{
80 Result: &dummyResponse{},
81 }
82
83 err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
84 assert.NoError(t, err)
85 assert.Nil(t, nip47Response.Error)
86 assert.Equal(t, nip47Response.ResultType, unmarshalledResponse.ResultType)
87 assert.Equal(t, nip47Response.Result, *unmarshalledResponse.Result.(*dummyResponse))
88 }
89
90 func TestHandleResponse_Nip04_WithPermission(t *testing.T) {
91 svc, err := tests.CreateTestService(t)
92 require.NoError(t, err)
93 defer svc.Remove()
94
95 doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
96 }
97
98 func TestHandleResponse_Nip44_WithPermission(t *testing.T) {
99 svc, err := tests.CreateTestService(t)
100 require.NoError(t, err)
101 defer svc.Remove()
102
103 doTestHandleResponse_WithPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
104 }
105
106 func doTestHandleResponse_WithPermission(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
107 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
108 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
109
110 reqPrivateKey := nostr.GeneratePrivateKey()
111 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
112 assert.NoError(t, err)
113
114 app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
115 assert.NoError(t, err)
116
117 appPermission := &db.AppPermission{
118 AppId: app.ID,
119 App: *app,
120 Scope: constants.GET_BALANCE_SCOPE,
121 }
122 err = svc.DB.Create(appPermission).Error
123 assert.NoError(t, err)
124
125 content := map[string]interface{}{
126 "method": models.GET_INFO_METHOD,
127 }
128
129 payloadBytes, err := json.Marshal(content)
130 assert.NoError(t, err)
131
132 msg, err := cipher.Encrypt(string(payloadBytes))
133 assert.NoError(t, err)
134
135 reqEvent := &nostr.Event{
136 Kind: models.REQUEST_KIND,
137 PubKey: reqPubkey,
138 CreatedAt: nostr.Now(),
139 Tags: nostr.Tags{},
140 Content: msg,
141 }
142
143 if encryption != constants.ENCRYPTION_TYPE_NIP04 {
144 reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
145 }
146
147 err = reqEvent.Sign(reqPrivateKey)
148 assert.NoError(t, err)
149
150 pool := tests.NewMockSimplePool()
151
152 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
153
154 assert.NotNil(t, pool.PublishedEvents[0])
155 assert.NotEmpty(t, pool.PublishedEvents[0].Content)
156
157 decrypted, err := cipher.Decrypt(pool.PublishedEvents[0].Content)
158 assert.NoError(t, err)
159
160 type getInfoResult struct {
161 Methods []string `json:"methods"`
162 }
163
164 type getInfoResponseWrapper struct {
165 models.Response
166 Result getInfoResult `json:"result"`
167 }
168
169 unmarshalledResponse := getInfoResponseWrapper{}
170
171 err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
172 assert.NoError(t, err)
173 assert.Nil(t, unmarshalledResponse.Error)
174 assert.Equal(t, models.GET_INFO_METHOD, unmarshalledResponse.ResultType)
175 expectedMethods := slices.Concat([]string{constants.GET_BALANCE_SCOPE}, permissions.GetAlwaysGrantedMethods())
176 assert.ElementsMatch(t, expectedMethods, unmarshalledResponse.Result.Methods)
177 }
178
179 func TestHandleResponse_Nip04_DuplicateRequest(t *testing.T) {
180 svc, err := tests.CreateTestService(t)
181 require.NoError(t, err)
182 defer svc.Remove()
183
184 doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
185 }
186
187 func TestHandleResponse_Nip44_DuplicateRequest(t *testing.T) {
188 svc, err := tests.CreateTestService(t)
189 require.NoError(t, err)
190 defer svc.Remove()
191
192 doTestHandleResponse_DuplicateRequest(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
193 }
194
195 func doTestHandleResponse_DuplicateRequest(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
196 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
197 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
198
199 reqPrivateKey := nostr.GeneratePrivateKey()
200 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
201 assert.NoError(t, err)
202
203 app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
204 assert.NoError(t, err)
205
206 appPermission := &db.AppPermission{
207 AppId: app.ID,
208 App: *app,
209 Scope: constants.GET_BALANCE_SCOPE,
210 }
211 err = svc.DB.Create(appPermission).Error
212 assert.NoError(t, err)
213
214 content := map[string]interface{}{
215 "method": models.GET_INFO_METHOD,
216 }
217
218 payloadBytes, err := json.Marshal(content)
219 assert.NoError(t, err)
220
221 msg, err := cipher.Encrypt(string(payloadBytes))
222 assert.NoError(t, err)
223
224 reqEvent := &nostr.Event{
225 Kind: models.REQUEST_KIND,
226 PubKey: reqPubkey,
227 CreatedAt: nostr.Now(),
228 Tags: nostr.Tags{},
229 Content: msg,
230 }
231
232 if encryption != constants.ENCRYPTION_TYPE_NIP04 {
233 reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
234 }
235
236 err = reqEvent.Sign(reqPrivateKey)
237 assert.NoError(t, err)
238
239 pool := tests.NewMockSimplePool()
240
241 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
242
243 assert.NotNil(t, pool.PublishedEvents[0])
244 assert.NotEmpty(t, pool.PublishedEvents[0].Content)
245
246 pool.PublishedEvents = nil
247
248 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
249
250 // second time it should not publish
251 assert.Nil(t, pool.PublishedEvents)
252 }
253
254 func TestHandleResponse_Nip04_NoPermission(t *testing.T) {
255 svc, err := tests.CreateTestService(t)
256 require.NoError(t, err)
257 defer svc.Remove()
258
259 doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
260 }
261
262 func TestHandleResponse_Nip44_NoPermission(t *testing.T) {
263 svc, err := tests.CreateTestService(t)
264 require.NoError(t, err)
265 defer svc.Remove()
266
267 doTestHandleResponse_NoPermission(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
268 }
269
270 func doTestHandleResponse_NoPermission(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
271 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
272 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
273
274 reqPrivateKey := nostr.GeneratePrivateKey()
275 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
276 assert.NoError(t, err)
277
278 _, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
279 assert.NoError(t, err)
280
281 content := map[string]interface{}{
282 "method": models.GET_BALANCE_METHOD,
283 }
284
285 payloadBytes, err := json.Marshal(content)
286 assert.NoError(t, err)
287
288 msg, err := cipher.Encrypt(string(payloadBytes))
289 assert.NoError(t, err)
290
291 reqEvent := &nostr.Event{
292 Kind: models.REQUEST_KIND,
293 PubKey: reqPubkey,
294 CreatedAt: nostr.Now(),
295 Tags: nostr.Tags{},
296 Content: msg,
297 }
298
299 if encryption != constants.ENCRYPTION_TYPE_NIP04 {
300 reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
301 }
302
303 err = reqEvent.Sign(reqPrivateKey)
304 assert.NoError(t, err)
305
306 pool := tests.NewMockSimplePool()
307
308 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
309
310 assert.NotNil(t, pool.PublishedEvents[0])
311 assert.NotEmpty(t, pool.PublishedEvents[0].Content)
312
313 decrypted, err := cipher.Decrypt(pool.PublishedEvents[0].Content)
314 assert.NoError(t, err)
315
316 unmarshalledResponse := models.Response{}
317
318 err = json.Unmarshal([]byte(decrypted), &unmarshalledResponse)
319 assert.NoError(t, err)
320 assert.Nil(t, unmarshalledResponse.Result)
321 assert.Equal(t, models.GET_BALANCE_METHOD, unmarshalledResponse.ResultType)
322 assert.Equal(t, "RESTRICTED", unmarshalledResponse.Error.Code)
323 assert.Equal(t, "This app does not have the get_balance scope", unmarshalledResponse.Error.Message)
324 }
325
326 func TestHandleResponse_Nip04_OldRequestForPayment(t *testing.T) {
327 svc, err := tests.CreateTestService(t)
328 require.NoError(t, err)
329 defer svc.Remove()
330
331 doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
332 }
333
334 func TestHandleResponse_Nip44_OldRequestForPayment(t *testing.T) {
335 svc, err := tests.CreateTestService(t)
336 require.NoError(t, err)
337 defer svc.Remove()
338
339 doTestHandleResponse_OldRequestForPayment(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
340 }
341
342 func doTestHandleResponse_OldRequestForPayment(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
343 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
344 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
345
346 reqPrivateKey := nostr.GeneratePrivateKey()
347 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
348 assert.NoError(t, err)
349
350 app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
351 assert.NoError(t, err)
352
353 content := map[string]interface{}{
354 "method": models.PAY_INVOICE_METHOD,
355 }
356
357 appPermission := &db.AppPermission{
358 AppId: app.ID,
359 App: *app,
360 Scope: constants.PAY_INVOICE_SCOPE,
361 }
362 err = svc.DB.Create(appPermission).Error
363 assert.NoError(t, err)
364
365 payloadBytes, err := json.Marshal(content)
366 assert.NoError(t, err)
367
368 msg, err := cipher.Encrypt(string(payloadBytes))
369 assert.NoError(t, err)
370
371 reqEvent := &nostr.Event{
372 Kind: models.REQUEST_KIND,
373 PubKey: reqPubkey,
374 CreatedAt: nostr.Timestamp(time.Now().Add(time.Duration(-6) * time.Hour).Unix()),
375 Tags: nostr.Tags{},
376 Content: msg,
377 }
378
379 if encryption != constants.ENCRYPTION_TYPE_NIP04 {
380 reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
381 }
382
383 err = reqEvent.Sign(reqPrivateKey)
384 assert.NoError(t, err)
385
386 pool := tests.NewMockSimplePool()
387
388 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
389
390 // it shouldn't return anything for an old request
391 assert.Nil(t, pool.PublishedEvents)
392
393 // change the request to now
394 reqEvent.CreatedAt = nostr.Now()
395 err = reqEvent.Sign(reqPrivateKey)
396 assert.NoError(t, err)
397
398 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
399 assert.NotNil(t, pool.PublishedEvents)
400 }
401
402 func TestHandleResponse_Nip04_IncorrectPubkey(t *testing.T) {
403 svc, err := tests.CreateTestService(t)
404 require.NoError(t, err)
405 defer svc.Remove()
406
407 doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP04)
408 }
409
410 func TestHandleResponse_Nip44_IncorrectPubkey(t *testing.T) {
411 svc, err := tests.CreateTestService(t)
412 require.NoError(t, err)
413 defer svc.Remove()
414
415 doTestHandleResponse_IncorrectPubkey(t, svc, tests.CreateAppWithPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
416 }
417
418 func doTestHandleResponse_IncorrectPubkey(t *testing.T, svc *tests.TestService, createAppFn tests.CreateAppFn, encryption string) {
419 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
420 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
421
422 reqPrivateKey := nostr.GeneratePrivateKey()
423 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
424 assert.NoError(t, err)
425
426 reqPrivateKey2 := nostr.GeneratePrivateKey()
427
428 app, cipher, err := createAppFn(svc, reqPrivateKey, encryption)
429 assert.NoError(t, err)
430
431 appPermission := &db.AppPermission{
432 AppId: app.ID,
433 App: *app,
434 Scope: constants.GET_BALANCE_SCOPE,
435 }
436 err = svc.DB.Create(appPermission).Error
437 assert.NoError(t, err)
438
439 content := map[string]interface{}{
440 "method": models.GET_BALANCE_METHOD,
441 }
442
443 payloadBytes, err := json.Marshal(content)
444 assert.NoError(t, err)
445
446 msg, err := cipher.Encrypt(string(payloadBytes))
447 assert.NoError(t, err)
448
449 reqEvent := &nostr.Event{
450 Kind: models.REQUEST_KIND,
451 CreatedAt: nostr.Now(),
452 Tags: nostr.Tags{},
453 Content: msg,
454 }
455
456 if encryption != constants.ENCRYPTION_TYPE_NIP04 {
457 reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", encryption})
458 }
459
460 err = reqEvent.Sign(reqPrivateKey2)
461 assert.NoError(t, err)
462
463 // set a different pubkey (this will not pass validation)
464 reqEvent.PubKey = reqPubkey
465
466 pool := tests.NewMockSimplePool()
467
468 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
469
470 assert.Nil(t, pool.PublishedEvents)
471 }
472
473 func TestHandleResponse_NoApp(t *testing.T) {
474 svc, err := tests.CreateTestService(t)
475 require.NoError(t, err)
476 defer svc.Remove()
477 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
478 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
479
480 reqPrivateKey := nostr.GeneratePrivateKey()
481 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
482 assert.NoError(t, err)
483
484 app, cipher, err := tests.CreateAppWithPrivateKey(svc, reqPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
485 assert.NoError(t, err)
486
487 // delete the app
488 err = svc.DB.Delete(app).Error
489 assert.NoError(t, err)
490
491 content := map[string]interface{}{
492 "method": models.GET_BALANCE_METHOD,
493 }
494
495 payloadBytes, err := json.Marshal(content)
496 assert.NoError(t, err)
497
498 msg, err := cipher.Encrypt(string(payloadBytes))
499 assert.NoError(t, err)
500
501 reqEvent := &nostr.Event{
502 Kind: models.REQUEST_KIND,
503 PubKey: reqPubkey,
504 CreatedAt: nostr.Now(),
505 Tags: nostr.Tags{[]string{"encryption", constants.ENCRYPTION_TYPE_NIP44_V2}},
506 Content: msg,
507 }
508 err = reqEvent.Sign(reqPrivateKey)
509 assert.NoError(t, err)
510
511 pool := tests.NewMockSimplePool()
512
513 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
514
515 // it shouldn't return anything for an invalid app key
516 assert.Nil(t, pool.PublishedEvents)
517 }
518
519 func TestHandleResponse_UnknownEncryptionTag(t *testing.T) {
520 svc, err := tests.CreateTestService(t)
521 require.NoError(t, err)
522 defer svc.Remove()
523 doTestHandleResponse_UnknownEncryptionTag(t, svc, "nip44")
524 doTestHandleResponse_UnknownEncryptionTag(t, svc, "nip44v2")
525 doTestHandleResponse_UnknownEncryptionTag(t, svc, "nip44_v3")
526 doTestHandleResponse_UnknownEncryptionTag(t, svc, "")
527 }
528
529 func doTestHandleResponse_UnknownEncryptionTag(t *testing.T, svc *tests.TestService, requestEncryptionTag string) {
530 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
531 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
532
533 reqPrivateKey := nostr.GeneratePrivateKey()
534 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
535 assert.NoError(t, err)
536
537 app, cipher, err := tests.CreateAppWithPrivateKey(svc, reqPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
538 assert.NoError(t, err)
539
540 appPermission := &db.AppPermission{
541 AppId: app.ID,
542 App: *app,
543 Scope: constants.GET_BALANCE_SCOPE,
544 }
545 err = svc.DB.Create(appPermission).Error
546 assert.NoError(t, err)
547
548 content := map[string]interface{}{
549 "method": models.GET_INFO_METHOD,
550 }
551
552 payloadBytes, err := json.Marshal(content)
553 assert.NoError(t, err)
554
555 msg, err := cipher.Encrypt(string(payloadBytes))
556 assert.NoError(t, err)
557
558 // don't pass correct encryption
559 reqEvent := &nostr.Event{
560 Kind: models.REQUEST_KIND,
561 PubKey: reqPubkey,
562 CreatedAt: nostr.Now(),
563 Tags: nostr.Tags{[]string{"encryption", requestEncryptionTag}},
564 Content: msg,
565 }
566
567 err = reqEvent.Sign(reqPrivateKey)
568 assert.NoError(t, err)
569
570 pool := tests.NewMockSimplePool()
571
572 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
573
574 assert.NotNil(t, pool.PublishedEvents)
575 responseContent := pool.PublishedEvents[0].Content
576 msg, err = cipher.Decrypt(responseContent)
577 assert.NoError(t, err)
578 assert.NotEqual(t, "", msg)
579
580 unmarshalledResponse := models.Response{}
581
582 err = json.Unmarshal([]byte(msg), &unmarshalledResponse)
583 assert.NoError(t, err)
584 assert.Nil(t, unmarshalledResponse.Result)
585 // assert.Equal(t, models.GET_INFO_METHOD, unmarshalledResponse.ResultType)
586 assert.Equal(t, constants.ERROR_UNSUPPORTED_ENCRYPTION, unmarshalledResponse.Error.Code)
587 assert.Contains(t, unmarshalledResponse.Error.Message, "invalid encryption:")
588 }
589
590 func TestHandleResponse_EncryptionTagDoesNotMatchPayload(t *testing.T) {
591 svc, err := tests.CreateTestService(t)
592 require.NoError(t, err)
593 defer svc.Remove()
594 // encryption specifies what cipher will use. If constants.ENCRYPTION_TYPE_NIP44_V2 is passed,
595 // cipher must be NIP-44, otherwise cipher MUST be NIP-04
596 doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t, svc, constants.ENCRYPTION_TYPE_NIP44_V2, constants.ENCRYPTION_TYPE_NIP04)
597 doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t, svc, constants.ENCRYPTION_TYPE_NIP04, constants.ENCRYPTION_TYPE_NIP44_V2)
598 doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t, svc, constants.ENCRYPTION_TYPE_NIP44_V2, "")
599 }
600
601 func doTestHandleResponse_EncryptionTagDoesNotMatchPayload(t *testing.T, svc *tests.TestService, requestEncryption, requestEncryptionTag string) {
602 albyOAuthSvc := alby.NewAlbyOAuthService(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)
603 nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher, albyOAuthSvc)
604
605 reqPrivateKey := nostr.GeneratePrivateKey()
606 reqPubkey, err := nostr.GetPublicKey(reqPrivateKey)
607 assert.NoError(t, err)
608
609 app, _, err := tests.CreateAppWithPrivateKey(svc, reqPrivateKey, constants.ENCRYPTION_TYPE_NIP44_V2)
610 assert.NoError(t, err)
611
612 appPermission := &db.AppPermission{
613 AppId: app.ID,
614 App: *app,
615 Scope: constants.GET_BALANCE_SCOPE,
616 }
617 err = svc.DB.Create(appPermission).Error
618 assert.NoError(t, err)
619
620 content := map[string]interface{}{
621 "method": models.GET_INFO_METHOD,
622 }
623
624 payloadBytes, err := json.Marshal(content)
625 assert.NoError(t, err)
626
627 reqCipher, err := cipher.NewNip47Cipher(requestEncryption, *app.WalletPubkey, reqPrivateKey)
628 assert.NoError(t, err)
629 // whenever we are unable to handle the request encryption, we always respond with our preferred encryption (NIP44)
630 nip44Cipher, err := cipher.NewNip47Cipher(constants.ENCRYPTION_TYPE_NIP44_V2, *app.WalletPubkey, reqPrivateKey)
631 assert.NoError(t, err)
632 msg, err := reqCipher.Encrypt(string(payloadBytes))
633 assert.NoError(t, err)
634
635 // don't pass correct encryption
636 reqEvent := &nostr.Event{
637 Kind: models.REQUEST_KIND,
638 PubKey: reqPubkey,
639 CreatedAt: nostr.Now(),
640 Tags: nostr.Tags{},
641 Content: msg,
642 }
643
644 if requestEncryptionTag != "" {
645 reqEvent.Tags = append(reqEvent.Tags, []string{"encryption", requestEncryptionTag})
646 }
647
648 err = reqEvent.Sign(reqPrivateKey)
649 assert.NoError(t, err)
650
651 pool := tests.NewMockSimplePool()
652
653 nip47svc.HandleEvent(context.TODO(), pool, reqEvent, svc.LNClient)
654
655 assert.NotNil(t, pool.PublishedEvents)
656 responseContent := pool.PublishedEvents[0].Content
657 msg, err = nip44Cipher.Decrypt(responseContent)
658 assert.NoError(t, err)
659 assert.NotEqual(t, "", msg)
660
661 unmarshalledResponse := models.Response{}
662 err = json.Unmarshal([]byte(msg), &unmarshalledResponse)
663 assert.NoError(t, err)
664 assert.Nil(t, unmarshalledResponse.Result)
665 // assert.Equal(t, models.GET_INFO_METHOD, unmarshalledResponse.ResultType)
666 assert.Equal(t, constants.ERROR_BAD_REQUEST, unmarshalledResponse.Error.Code)
667 assert.Contains(t, unmarshalledResponse.Error.Message, "failed to decrypt:")
668 }
669