diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 7e1dded1d..3288584d5 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -273,6 +273,11 @@ type ChannelLinkConfig struct { // re-establish and should not allow anymore HTLC adds on the outgoing // direction of the link. PreviouslySentShutdown fn.Option[lnwire.Shutdown] + + // Adds the option to disable forwarding payments in blinded routes + // by failing back any blinding-related payloads as if they were + // invalid. + DisallowRouteBlinding bool } // channelLink is the service which drives a channel's commitment update @@ -1928,6 +1933,19 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { return } + // Disallow htlcs with blinding points set if we haven't + // enabled the feature. This saves us from having to process + // the onion at all, but will only catch blinded payments + // where we are a relaying node (as the blinding point will + // be in the payload when we're the introduction node). + if msg.BlindingPoint.IsSome() && l.cfg.DisallowRouteBlinding { + l.fail(LinkFailureError{code: ErrInvalidUpdate}, + "blinding point included when route blinding "+ + "is disabled") + + return + } + // We just received an add request from an upstream peer, so we // add it to our state machine, then add the HTLC to our // "settle" list in the event that we know the preimage. diff --git a/lncfg/protocol.go b/lncfg/protocol.go index f8ac08e86..e98b4dcf8 100644 --- a/lncfg/protocol.go +++ b/lncfg/protocol.go @@ -54,6 +54,9 @@ type ProtocolOptions struct { // also mean that we won't respond with timestamps if requested by our // peers. NoTimestampQueryOption bool `long:"no-timestamp-query-option" description:"do not query syncing peers for announcement timestamps and do not respond with timestamps if requested"` + + // NoRouteBlindingOption disables forwarding of payments in blinded routes. + NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` } // Wumbo returns true if lnd should permit the creation and acceptance of wumbo @@ -97,3 +100,8 @@ func (l *ProtocolOptions) NoAnySegwit() bool { func (l *ProtocolOptions) NoTimestampsQuery() bool { return l.NoTimestampQueryOption } + +// NoRouteBlinding returns true if forwarding of blinded payments is disabled. +func (l *ProtocolOptions) NoRouteBlinding() bool { + return l.NoRouteBlindingOption +} diff --git a/lncfg/protocol_integration.go b/lncfg/protocol_integration.go index ff74ba9e9..841f8e9eb 100644 --- a/lncfg/protocol_integration.go +++ b/lncfg/protocol_integration.go @@ -57,6 +57,9 @@ type ProtocolOptions struct { // also mean that we won't respond with timestamps if requested by our // peers. NoTimestampQueryOption bool `long:"no-timestamp-query-option" description:"do not query syncing peers for announcement timestamps and do not respond with timestamps if requested"` + + // NoRouteBlindingOption disables forwarding of payments in blinded routes. + NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` } // Wumbo returns true if lnd should permit the creation and acceptance of wumbo @@ -92,3 +95,8 @@ func (l *ProtocolOptions) ZeroConf() bool { func (l *ProtocolOptions) NoAnySegwit() bool { return l.NoOptionAnySegwit } + +// NoRouteBlinding returns true if forwarding of blinded payments is disabled. +func (l *ProtocolOptions) NoRouteBlinding() bool { + return l.NoRouteBlindingOption +} diff --git a/peer/brontide.go b/peer/brontide.go index 541c0f358..187fbafe1 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -365,6 +365,11 @@ type Config struct { // this across multiple Peer struct instances. PongBuf []byte + // Adds the option to disable forwarding payments in blinded routes + // by failing back any blinding-related payloads as if they were + // invalid. + DisallowRouteBlinding bool + // Quit is the server's quit channel. If this is closed, we halt operation. Quit chan struct{} } @@ -1155,6 +1160,7 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint, HtlcNotifier: p.cfg.HtlcNotifier, GetAliases: p.cfg.GetAliases, PreviouslySentShutdown: shutdownMsg, + DisallowRouteBlinding: p.cfg.DisallowRouteBlinding, } // Before adding our new link, purge the switch of any pending or live diff --git a/sample-lnd.conf b/sample-lnd.conf index dd538b07a..08a79bde5 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -1282,6 +1282,9 @@ ; Set to enable support for the experimental taproot channel type. ; protocol.simple-taproot-chans=false +; Set to disable blinded route forwarding. +; protocol.no-route-blinding=false + [db] ; The selected database backend. The current default backend is "bolt". lnd diff --git a/server.go b/server.go index ea51242e4..2c8b75af1 100644 --- a/server.go +++ b/server.go @@ -3872,6 +3872,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, GetAliases: s.aliasMgr.GetAliases, RequestAlias: s.aliasMgr.RequestAlias, AddLocalAlias: s.aliasMgr.AddLocalAlias, + DisallowRouteBlinding: s.cfg.ProtocolOptions.NoRouteBlinding(), Quit: s.quit, }