feature: Use the Heartwood protocol version in zebra-network

This commit is contained in:
teor 2020-07-21 18:41:18 +10:00 committed by Henry de Valence
parent e5bb96715f
commit b0cd920fad
6 changed files with 82 additions and 22 deletions

1
Cargo.lock generated
View File

@ -2621,6 +2621,7 @@ dependencies = [
"tracing-error", "tracing-error",
"tracing-futures", "tracing-futures",
"zebra-chain", "zebra-chain",
"zebra-consensus",
"zebra-test", "zebra-test",
] ]

View File

@ -12,6 +12,28 @@
use zebra_chain::block::BlockHeaderHash; use zebra_chain::block::BlockHeaderHash;
use zebra_chain::{Network, Network::*}; use zebra_chain::{Network, Network::*};
/// A Zcash network protocol upgrade.
//
// TODO: are new network upgrades a breaking change, or should we make this
// enum non-exhaustive?
pub enum NetworkUpgrade {
/// The Zcash protocol before the Overwinter upgrade.
///
/// We avoid using `Sprout`, because the specification says that Sprout
/// is the name of the pre-Sapling protocol, before and after Overwinter.
BeforeOverwinter,
/// The Zcash protocol after the Overwinter upgrade.
Overwinter,
/// The Zcash protocol after the Sapling upgrade.
Sapling,
/// The Zcash protocol after the Blossom upgrade.
Blossom,
/// The Zcash protocol after the Heartwood upgrade.
Heartwood,
/// The Zcash protocol after the Canopy upgrade.
Canopy,
}
/// The previous block hash for the genesis block. /// The previous block hash for the genesis block.
/// ///
/// All known networks use the Bitcoin `null` value for the parent of the /// All known networks use the Bitcoin `null` value for the parent of the

View File

@ -17,25 +17,26 @@ hex = "0.4"
# which we don't use, so disable it to drop the dependencies. # which we don't use, so disable it to drop the dependencies.
indexmap = { version = "1.5", default-features = false } indexmap = { version = "1.5", default-features = false }
pin-project = "0.4" pin-project = "0.4"
proptest = "0.10"
proptest-derive = "0.2.0"
rand = "0.7" rand = "0.7"
serde = { version = "1", features = ["serde_derive"] } serde = { version = "1", features = ["serde_derive"] }
thiserror = "1" thiserror = "1"
futures = "0.3"
tokio = { version = "0.2", features = ["net", "time", "stream"] } tokio = { version = "0.2", features = ["net", "time", "stream"] }
tokio-util = { version = "0.2", features = ["codec"] } tokio-util = { version = "0.2", features = ["codec"] }
futures = "0.3"
tracing = "0.1"
tracing-futures = "0.2"
tower = "0.3" tower = "0.3"
tower-load = "0.3" tower-load = "0.3"
metrics = "0.12" metrics = "0.12"
tracing = "0.1"
zebra-chain = { path = "../zebra-chain" } tracing-futures = "0.2"
tracing-error = { version = "0.1.2", features = ["traced-error"] } tracing-error = { version = "0.1.2", features = ["traced-error"] }
zebra-chain = { path = "../zebra-chain" }
zebra-consensus = { path = "../zebra-consensus" }
[dev-dependencies]
proptest = "0.10"
proptest-derive = "0.2.0"
zebra-test = { path = "../zebra-test/" } zebra-test = { path = "../zebra-test/" }

View File

@ -5,6 +5,8 @@ use std::time::Duration;
// XXX should these constants be split into protocol also? // XXX should these constants be split into protocol also?
use crate::protocol::external::types::*; use crate::protocol::external::types::*;
use zebra_consensus::parameters::NetworkUpgrade::{self, *};
/// The timeout for requests made to a remote peer. /// The timeout for requests made to a remote peer.
pub const REQUEST_TIMEOUT: Duration = Duration::from_secs(10); pub const REQUEST_TIMEOUT: Duration = Duration::from_secs(10);
@ -34,11 +36,19 @@ pub const TIMESTAMP_TRUNCATION_SECONDS: i64 = 30 * 60;
/// The User-Agent string provided by the node. /// The User-Agent string provided by the node.
pub const USER_AGENT: &str = "🦓Zebra v2.0.0-alpha.0🦓"; pub const USER_AGENT: &str = "🦓Zebra v2.0.0-alpha.0🦓";
/// The Zcash network protocol version used on mainnet. /// The Zcash network protocol version implemented by this crate.
pub const CURRENT_VERSION: Version = Version(170_009); ///
/// This protocol version might be the current version on Mainnet or Testnet,
/// based on where we are in the network upgrade cycle.
pub const CURRENT_VERSION: Version = Version(170_011);
/// The minimum version supported for peer connections. /// The most recent bilateral consensus upgrade implemented by this crate.
pub const MIN_VERSION: Version = Version(170_009); ///
/// Used to select the minimum supported version for peer connections.
//
// TODO: dynamically choose the minimum network upgrade based on block height.
// See the detailed comment in handshake.rs, where this constant is used.
pub const MIN_NETWORK_UPGRADE: NetworkUpgrade = Heartwood;
/// Magic numbers used to identify different Zcash networks. /// Magic numbers used to identify different Zcash networks.
pub mod magics { pub mod magics {

View File

@ -184,16 +184,20 @@ where
// we would disconnect here if it received a second one. Is it even possible // we would disconnect here if it received a second one. Is it even possible
// for that to happen to us here? // for that to happen to us here?
if remote_version < constants::MIN_VERSION {
// Disconnect if peer is using an obsolete version.
return Err(HandshakeError::ObsoleteVersion(remote_version));
}
// TODO: Reject incoming connections from nodes that don't know about the current epoch. // TODO: Reject incoming connections from nodes that don't know about the current epoch.
// zcashd does this: // zcashd does this:
// const Consensus::Params& consensusParams = chainparams.GetConsensus(); // const Consensus::Params& consensusParams = chainparams.GetConsensus();
// auto currentEpoch = CurrentEpoch(GetHeight(), consensusParams); // auto currentEpoch = CurrentEpoch(GetHeight(), consensusParams);
// if (pfrom->nVersion < consensusParams.vUpgrades[currentEpoch].nProtocolVersion) // if (pfrom->nVersion < consensusParams.vUpgrades[currentEpoch].nProtocolVersion)
//
// For approximately 1.5 days before a network upgrade, we also need to:
// - prefer evicting pre-upgrade peers from the peer set, and
// - prefer choosing post-upgrade ready peers for queries
if remote_version < Version::min_version(network, constants::MIN_NETWORK_UPGRADE) {
// Disconnect if peer is using an obsolete version.
return Err(HandshakeError::ObsoleteVersion(remote_version));
}
// Set the connection's version to the minimum of the received version or our own. // Set the connection's version to the minimum of the received version or our own.
let negotiated_version = std::cmp::min(remote_version, constants::CURRENT_VERSION); let negotiated_version = std::cmp::min(remote_version, constants::CURRENT_VERSION);

View File

@ -1,13 +1,15 @@
#![allow(clippy::unit_arg)] #![allow(clippy::unit_arg)]
use crate::constants::magics;
use std::fmt; use std::fmt;
use zebra_chain::Network::{self, *};
use zebra_consensus::parameters::NetworkUpgrade::{self, *};
#[cfg(test)] #[cfg(test)]
use proptest_derive::Arbitrary; use proptest_derive::Arbitrary;
use zebra_chain::Network;
use crate::constants::magics;
/// A magic number identifying the network. /// A magic number identifying the network.
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(test, derive(Arbitrary))] #[cfg_attr(test, derive(Arbitrary))]
@ -33,6 +35,26 @@ impl From<Network> for Magic {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Version(pub u32); pub struct Version(pub u32);
impl Version {
/// Returns the minimum network protocol version for `network` and
/// `network_upgrade`.
pub fn min_version(network: Network, network_upgrade: NetworkUpgrade) -> Self {
// We might not ever use these older versions.
Version(match (network, network_upgrade) {
(_, BeforeOverwinter) => 170_002,
(Testnet, Overwinter) => 170_003,
(Mainnet, Overwinter) => 170_005,
(_, Sapling) => 170_007,
(Testnet, Blossom) => 170_008,
(Mainnet, Blossom) => 170_009,
(Testnet, Heartwood) => 170_010,
(Mainnet, Heartwood) => 170_011,
(Testnet, Canopy) => 170_012,
(Mainnet, Canopy) => 170_013,
})
}
}
bitflags! { bitflags! {
/// A bitflag describing services advertised by a node in the network. /// A bitflag describing services advertised by a node in the network.
/// ///