From 040fcb0f927af4d1df99096645d0a230be25d191 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Tue, 2 Apr 2024 09:04:27 -0400 Subject: [PATCH] multi: add option to disable route blinding, rejecting at link Add an option to disable route blinding, failing back any HTLC with a blinding point set when we haven't got the feature enabled. Note that this commit only handles the case where we're chosen as the relaying node (where the blinding point is in update_add_htlc), we'll add handling for the introduction node case once we get to handling of blinded payloads). --- htlcswitch/link.go | 18 ++++++++++++++++++ lncfg/protocol.go | 8 ++++++++ lncfg/protocol_integration.go | 8 ++++++++ peer/brontide.go | 6 ++++++ sample-lnd.conf | 3 +++ server.go | 1 + 6 files changed, 44 insertions(+) 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, }