diff --git a/discovery/chan_series.go b/discovery/chan_series.go index ed7140d7d..cf502694c 100644 --- a/discovery/chan_series.go +++ b/discovery/chan_series.go @@ -231,6 +231,13 @@ func (c *ChanSeries) UpdatesInHorizon(chain chainhash.Hash, return nil, err } + if err := netann.ValidateNodeAnnFields(nodeUpdate); err != nil { + log.Debugf("Skipping forwarding invalid node "+ + "announcement %x: %v", nodeAnn.PubKeyBytes, err) + + continue + } + updates = append(updates, nodeUpdate) } @@ -282,6 +289,7 @@ func (c *ChanSeries) FilterChannelRange(_ chainhash.Hash, startHeight, // to reply to a QueryShortChanIDs message sent by a remote peer. The response // will contain a unique set of ChannelAnnouncements, the latest ChannelUpdate // for each of the announcements, and a unique set of NodeAnnouncements. +// Invalid node announcements are skipped and logged for debugging purposes. // // NOTE: This is part of the ChannelGraphTimeSeries interface. func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash, @@ -335,8 +343,15 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash, return nil, err } - chanAnns = append(chanAnns, nodeAnn) - nodePubsSent[nodePub] = struct{}{} + err = netann.ValidateNodeAnnFields(nodeAnn) + if err != nil { + log.Debugf("Skipping forwarding "+ + "invalid node announcement "+ + "%x: %v", nodeAnn.NodeID, err) + } else { + chanAnns = append(chanAnns, nodeAnn) + nodePubsSent[nodePub] = struct{}{} + } } } if edge2 != nil { @@ -354,8 +369,15 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash, return nil, err } - chanAnns = append(chanAnns, nodeAnn) - nodePubsSent[nodePub] = struct{}{} + err = netann.ValidateNodeAnnFields(nodeAnn) + if err != nil { + log.Debugf("Skipping forwarding "+ + "invalid node announcement "+ + "%x: %v", nodeAnn.NodeID, err) + } else { + chanAnns = append(chanAnns, nodeAnn) + nodePubsSent[nodePub] = struct{}{} + } } } } diff --git a/discovery/gossiper.go b/discovery/gossiper.go index c720a6129..f24286ad9 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -2229,7 +2229,9 @@ func (d *AuthenticatedGossiper) processZombieUpdate(_ context.Context, } // fetchNodeAnn fetches the latest signed node announcement from our point of -// view for the node with the given public key. +// view for the node with the given public key. It also validates the node +// announcement fields and returns an error if they are invalid to prevent +// forwarding invalid node announcements to our peers. func (d *AuthenticatedGossiper) fetchNodeAnn(ctx context.Context, pubKey [33]byte) (*lnwire.NodeAnnouncement, error) { @@ -2238,7 +2240,12 @@ func (d *AuthenticatedGossiper) fetchNodeAnn(ctx context.Context, return nil, err } - return node.NodeAnnouncement(true) + nodeAnn, err := node.NodeAnnouncement(true) + if err != nil { + return nil, err + } + + return nodeAnn, netann.ValidateNodeAnnFields(nodeAnn) } // isMsgStale determines whether a message retrieved from the backing