diff --git a/feature/default_sets.go b/feature/default_sets.go index cc802fe8593..447870b277d 100644 --- a/feature/default_sets.go +++ b/feature/default_sets.go @@ -92,4 +92,7 @@ var defaultSetDesc = setDesc{ SetInit: {}, // I SetNodeAnn: {}, // N }, + lnwire.Bolt11BlindedPathsOptional: { + SetInvoice: {}, // I + }, } diff --git a/feature/deps.go b/feature/deps.go index 350d49acf31..64b4f2fc9c9 100644 --- a/feature/deps.go +++ b/feature/deps.go @@ -82,8 +82,8 @@ var deps = depDesc{ lnwire.RouteBlindingOptional: { lnwire.TLVOnionPayloadOptional: {}, }, - lnwire.RouteBlindingRequired: { - lnwire.TLVOnionPayloadRequired: {}, + lnwire.Bolt11BlindedPathsOptional: { + lnwire.RouteBlindingOptional: {}, }, } diff --git a/feature/manager.go b/feature/manager.go index c7029e89382..c8fa76db17e 100644 --- a/feature/manager.go +++ b/feature/manager.go @@ -187,6 +187,8 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { if cfg.NoRouteBlinding { raw.Unset(lnwire.RouteBlindingOptional) raw.Unset(lnwire.RouteBlindingRequired) + raw.Unset(lnwire.Bolt11BlindedPathsOptional) + raw.Unset(lnwire.Bolt11BlindedPathsRequired) } for _, custom := range cfg.CustomFeatures[set] { if custom > set.Maximum() { diff --git a/lnwire/features.go b/lnwire/features.go index e4dd7f4f81c..a0c956680b1 100644 --- a/lnwire/features.go +++ b/lnwire/features.go @@ -223,7 +223,7 @@ const ( // able and willing to accept keysend payments. KeysendOptional = 55 - // ScriptEnforcedLeaseOptional is an optional feature bit that signals + // ScriptEnforcedLeaseRequired is an optional feature bit that signals // that the node requires channels having zero-fee second-level HTLC // transactions, which also imply anchor commitments, along with an // additional CLTV constraint of a channel lease's expiration height @@ -241,18 +241,17 @@ const ( // TODO: Decide on actual feature bit value. ScriptEnforcedLeaseOptional FeatureBit = 2023 - // SimpleTaprootChannelsRequredFinal is a required bit that indicates + // SimpleTaprootChannelsRequiredFinal is a required bit that indicates // the node is able to create taproot-native channels. This is the // final feature bit to be used once the channel type is finalized. SimpleTaprootChannelsRequiredFinal = 80 // SimpleTaprootChannelsOptionalFinal is an optional bit that indicates // the node is able to create taproot-native channels. This is the - // final - // feature bit to be used once the channel type is finalized. + // final feature bit to be used once the channel type is finalized. SimpleTaprootChannelsOptionalFinal = 81 - // SimpleTaprootChannelsRequredStaging is a required bit that indicates + // SimpleTaprootChannelsRequiredStaging is a required bit that indicates // the node is able to create taproot-native channels. This is a // feature bit used in the wild while the channel type is still being // finalized. @@ -260,11 +259,20 @@ const ( // SimpleTaprootChannelsOptionalStaging is an optional bit that // indicates the node is able to create taproot-native channels. This - // is a feature - // bit used in the wild while the channel type is still being - // finalized. + // is a feature bit used in the wild while the channel type is still + // being finalized. SimpleTaprootChannelsOptionalStaging = 181 + // Bolt11BlindedPathsRequired is a required feature bit that indicates + // that the node is able to understand the blinded path tagged field in + // a BOLT 11 invoice. + Bolt11BlindedPathsRequired = 260 + + // Bolt11BlindedPathsOptional is an optional feature bit that indicates + // that the node is able to understand the blinded path tagged field in + // a BOLT 11 invoice. + Bolt11BlindedPathsOptional = 261 + // MaxBolt11Feature is the maximum feature bit value allowed in bolt 11 // invoices. // @@ -331,6 +339,8 @@ var Features = map[FeatureBit]string{ SimpleTaprootChannelsOptionalFinal: "simple-taproot-chans", SimpleTaprootChannelsRequiredStaging: "simple-taproot-chans-x", SimpleTaprootChannelsOptionalStaging: "simple-taproot-chans-x", + Bolt11BlindedPathsOptional: "bolt-11-blinded-paths-x", + Bolt11BlindedPathsRequired: "bolt-11-blinded-paths-x", } // RawFeatureVector represents a set of feature bits as defined in BOLT-09. A diff --git a/rpcserver.go b/rpcserver.go index 9b789182be0..99386ac6864 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -5799,13 +5799,20 @@ func (r *rpcServer) AddInvoice(ctx context.Context, GenInvoiceFeatures: func() *lnwire.FeatureVector { v := r.server.featureMgr.Get(feature.SetInvoice) - // If an invoice includes blinded paths, then a payment - // address is not required since we use the PathID in - // the final hop's encrypted data for the payment - // address. if invoice.Blind { + // If an invoice includes blinded paths, then a + // payment address is not required since we use + // the PathID in the final hop's encrypted data + // for the payment address. v.Unset(lnwire.PaymentAddrRequired) v.Set(lnwire.PaymentAddrOptional) + + // The invoice payer will also need to + // understand the new BOLT 11 tagged field + // containing the blinded path, so we switch + // the bit to required. + v.Unset(lnwire.Bolt11BlindedPathsOptional) + v.Set(lnwire.Bolt11BlindedPathsRequired) } return v