Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore node announcements for nodes not found in any existing channel #227

Merged

Conversation

halseth
Copy link
Contributor

@halseth halseth commented Jun 26, 2017

As specified in BOLT#7, we should ignore any node announcements for nodes that we have not gotten any channel announcements for. This is to prevent an attacker to DoSing the network by creating a lot of cheap nodes.

  • We are now sending a node announcement (self) after every channel announcement
  • When we receive a channel announcement we are adding a node to the graph which only has the pubkey field set. The rest will be set when a node announcement for the same node is received.

Fixes #138.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still need to take a close look at the tests, but I've completed an initial round of review.


nodePub := node.PubKey.SerializeCompressed()

if err := aliasBucket.Put(nodePub, []byte(node.Alias)); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the scenario that we're adding a partial node, then we don't yet know it's alias.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the order here is off, the alias is written much after the public key. As a result, alias bucket shouldn't yet be updated as we don't have a valid alias for a node if we've only discovered it via a ChannelUpdate message.

@@ -537,6 +538,10 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []l
BitcoinKey2: msg.BitcoinKey2,
AuthProof: proof,
}

// We will add the edge to the channel router. If the nodes present in this
// channel is not present in the database from before, a partial node will
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is not -> are not

Also "from before" can be dropped.

// both of the directed infos that make up the channel.
// As peers are expecting channel announcements before node announcements, we
// first retrieve the initial announcement, as well as the latest channel
// update announcement for both of the directed infos that make up each
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

directed infos -> directed edges

@@ -1246,6 +1246,8 @@ func (f *fundingManager) announceChannel(localIDKey, remoteIDKey, localFundingKe
f.cfg.SendAnnouncement(ann.chanAnn)
f.cfg.SendAnnouncement(ann.chanUpdateAnn)
f.cfg.SendAnnouncement(ann.chanProof)

// TODO: Send node announcement?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After reflecting, I think a node announcement should indeed follow any local announcements we send out.

@@ -828,3 +828,85 @@ func TestOrphanSignatureAnnouncement(t *testing.T) {
t.Fatal("wrong number of objects in storage")
}
}

// We should ignore node announcements of nodes not associated with any
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment should be prefixed with TestOrphanNodeAnnouncement.

Also I'm not sure that this is the correct package for this test. Correct me if I'm wrong, but the underlying logic of ignoring a node announcement if there aren't any matching channels for it is implemented in the router itself.

@halseth halseth force-pushed the channel-announcement-ordering branch from 7a3dcad to b455494 Compare July 12, 2017 13:24
@halseth
Copy link
Contributor Author

halseth commented Jul 12, 2017

I added a new field to the LightningNode struct, HaveNodeAnnouncement, which is set to false if we want to add a node to the graph which we found in a channel announcement. That way we can use the AddLightningNode method to add it to the graph as before, we just return early after writing the pubkey if HaveNodeAnnouncement is false.

Now we also sign and send a new NodeAnnouncement after each channel annoucement, and the test were updated to expect this extra node announcement notification.

@halseth
Copy link
Contributor Author

halseth commented Jul 12, 2017

PTAL

@halseth halseth force-pushed the channel-announcement-ordering branch 2 times, most recently from a581497 to 8fc68b6 Compare July 19, 2017 20:45
@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) to 73.89% when pulling 75abb2c on halseth:channel-announcement-ordering into 78f6caf on lightningnetwork:master.

@halseth halseth force-pushed the channel-announcement-ordering branch from 75abb2c to dbc194b Compare July 20, 2017 09:24
@coveralls
Copy link

Coverage Status

Coverage increased (+0.03%) to 73.898% when pulling dbc194b on halseth:channel-announcement-ordering into 78f6caf on lightningnetwork:master.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just completed a final round of review. I've tested this PR locally, and within a sub-graph of the current Bitcoin testnet deployment and confirmed everything works as advertised. Nice work!

I have a few final comments, none of them major. The most pertinent one is an attempt to ensure that we don't cause extraneous messages to propagate through the network by always updating the timestamp of our NodeAnnouncement each time a channel is funded.

Also this will need to be rebased to the latest master, as there's a conflict in the fundingManager. Within the wallet, what used to be the ChannelDB field is now accessed as wallet.Cfg.Database.

PubKey *btcec.PublicKey

// HaveNodeAnnouncement indicates whether we received a node annoucement
// for this particular node. If true, the remaining fiels will be set,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fiels -> fields

// is only accepted after a channel is known for that particular node,
// and this might be our first channel.
graph := f.cfg.Wallet.ChannelDB.ChannelGraph()
self, err := graph.FetchLightningNode(f.cfg.IDKey)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The graph.SourceNode method can be used in place of FetchLightningNode. Worth noting though that I don't consider this a blocker to merging the PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though my comment above invalidates this comment.

@@ -152,6 +152,10 @@ type fundingConfig struct {
// cannot be located, then an error is returned.
SignMessage func(pubKey *btcec.PublicKey, msg []byte) (*btcec.Signature, error)

// SignNodeAnnouncement is used by the fundingManager to sign the
// updated self node announcements sent after each channel announcement.
SignNodeAnnouncement func(nodeAnn *lnwire.NodeAnnouncement) (*btcec.Signature, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than requesting a signature for a node announcement, we should instead simply be fetching the latest pre-signed NodeAnnouncment. We currently create, and sign one at start up within the Start method of the server struct.

If we take this path, then we avoid unnecessarily updating our the timestamp on our node announcement. By avoiding this update, we save the network a bit of bandwidth as nodes now don't need to add this (unchanged) announcement to their re-broadcast buffers.

Adds a HaveNodeAnnouncement field to the LightningNode
struct, which is used to indicate if we have gotten
all the necessary information to fill the remaining
fields in the struct. If we haven't gotten a node
announcement for this specific node, then we only
know the pubkey, and can only fill that field in
the struct. Still, we should be able to add it to the
channel graph and use it for routes, as long as we
know about channels to this node.
This commit introduces the requirement specified in BOLT#7,
where we ignore any node announcements for a specific node
if we yet haven't seen any channel announcements where this
node takes part. This is to prevent someone DoS-ing the
network with cheap node announcements. In the router this
is enforced by requiring a call to AddNode(node_id) to
be preceded by an AddEdge(edge_id) call, where node_id is
one of the nodes in edge_id.
According to BOLT#7, nodes will ignore node announcements
for nodes not found in any previous channel announcements.
This commit makes the discovery service send its known
channels before its known nodes when syncing the channel
graph with a peer.
Make the fundingmanager send an updated node announcement
each time it opens a new channel. This is to make sure
our node announcement is propagated in the network, since
peers will ignore our node announcements if we haven't
opened any channels yet.
@halseth halseth force-pushed the channel-announcement-ordering branch from dbc194b to 7aada05 Compare August 2, 2017 20:29
@coveralls
Copy link

coveralls commented Aug 2, 2017

Coverage Status

Coverage increased (+0.05%) to 73.785% when pulling 7aada05 on halseth:channel-announcement-ordering into 24db310 on lightningnetwork:master.

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🗼

@Roasbeef Roasbeef merged commit e211270 into lightningnetwork:master Aug 2, 2017
@halseth halseth deleted the channel-announcement-ordering branch July 12, 2018 13:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants