zpay32: add functional opt to error out on unknown feature bit

This commit adds two functional options to the zpay32.Decode function.
`WithKnownFeatureBits` allows the caller to overwrite the default set of
known feature bits used by the function.
`WithErrorOnUnknownFeatureBit` allows the caller to instruct the
function to error out if the invoice that is decoded contaijns unknown
feature bits. We then use this new error-out option from the
`rpcServer`'s `extractPaymentIntent` method.
This commit is contained in:
Elle Mouton committed 2024-08-07 17:03:12 +02:00
1 parent e4619afc08
commit 48a9a8d20e
3 files changed
+133 -4

No files matched your search

+64 -3
View File
@@ -17,10 +17,53 @@ import (
"github.com/lightningnetwork/lnd/lnwire"
)
// DecodeOption is a type that can be used to supply functional options to the
// Decode function.
type DecodeOption func(*decodeOptions)
// WithKnownFeatureBits is a functional option that overwrites the set of
// known feature bits. If not set, then LND's lnwire.Features variable will be
// used by default.
func WithKnownFeatureBits(features map[lnwire.FeatureBit]string) DecodeOption {
return func(options *decodeOptions) {
options.knownFeatureBits = features
}
}
// WithErrorOnUnknownFeatureBit is a functional option that will cause the
// Decode function to return an error if the decoded invoice contains an unknown
// feature bit.
func WithErrorOnUnknownFeatureBit() DecodeOption {
return func(options *decodeOptions) {
options.errorOnUnknownFeature = true
}
}
// decodeOptions holds the set of Decode options.
type decodeOptions struct {
knownFeatureBits map[lnwire.FeatureBit]string
errorOnUnknownFeature bool
}
// newDecodeOptions constructs the default decodeOptions struct.
func newDecodeOptions() *decodeOptions {
return &decodeOptions{
knownFeatureBits: lnwire.Features,
errorOnUnknownFeature: false,
}
}
// Decode parses the provided encoded invoice and returns a decoded Invoice if
// it is valid by BOLT-0011 and matches the provided active network.
func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
decodedInvoice := Invoice{}
func Decode(invoice string, net *chaincfg.Params, opts ...DecodeOption) (
*Invoice, error) {
options := newDecodeOptions()
for _, o := range opts {
o(options)
}
var decodedInvoice Invoice
// Before bech32 decoding the invoice, make sure that it is not too large.
// This is done as an anti-DoS measure since bech32 decoding is expensive.
@@ -134,7 +177,7 @@ func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
// If no feature vector was decoded, populate an empty one.
if decodedInvoice.Features == nil {
decodedInvoice.Features = lnwire.NewFeatureVector(
nil, lnwire.Features,
nil, options.knownFeatureBits,
)
}
@@ -144,6 +187,24 @@ func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
return nil, err
}
if options.errorOnUnknownFeature {
// Make sure that we understand all the required feature bits
// in the invoice.
unknownFeatureBits := decodedInvoice.Features.
UnknownRequiredFeatures()
if len(unknownFeatureBits) > 0 {
errStr := fmt.Sprintf("invoice contains " +
"unknown feature bits:")
for _, bit := range unknownFeatureBits {
errStr += fmt.Sprintf(" %d,", bit)
}
return nil, fmt.Errorf(strings.TrimRight(errStr, ","))
}
}
return &decodedInvoice, nil
}