@@ -17,10 +17,53 @@ import (
1717 "github.com/lightningnetwork/lnd/lnwire"
1818)
1919
20+ // DecodeOption is a type that can be used to supply functional options to the
21+ // Decode function.
22+ type DecodeOption func (* decodeOptions )
23+
24+ // WithKnownFeatureBits is a functional option that overwrites the set of
25+ // known feature bits. If not set, then LND's lnwire.Features variable will be
26+ // used by default.
27+ func WithKnownFeatureBits (features map [lnwire.FeatureBit ]string ) DecodeOption {
28+ return func (options * decodeOptions ) {
29+ options .knownFeatureBits = features
30+ }
31+ }
32+
33+ // WithErrorOnUnknownFeatureBit is a functional option that will cause the
34+ // Decode function to return an error if the decoded invoice contains an unknown
35+ // feature bit.
36+ func WithErrorOnUnknownFeatureBit () DecodeOption {
37+ return func (options * decodeOptions ) {
38+ options .errorOnUnknownFeature = true
39+ }
40+ }
41+
42+ // decodeOptions holds the set of Decode options.
43+ type decodeOptions struct {
44+ knownFeatureBits map [lnwire.FeatureBit ]string
45+ errorOnUnknownFeature bool
46+ }
47+
48+ // newDecodeOptions constructs the default decodeOptions struct.
49+ func newDecodeOptions () * decodeOptions {
50+ return & decodeOptions {
51+ knownFeatureBits : lnwire .Features ,
52+ errorOnUnknownFeature : false ,
53+ }
54+ }
55+
2056// Decode parses the provided encoded invoice and returns a decoded Invoice if
2157// it is valid by BOLT-0011 and matches the provided active network.
22- func Decode (invoice string , net * chaincfg.Params ) (* Invoice , error ) {
23- decodedInvoice := Invoice {}
58+ func Decode (invoice string , net * chaincfg.Params , opts ... DecodeOption ) (
59+ * Invoice , error ) {
60+
61+ options := newDecodeOptions ()
62+ for _ , o := range opts {
63+ o (options )
64+ }
65+
66+ var decodedInvoice Invoice
2467
2568 // Before bech32 decoding the invoice, make sure that it is not too large.
2669 // 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) {
134177 // If no feature vector was decoded, populate an empty one.
135178 if decodedInvoice .Features == nil {
136179 decodedInvoice .Features = lnwire .NewFeatureVector (
137- nil , lnwire . Features ,
180+ nil , options . knownFeatureBits ,
138181 )
139182 }
140183
@@ -144,6 +187,24 @@ func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
144187 return nil , err
145188 }
146189
190+ if options .errorOnUnknownFeature {
191+ // Make sure that we understand all the required feature bits
192+ // in the invoice.
193+ unknownFeatureBits := decodedInvoice .Features .
194+ UnknownRequiredFeatures ()
195+
196+ if len (unknownFeatureBits ) > 0 {
197+ errStr := fmt .Sprintf ("invoice contains " +
198+ "unknown feature bits:" )
199+
200+ for _ , bit := range unknownFeatureBits {
201+ errStr += fmt .Sprintf (" %d," , bit )
202+ }
203+
204+ return nil , fmt .Errorf (strings .TrimRight (errStr , "," ))
205+ }
206+ }
207+
147208 return & decodedInvoice , nil
148209}
149210
0 commit comments