diff --git a/zpay32/amountunits.go b/zpay32/amountunits.go index 8698ab60..ba2fcb7f 100644 --- a/zpay32/amountunits.go +++ b/zpay32/amountunits.go @@ -127,6 +127,10 @@ func decodeAmount(amount string) (lnwire.MilliSatoshi, error) { // encodeAmount encodes the provided millisatoshi amount using as few characters // as possible. func encodeAmount(msat lnwire.MilliSatoshi) (string, error) { + if msat < 0 { + return "", fmt.Errorf("amount must be positive: %v", msat) + } + // If possible to express in BTC, that will always be the shortest // representation. if msat%mSatPerBtc == 0 { diff --git a/zpay32/invoice.go b/zpay32/invoice.go index 00960fac..72f13461 100644 --- a/zpay32/invoice.go +++ b/zpay32/invoice.go @@ -514,6 +514,11 @@ func validateInvoice(invoice *Invoice) error { return fmt.Errorf("net params not set") } + // Ensure that if there is an amount set, it is not negative. + if invoice.MilliSat != nil && *invoice.MilliSat < 0 { + return fmt.Errorf("negative amount: %v", *invoice.MilliSat) + } + // The invoice must contain a payment hash. if invoice.PaymentHash == nil { return fmt.Errorf("no payment hash found") diff --git a/zpay32/invoice_internal_test.go b/zpay32/invoice_internal_test.go index cefb6da1..99fa8375 100644 --- a/zpay32/invoice_internal_test.go +++ b/zpay32/invoice_internal_test.go @@ -55,6 +55,10 @@ func TestDecodeAmount(t *testing.T) { amount: "1109p", // pBTC valid: false, // not divisible by 10 }, + { + amount: "-10p", // pBTC + valid: false, // negative amount + }, { amount: "10p", // pBTC valid: true, @@ -145,6 +149,10 @@ func TestEncodeAmount(t *testing.T) { valid bool result string }{ + { + msat: -10, // mSat + valid: false, // negative amount + }, { msat: 1, // mSat valid: true,