From 7bc2f0ac278da7099969ddaea5ad6dc0ffe441c5 Mon Sep 17 00:00:00 2001 From: Janito Vaqueiro Ferreira Filho Date: Mon, 13 Dec 2021 07:17:20 -0300 Subject: [PATCH] Describe `PeerSet`s behavior at a network upgrade (#3181) ZIP-201 describes how a Zcash node should behave when it reaches a network upgrade activation height. Zebra doesn't implement all the details specified there, so we need to document what it does implement and what it doesn't and why. --- zebra-network/src/peer_set/set.rs | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/zebra-network/src/peer_set/set.rs b/zebra-network/src/peer_set/set.rs index 39e57615..9735be21 100644 --- a/zebra-network/src/peer_set/set.rs +++ b/zebra-network/src/peer_set/set.rs @@ -41,6 +41,53 @@ //! [finagle]: https://twitter.github.io/finagle/guide/Clients.html#power-of-two-choices-p2c-least-loaded //! [p2c]: http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf //! [tower-balance]: https://crates.io/crates/tower-balance +//! +//! # Behavior During Network Upgrades +//! +//! [ZIP-201] specifies peer behavior during network upgrades: +//! +//! > With scheduled network upgrades, at the activation height, nodes on each consensus branch +//! > should disconnect from nodes on other consensus branches and only accept new incoming +//! > connections from nodes on the same consensus branch. +//! +//! Zebra handles this with the help of [`MinimumPeerVersion`], which determines the minimum peer +//! protocol version to accept based on the current best chain tip height. The minimum version is +//! therefore automatically increased when the block height reaches a network upgrade's activation +//! height. The helper type is then used to: +//! +//! - cancel handshakes to outdated peers, in +//! [`handshake::negotiate_version`][crate::peer::handshake::negotiate_version] +//! - cancel requests to and disconnect from peers that have become outdated, in +//! [`PeerSet::push_unready`] +//! - disconnect from peers that have just responded and became outdated, in +//! [`PeerSet::poll_unready`] +//! - disconnect from idle peers that have become outdated, in +//! [`PeerSet::disconnect_from_outdated_peers`] +//! +//! ## Network Coalescence +//! +//! [ZIP-201] also specifies how Zcashd behaves [leading up to a activation +//! height][network-coalescence]. Since Zcashd limits the number of connections to at most eight +//! peers, it will gradually migrate its connections to up-to-date peers as it approaches the +//! activation height. +//! +//! The motivation for this behavior is to avoid an abrupt partitioning the network, which can lead +//! to isolated peers and increases the chance of an eclipse attack on some peers of the network. +//! +//! Zebra does not gradually migrate its peers as it approaches an activation height. This is +//! because Zebra by default can connect to up to 75 peers, as can be seen in [`Config::default`]. +//! Since this is a lot larger than the 8 peers Zcashd connects to, an eclipse attack becomes a lot +//! more costly to execute, and the probability of an abrupt network partition that isolates peers +//! is lower. +//! +//! Even if a Zebra node is manually configured to connect to a smaller number of peers, the +//! [`AddressBook`] is configured to hold a large number of peer addresses +//! ([`MAX_ADDRS_IN_ADDRESS_BOOK`]). Since the address book prioritizes addresses it trusts (like +//! those that it has successfully connected to before), the node should be able to recover and +//! rejoin the network by itself, as long as the address book is populated with enough entries. +//! +//! [ZIP-201]: https://zips.z.cash/zip-0201 +//! [network-coalescence]: https://zips.z.cash/zip-0201#network-coalescence use std::{ collections::{HashMap, HashSet},