diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 2d1dd7de0..4c81964cc 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -298,6 +298,11 @@ type ChannelLinkConfig struct { // used to manage the bandwidth of the link. AuxTrafficShaper fn.Option[AuxTrafficShaper] + // AuxChannelNegotiator is an optional interface that allows aux channel + // implementations to inject and process custom records over channel + // related wire messages. + AuxChannelNegotiator fn.Option[lnwallet.AuxChannelNegotiator] + // QuiescenceTimeout is the max duration that the channel can be // quiesced. Any dependent protocols (dynamic commitments, splicing, // etc.) must finish their operations under this timeout value, @@ -987,6 +992,22 @@ func (l *channelLink) syncChanStates(ctx context.Context) error { // In any case, we'll then process their ChanSync message. l.log.Info("received re-establishment message from remote side") + // If we have an AuxChannelNegotiator we notify any external + // component for this message. This serves as a notification + // that the reestablish message was received. + l.cfg.AuxChannelNegotiator.WhenSome( + func(acn lnwallet.AuxChannelNegotiator) { + fundingPoint := l.channel.ChannelPoint() + cid := lnwire.NewChanIDFromOutPoint( + fundingPoint, + ) + + acn.ProcessReestablish( + cid, l.cfg.Peer.PubKey(), + ) + }, + ) + var ( openedCircuits []CircuitKey closedCircuits []CircuitKey diff --git a/peer/brontide.go b/peer/brontide.go index 57e340fb0..1ea16d1e8 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -456,6 +456,11 @@ type Config struct { // used to modify the way the co-op close transaction is constructed. AuxChanCloser fn.Option[chancloser.AuxChanCloser] + // AuxChannelNegotiator is an optional interface that allows aux channel + // implementations to inject and process custom records over channel + // related wire messages. + AuxChannelNegotiator fn.Option[lnwallet.AuxChannelNegotiator] + // ShouldFwdExpEndorsement is a closure that indicates whether // experimental endorsement signals should be set. ShouldFwdExpEndorsement func() bool @@ -1454,8 +1459,9 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint, ShouldFwdExpEndorsement: p.cfg.ShouldFwdExpEndorsement, DisallowQuiescence: p.cfg.DisallowQuiescence || !p.remoteFeatures.HasFeature(lnwire.QuiescenceOptional), - AuxTrafficShaper: p.cfg.AuxTrafficShaper, - QuiescenceTimeout: p.cfg.QuiescenceTimeout, + AuxTrafficShaper: p.cfg.AuxTrafficShaper, + AuxChannelNegotiator: p.cfg.AuxChannelNegotiator, + QuiescenceTimeout: p.cfg.QuiescenceTimeout, } // Before adding our new link, purge the switch of any pending or live @@ -4537,6 +4543,19 @@ func (p *Brontide) handleInitMsg(msg *lnwire.Init) error { return fmt.Errorf("data loss protection required") } + // If we have an AuxChannelNegotiator and the peer sent aux features, + // process them. + p.cfg.AuxChannelNegotiator.WhenSome( + func(acn lnwallet.AuxChannelNegotiator) { + err = acn.ProcessInitRecords( + p.cfg.PubKeyBytes, msg.CustomRecords.Copy(), + ) + }, + ) + if err != nil { + return fmt.Errorf("could not process init records: %w", err) + } + return nil } @@ -4597,6 +4616,30 @@ func (p *Brontide) sendInitMsg(legacyChan bool) error { features.RawFeatureVector, ) + var err error + + // If we have an AuxChannelNegotiator, get custom feature bits to + // include in the init message. + p.cfg.AuxChannelNegotiator.WhenSome( + func(negotiator lnwallet.AuxChannelNegotiator) { + var auxRecords lnwire.CustomRecords + auxRecords, err = negotiator.GetInitRecords( + p.cfg.PubKeyBytes, + ) + if err != nil { + p.log.Warnf("Failed to get aux init features: "+ + "%v", err) + return + } + + mergedRecs := msg.CustomRecords.MergedCopy(auxRecords) + msg.CustomRecords = mergedRecs + }, + ) + if err != nil { + return err + } + return p.writeMessage(msg) } diff --git a/server.go b/server.go index 44be180ea..33b8fd787 100644 --- a/server.go +++ b/server.go @@ -4431,6 +4431,7 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, AuxChanCloser: s.implCfg.AuxChanCloser, AuxResolver: s.implCfg.AuxContractResolver, AuxTrafficShaper: s.implCfg.TrafficShaper, + AuxChannelNegotiator: s.implCfg.AuxChannelNegotiator, ShouldFwdExpEndorsement: func() bool { if s.cfg.ProtocolOptions.NoExperimentalEndorsement() { return false