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

Disconnect from outdated peers on network upgrade #3108

Conversation

jvff
Copy link
Contributor

@jvff jvff commented Nov 28, 2021

Motivation

Zebra should disconnect from outdated peers when a network upgrade is activated.

Specifications

Overwinter nodes should take steps to:

[...]

  • disconnect any existing connections to pre-Overwinter nodes.

https://zips.z.cash/zip-0201#rejecting-pre-overwinter-connections

Solution

  • create a LoadTrackedClient that wraps a load tracked client service and keeps track of the peer's reported protocol version
  • create a PeerDiscoverer type that prepares discovered peers into LoadTrackedClients
  • disconnect from outdated peers stored in ready_services once the minimum peer version changes
  • avoid adding unready services for outdated peers
  • avoid adding ready services for outdated peers

Review

@teor2345 can review this. It's still in draft because I haven't written any tests yet.

Reviewer Checklist

  • Code implements Specs and Designs
  • Tests for Expected Behaviour
  • Tests for Errors

Follow Up Work

@zfnd-bot zfnd-bot bot assigned jvff Nov 28, 2021
Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

This looks great, thanks for your hard work on this!

The new design avoids the issues with smuggling the version in the Discover::Key. (I was concerned I would have to review every existing key use, to make sure the hidden version was handled correctly. But this design avoids that problem entirely.)

I've suggested some behaviour and module changes that we should fix before writing the tests. Or feel free to skip them.

I also have a bunch of minor questions and nitpicks.
Edit: I've marked some minor issues as resolved, so we can focus on the changes that might cause test rework.

zebra-network/src/discoverer.rs Outdated Show resolved Hide resolved
zebra-network/src/discoverer.rs Outdated Show resolved Hide resolved
zebra-network/src/discoverer.rs Outdated Show resolved Hide resolved
zebra-network/src/discoverer.rs Outdated Show resolved Hide resolved
zebra-network/src/discoverer.rs Outdated Show resolved Hide resolved
zebra-network/src/discoverer.rs Outdated Show resolved Hide resolved
zebra-network/src/peer_set/initialize.rs Outdated Show resolved Hide resolved
zebra-network/src/peer_set/set.rs Show resolved Hide resolved
zebra-network/src/peer_set/set.rs Show resolved Hide resolved
zebra-network/src/peer_set/set.rs Outdated Show resolved Hide resolved
@teor2345
Copy link
Contributor

teor2345 commented Nov 29, 2021

I think we can close #2262 without any disconnection rate limits, because:

  • ready peer connections are closed immediately
  • unready peer connections are closed when their requests complete

So that provides enough natural rate-limiting on busy peers. And on peers that aren't busy, the rate-limits don't matter, they'll just slowly re-open connections as needed.

But we should document this behaviour somewhere, so we know why it's ok.

What do you think?

@mpguerra mpguerra linked an issue Nov 29, 2021 that may be closed by this pull request
8 tasks
@jvff jvff force-pushed the disconnect-from-outdated-peers-on-network-upgrade branch from 037da4b to ef0d790 Compare December 1, 2021 02:34
@jvff jvff requested review from teor2345 December 1, 2021 02:38
@jvff
Copy link
Contributor Author

jvff commented Dec 1, 2021

Before Tests Question: This type is really complicated, I'm wondering if we could use a stream mapping instead?

Thanks for this, it's a great idea! It allowed me to simplify the code quite a bit :)

Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Looks good, I think we're getting down to the last few bugs.

I've un-resolved some minor nitpicks as well.

zebra-network/src/constants.rs Show resolved Hide resolved
zebra-network/src/peer_set/initialize.rs Show resolved Hide resolved
zebra-network/src/peer_set/set.rs Outdated Show resolved Hide resolved
zebra-network/src/peer_set/set.rs Show resolved Hide resolved
zebra-network/src/peer_set/set.rs Show resolved Hide resolved
@jvff jvff force-pushed the disconnect-from-outdated-peers-on-network-upgrade branch 2 times, most recently from 783a891 to 32f0417 Compare December 2, 2021 01:22
Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Looks great!

We're just tweaking comments now, so feel free to merge once you're happy with the tests.

@jvff jvff force-pushed the disconnect-from-outdated-peers-on-network-upgrade branch from 32f0417 to 77d55ad Compare December 3, 2021 01:51
@jvff jvff requested a review from teor2345 December 3, 2021 01:51
Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Looks good, let me know if you'd like help with the tests

@jvff jvff force-pushed the disconnect-from-outdated-peers-on-network-upgrade branch from 0f1e426 to 51831c5 Compare December 8, 2021 22:36
Remove the assumption that a `Remove` variant would never be created
with type changes that allow the compiler to guarantee that assumption.
Keep track of the peer's reported protocol version.
A `peer::Client` type wrapper that implements `Load`. This helps with
the creation of a client service that has extra peer information to be
accessed without having to send requests.
Ensure that `PeerSet` receives `LoadTrackedClient`s so that it will be
able to query the peer's protocol version later on.
Replace the generic type with a concrete `LoadTrackedClient` so that we
can query its version.
A type to track the current minimum protocol version for connected
peers based on the current block height.
Keep the code to obtain the current minimum peer protocol version in a
central place.
Prepare it to be able to disconnect from outdated peers based on the
current minimum supported peer protocol version.
When the minimum peer protocol version is detected to have changed
(because of a network upgrade), remove all ready services of peers that
became outdated.
Only add an unready service if it's for a peer that has a supported
protocol version. Otherwise, add it but drop the cancel handle so that
the `UnreadyService` can execute and detect that it was cancelled.
jvff and others added 14 commits December 9, 2021 00:54
If a service becomes ready but it's for a connection to an outdated
peer, drop it.
Describe an edge case that is also handled but was not explicit.

Co-authored-by: teor <teor@riseup.net>
Given an arbitrary best chain tip height, check that the calculated
minimum peer protocol version is the expected value.
Apply an arbitrary list of chain tip height updates and check that for
each update the minimum peer version is calculated correctly.
Simulate a series of best chain tip height updates, and check for
minimum peer version updates at least once between them. Changes should
only be reported once.
Used to create and then track a mock `Client` instance.
An extension method useful for tests, that contains some shared
boilerplate code.
Give a 50% chance for an arbitrary `Version` to be in the range of
previously used values the Zcash network.
Helps with the creation of mocked client services with arbitrary
protocol versions.
An auxiliary type to a `PeerSet` instance created for testing. It keeps
track of any dummy endpoints of channels created and passed to the
`PeerSet` instance.
Helps to reduce the code when preparing a `PeerSet` test instance.
Simulate a set of discovered peers being sent to the `PeerSet`. Ensure
that only up-to-date peers are kept by the `PeerSet` and that outdated
peers are dropped.
A helper type that allows the creation of arbitrary block height pairs,
where one value is before and the other is at or after the activation
height of an arbitrary network upgrade.
Simulate a network upgrade, and check that peers that become outdated
are dropped by the `PeerSet`.
@jvff jvff force-pushed the disconnect-from-outdated-peers-on-network-upgrade branch from 51831c5 to cb0f2ee Compare December 9, 2021 00:57
@jvff jvff marked this pull request as ready for review December 9, 2021 01:18
@jvff jvff requested a review from teor2345 December 9, 2021 01:19
teor2345
teor2345 previously approved these changes Dec 9, 2021
Copy link
Contributor

@teor2345 teor2345 left a comment

Choose a reason for hiding this comment

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

Looks good, merging now to unblock the notfound work in this sprint.

I have a minor suggestion that we can fix in a follow-up PR or ticket.

@teor2345 teor2345 merged commit 0ad89f2 into ZcashFoundation:main Dec 9, 2021
@jvff jvff deleted the disconnect-from-outdated-peers-on-network-upgrade branch December 9, 2021 13:35
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.

After network upgrade activation, close existing connections to outdated peers
2 participants