Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion channeldb/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -1804,7 +1804,7 @@ func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
currentCommitSecret[0] ^= 1

// If this is a tweakless channel, then we'll purposefully send
// a next local height taht's invalid to trigger a force close
// a next local height that's invalid to trigger a force close
// on their end. We do this as tweakless channels don't require
// that the commitment point is valid, only that it's present.
if c.ChanType.IsTweakless() {
Expand Down
150 changes: 117 additions & 33 deletions discovery/gossiper.go
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,10 @@ func (d *AuthenticatedGossiper) networkHandler() {
sourceToPub(announcement.source),
) {

peer := sourceToPub(announcement.source)
log.Debugf("Throttling messages from peer=%v "+
"(recently rejected)", peer)

announcement.err <- fmt.Errorf("recently " +
"rejected")
continue
Expand Down Expand Up @@ -1927,17 +1931,24 @@ func (d *AuthenticatedGossiper) processRejectedEdge(
msg: chanAnn,
})
if e1Ann != nil {
announcements = append(announcements, networkMsg{
source: d.selfKey,
msg: e1Ann,
})
// Only add the ChanUpdate to the gossiper if the
// __dont_forward__ bit signals it.
if !e1Ann.MessageFlags.HasDontForward() {
announcements = append(announcements, networkMsg{
source: d.selfKey,
msg: e1Ann,
})
}
}
if e2Ann != nil {
announcements = append(announcements, networkMsg{
source: d.selfKey,
msg: e2Ann,
})

// Only add the ChanUpdate to the gossiper if the
// __dont_forward__ bit signals it.
if !e2Ann.MessageFlags.HasDontForward() {
announcements = append(announcements, networkMsg{
source: d.selfKey,
msg: e2Ann,
})
}
}

return announcements, nil
Expand Down Expand Up @@ -2347,6 +2358,18 @@ func IsKeepAliveUpdate(update *lnwire.ChannelUpdate1,
if update.MessageFlags.HasMaxHtlc() && !prev.MessageFlags.HasMaxHtlc() {
return false
}

// Every public channel starts with the dont_forward bit set before the
// mandatory six confirmations are reached. We will see 2 different
// ChanUpdates before a public channel is announced to the broader
// network. We need to make sure we don't consider the second one as a
// keepalive msg.
if !update.MessageFlags.HasDontForward() &&
prev.MessageFlags.HasDontForward() {

return false
}

if update.HtlcMaximumMsat != prev.MaxHTLC {
return false
}
Expand Down Expand Up @@ -2459,6 +2482,10 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

nMsg.err <- err
return nil, false
}
Expand All @@ -2476,6 +2503,10 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

nMsg.err <- err
return nil, false
}
Expand Down Expand Up @@ -2560,6 +2591,10 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

log.Error(err)
nMsg.err <- err
return nil, false
Expand Down Expand Up @@ -2673,6 +2708,10 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

// Increment the peer's ban score. We check isRemote
// so we don't actually ban the peer in case of a local
// bug.
Expand All @@ -2687,6 +2726,10 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

// Since this channel has already been closed, we'll
// add it to the graph's closed channel index such that
// we won't attempt to do expensive validation checks
Expand Down Expand Up @@ -2717,6 +2760,10 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg,
sourceToPub(nMsg.source),
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)
}

if !nMsg.isRemote {
Expand Down Expand Up @@ -2847,6 +2894,10 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

nMsg.err <- err
return nil, false
}
Expand Down Expand Up @@ -2956,9 +3007,9 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
// If the edge corresponding to this ChannelUpdate was not
// found in the graph, this might be a channel in the process
// of being opened, and we haven't processed our own
// ChannelAnnouncement yet, hence it is not not found in the
// graph. This usually gets resolved after the channel proofs
// are exchanged and the channel is broadcasted to the rest of
// ChannelAnnouncement yet, hence it is not found in the graph.
// This usually gets resolved after the channel proofs are
// exchanged and the channel is broadcasted to the rest of
// the network, but in case this is a private channel this
// won't ever happen. This can also happen in the case of a
// zombie channel with a fresh update for which we don't have a
Expand Down Expand Up @@ -3014,6 +3065,10 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

return nil, false
}

Expand Down Expand Up @@ -3143,6 +3198,10 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
)
_, _ = d.recentRejects.Put(key, &cachedReject{})

log.Debugf("Adding msg short_chan_id(%v) from "+
"peer=%x to RejectCache", key.chanID,
key.pubkey)

log.Errorf("Update edge for short_chan_id(%v) got: %v",
shortChanID, err)
}
Expand All @@ -3151,6 +3210,11 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
return nil, false
}

// Get our peer's public key.
remotePubKey := remotePubFromChanInfo(
chanInfo, upd.ChannelFlags,
)

// If this is a local ChannelUpdate without an AuthProof, it means it
// is an update to a channel that is not (yet) supposed to be announced
// to the greater network. However, our channel counter party will need
Expand Down Expand Up @@ -3186,11 +3250,6 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
}
}

// Get our peer's public key.
remotePubKey := remotePubFromChanInfo(
chanInfo, upd.ChannelFlags,
)

log.Debugf("The message %v has no AuthProof, sending the "+
"update to remote peer %x", upd.MsgType(), remotePubKey)

Expand All @@ -3214,12 +3273,29 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
// contains an alias because the network would reject this.
var announcements []networkMsg
if chanInfo.AuthProof != nil && !d.cfg.IsAlias(upd.ShortChannelID) {
announcements = append(announcements, networkMsg{
peer: nMsg.peer,
source: nMsg.source,
isRemote: nMsg.isRemote,
msg: upd,
})
// We log the case where the dont_forward bit is set although
// the channel is already announced to the network because we
// already have a AuthProof for it. In addition we do not add
// this msg to the gossip msg queue to make sure we follow the
// network rules.
if upd.MessageFlags.HasDontForward() {
log.Warnf("Received %v with the dont_forward bit set "+
"(msgflags=%s) for channel=%v from peer=%x "+
"for an announced channel, not forwarding to "+
"the broader network",
upd.MsgType().String(),
upd.MessageFlags.String(),
upd.ShortChannelID.ToUint64(),
remotePubKey,
)
} else {
announcements = append(announcements, networkMsg{
peer: nMsg.peer,
source: nMsg.source,
isRemote: nMsg.isRemote,
msg: upd,
})
}
}

nMsg.err <- nil
Expand Down Expand Up @@ -3495,18 +3571,26 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
msg: chanAnn,
})
if src, err := chanInfo.NodeKey1(); err == nil && e1Ann != nil {
announcements = append(announcements, networkMsg{
peer: nMsg.peer,
source: src,
msg: e1Ann,
})
// Only add the ChanUpdate to the gossiper if the
// __dont_forward__ bit signals it.
if !e1Ann.MessageFlags.HasDontForward() {
announcements = append(announcements, networkMsg{
peer: nMsg.peer,
source: src,
msg: e1Ann,
})
}
}
if src, err := chanInfo.NodeKey2(); err == nil && e2Ann != nil {
announcements = append(announcements, networkMsg{
peer: nMsg.peer,
source: src,
msg: e2Ann,
})
// Only add the ChanUpdate to the gossiper if the
// __dont_forward__ bit signals it.
if !e2Ann.MessageFlags.HasDontForward() {
announcements = append(announcements, networkMsg{
peer: nMsg.peer,
source: src,
msg: e2Ann,
})
}
}

// We'll also send along the node announcements for each channel
Expand Down
21 changes: 19 additions & 2 deletions discovery/gossiper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3214,15 +3214,32 @@ func TestSendChannelUpdateReliably(t *testing.T) {
require.NoError(t, err, "unable to process remote channel proof")

// Now that we've constructed our full proof, we can assert that the
// channel has been announced.
// channel has been announced. We anticipate the local ChanAnnouncement
// and the local ChanUpdate.
gotChannelAnnouncement := false
gotChannelUpdate := false
for i := 0; i < 2; i++ {
select {
case <-ctx.broadcastedMessage:
case gossip := <-ctx.broadcastedMessage:
switch msg := gossip.msg.(type) {
case *lnwire.ChannelUpdate1:
gotChannelUpdate = true
case *lnwire.ChannelAnnouncement1:
gotChannelAnnouncement = true
default:
t.Fatalf("send unexpected %v "+
"message", msg.MsgType())
}
case <-time.After(2 * trickleDelay):
t.Fatal("expected channel to be announced")
}
}

require.Truef(
t, gotChannelAnnouncement, "did not receive ChanAnnouncement",
)
require.Truef(t, gotChannelUpdate, "did not receive ChanUpdate")

// With the channel announced, we'll generate a new channel update. This
// one won't take the path of the reliable sender, as the channel has
// already been announced. We'll keep track of the old message that is
Expand Down
8 changes: 8 additions & 0 deletions docs/release-notes/release-notes-0.19.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
* [Fixed a bug](https://github.com/lightningnetwork/lnd/pull/9322) that caused
estimateroutefee to ignore the default payment timeout.

* [Make reassignment of alias channel edges atomic](
https://github.com/lightningnetwork/lnd/pull/8777). This fixes an edge case
where we might rate limit a peer because he already sent us a channel update
with the confirmed channel ID but the graph was still not updated.

# New Features

* [Support](https://github.com/lightningnetwork/lnd/pull/8390) for
Expand Down Expand Up @@ -94,6 +99,9 @@
are now [sorted](https://github.com/lightningnetwork/lnd/pull/9337) based on
the `InvoiceHTLC.HtlcIndex`.

* Make sure to [set the dont_forward msg flag in the channel update msg
for unannounced channels](https://github.com/lightningnetwork/lnd/pull/8582).

## lncli Additions

* [A pre-generated macaroon root key can now be specified in `lncli create` and
Expand Down
Loading