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

Only sync with channel peers #1587

Merged
merged 7 commits into from
Feb 4, 2021
Merged

Only sync with channel peers #1587

merged 7 commits into from
Feb 4, 2021

Conversation

t-bast
Copy link
Member

@t-bast t-bast commented Nov 5, 2020

Our previous behaviour was to do a full routing table sync whenever we connected to a node (or a node connected to us).
This was wasting a lot of bandwidth for no reason.

Instead, we only sync with nodes that are either:

  • in our sync whitelist
  • have channels with us

On top of that, we trigger a sync whenever our first channel is opened with a new peer: this ensures we following flow works:

  • connect to a new node
  • we don't have channels together yet, so we're not syncing
  • open a channel
  • once the channel is open, sync the routing table
  • we can now make payments (yay!)

The syncing state is a bit hard to read: we've started discussions in the spec to make changes to channel queries (see lightning/bolts#804 and lightning/bolts#811), it will be a good opportunity to refactor the code later.

@codecov-io
Copy link

codecov-io commented Dec 8, 2020

Codecov Report

Merging #1587 (5d388ad) into master (34e901d) will decrease coverage by 0.01%.
The diff coverage is 93.33%.

@@            Coverage Diff             @@
##           master    #1587      +/-   ##
==========================================
- Coverage   85.93%   85.91%   -0.02%     
==========================================
  Files         151      151              
  Lines       11430    11452      +22     
  Branches      497      488       -9     
==========================================
+ Hits         9822     9839      +17     
- Misses       1608     1613       +5     
Impacted Files Coverage Δ
...cinq/eclair/remote/EclairInternalsSerializer.scala 97.43% <ø> (ø)
...a/fr/acinq/eclair/wire/LightningMessageTypes.scala 86.36% <ø> (ø)
...main/scala/fr/acinq/eclair/router/Validation.scala 90.76% <33.33%> (-1.90%) ⬇️
...src/main/scala/fr/acinq/eclair/router/Router.scala 93.58% <50.00%> (+0.03%) ⬆️
...main/scala/fr/acinq/eclair/io/PeerConnection.scala 81.89% <81.81%> (-0.04%) ⬇️
...-core/src/main/scala/fr/acinq/eclair/io/Peer.scala 89.83% <100.00%> (+0.16%) ⬆️
...rc/main/scala/fr/acinq/eclair/io/Switchboard.scala 81.08% <100.00%> (+2.95%) ⬆️
...e/src/main/scala/fr/acinq/eclair/router/Sync.scala 98.36% <100.00%> (+0.06%) ⬆️
...nq/eclair/blockchain/electrum/ElectrumWallet.scala 80.25% <0.00%> (-0.26%) ⬇️
... and 1 more

@t-bast t-bast requested a review from pm47 December 16, 2020 07:55
Copy link
Member

@pm47 pm47 left a comment

Choose a reason for hiding this comment

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

Just a first pass.

sstone
sstone previously approved these changes Jan 22, 2021
This reduces the bandwidth used: it doesn't make sense to sync with every
node that connects to us.

We also better track sync requests, to reject unsolicited sync responses.

To ensure that nodes don't need to explicitly reconnect after creating
their first channel in order to get the routing table, we add a mechanism
to trigger a sync when the first channel is created.
If our peer doesn't support gossip queries, we'll have sync-ed with him
with `initial_routing_sync` right after `init`.
Comment on lines 99 to 101
case Some(currentSync) if currentSync.remainingQueries.isEmpty && r.shortChannelIds.array.isEmpty =>
log.info("received empty reply_channel_range, sync is complete")
d.copy(sync = d.sync - origin.nodeId)
Copy link
Member

Choose a reason for hiding this comment

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

This isn't how the spec indicates that we should detect the last reply_channel_range message:

the final reply_channel_range message:
MUST have first_blocknum plus number_of_blocks equal or greater than the query_channel_range first_blocknum plus number_of_blocks.

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, this is probably a leftover made to handle nodes that didn't correctly signal termination?
I'll look into it.
Note that we'll be bringing back the complete field which will greatly simplify our lives.

Copy link
Member Author

Choose a reason for hiding this comment

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

This case doesn't handle the normal termination of reply_channel_range, it deals with a special case where the first reply_channel_range is empty (meaning the remote node doesn't want to send us anything basically). Otherwise we'll have something in remainingQueries and we'll wait for these to complete before we consider the sync done. I had to add this because we have a test case for it.

An interesting note is that we don't detect the end of a reply_channel_range at all: we rely on reply_short_channel_ids_end and the fact that our remainingQueries is empty. That's different from the spec and should be fixed. In practice it will very likely work (we've always had this behavior and we've been fine) and it's orthogonal to this PR since it was our previous behavior. I think that can be fixed in a later PR (and we can wait to rely on the complete field for a cleaner signal that the sync is complete once we correctly set it again).

Copy link
Member

Choose a reason for hiding this comment

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

Maybe you should include your reply as a TODO note here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in 8f292b9 and added to my todo list.

pm47
pm47 previously approved these changes Feb 4, 2021
Comment on lines 99 to 101
case Some(currentSync) if currentSync.remainingQueries.isEmpty && r.shortChannelIds.array.isEmpty =>
log.info("received empty reply_channel_range, sync is complete")
d.copy(sync = d.sync - origin.nodeId)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe you should include your reply as a TODO note here?

@t-bast t-bast merged commit ac054a2 into master Feb 4, 2021
@t-bast t-bast deleted the sync-nodes-with-channels branch February 4, 2021 14:27
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.

4 participants