From 64afc2227f128cf4cd90daf0d844af48e3513166 Mon Sep 17 00:00:00 2001 From: Roland <33993199+rolznz@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:25:36 +0700 Subject: [PATCH] fix: add validation on MakeInvoice for zero and non-whole satoshi amounts (#2413) --- transactions/make_invoice_test.go | 36 +++++++++++++++++++++++++--- transactions/transactions_service.go | 7 ++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/transactions/make_invoice_test.go b/transactions/make_invoice_test.go index 7ff06342..b66fd2e9 100644 --- a/transactions/make_invoice_test.go +++ b/transactions/make_invoice_test.go @@ -26,7 +26,7 @@ func TestMakeInvoice_NoApp(t *testing.T) { txMetadata["randomkey"] = strings.Repeat("a", constants.INVOICE_METADATA_MAX_LENGTH-16) // json encoding adds 16 characters - {"randomkey":""} transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) - transaction, err := transactionsService.MakeInvoice(ctx, 1234, "Hello world", "", 0, txMetadata, svc.LNClient, nil, nil, nil) + transaction, err := transactionsService.MakeInvoice(ctx, 1000, "Hello world", "", 0, txMetadata, svc.LNClient, nil, nil, nil) assert.NoError(t, err) var metadata map[string]interface{} @@ -50,13 +50,43 @@ func TestMakeInvoice_MetadataTooLarge(t *testing.T) { metadata["randomkey"] = strings.Repeat("a", constants.INVOICE_METADATA_MAX_LENGTH-15) // json encoding adds 16 characters transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) - transaction, err := transactionsService.MakeInvoice(ctx, 1234, "Hello world", "", 0, metadata, svc.LNClient, nil, nil, nil) + transaction, err := transactionsService.MakeInvoice(ctx, 1000, "Hello world", "", 0, metadata, svc.LNClient, nil, nil, nil) assert.Error(t, err) assert.Equal(t, fmt.Sprintf("encoded invoice metadata provided is too large. Limit: %d Received: %d", constants.INVOICE_METADATA_MAX_LENGTH, constants.INVOICE_METADATA_MAX_LENGTH+1), err.Error()) assert.Nil(t, transaction) } +func TestMakeInvoice_AmountNotWholeSats(t *testing.T) { + ctx := context.TODO() + + svc, err := tests.CreateTestService(t) + require.NoError(t, err) + defer svc.Remove() + + transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) + transaction, err := transactionsService.MakeInvoice(ctx, 1234, "Hello world", "", 0, nil, svc.LNClient, nil, nil, nil) + + require.Error(t, err) + assert.Equal(t, "the amount must be a whole number of satoshis", err.Error()) + assert.Nil(t, transaction) +} + +func TestMakeInvoice_AmountTooLow(t *testing.T) { + ctx := context.TODO() + + svc, err := tests.CreateTestService(t) + require.NoError(t, err) + defer svc.Remove() + + transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) + transaction, err := transactionsService.MakeInvoice(ctx, 0, "Hello world", "", 0, nil, svc.LNClient, nil, nil, nil) + + require.Error(t, err) + assert.Equal(t, "the amount must be at least 1 satoshi", err.Error()) + assert.Nil(t, transaction) +} + func TestMakeInvoice_App(t *testing.T) { ctx := context.TODO() @@ -72,7 +102,7 @@ func TestMakeInvoice_App(t *testing.T) { assert.NoError(t, err) transactionsService := NewTransactionsService(svc.DB, svc.EventPublisher) - transaction, err := transactionsService.MakeInvoice(ctx, 1234, "Hello world", "", 0, nil, svc.LNClient, &app.ID, &dbRequestEvent.ID, nil) + transaction, err := transactionsService.MakeInvoice(ctx, 1000, "Hello world", "", 0, nil, svc.LNClient, &app.ID, &dbRequestEvent.ID, nil) assert.NoError(t, err) assert.Equal(t, uint64(tests.MockLNClientTransaction.AmountMsat), transaction.AmountMsat) diff --git a/transactions/transactions_service.go b/transactions/transactions_service.go index 9c32cf25..42ae95c5 100644 --- a/transactions/transactions_service.go +++ b/transactions/transactions_service.go @@ -152,6 +152,13 @@ func (svc *transactionsService) MakeInvoice(ctx context.Context, amountMsat uint "metadata": metadata, }).Debug("Making invoice") + if amountMsat%1000 != 0 { + return nil, errors.New("the amount must be a whole number of satoshis") + } + if amountMsat < 1000 { + return nil, errors.New("the amount must be at least 1 satoshi") + } + var metadataBytes []byte if metadata != nil { var err error