use std::{cmp::max, fmt};
use zebra_chain::{
block,
parameters::{
Network::{self, *},
NetworkUpgrade::{self, *},
},
};
use crate::constants::{self, CURRENT_NETWORK_PROTOCOL_VERSION};
#[cfg(any(test, feature = "proptest-impl"))]
use proptest_derive::Arbitrary;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Version(pub u32);
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0.to_string())
}
}
impl Version {
pub fn min_remote_for_height(
network: &Network,
height: impl Into<Option<block::Height>>,
) -> Version {
let height = height.into().unwrap_or(block::Height(0));
let min_spec = Version::min_specified_for_height(network, height);
assert!(
constants::CURRENT_NETWORK_PROTOCOL_VERSION >= min_spec,
"Zebra does not implement the minimum specified {:?} protocol version for {:?} at {:?}",
NetworkUpgrade::current(network, height),
network,
height,
);
max(min_spec, Version::initial_min_for_network(network))
}
fn initial_min_for_network(network: &Network) -> Version {
*constants::INITIAL_MIN_NETWORK_PROTOCOL_VERSION
.get(&network.kind())
.expect("We always have a value for testnet or mainnet")
}
fn min_specified_for_height(network: &Network, height: block::Height) -> Version {
let network_upgrade = NetworkUpgrade::current(network, height);
Version::min_specified_for_upgrade(network, network_upgrade)
}
pub(crate) fn min_specified_for_upgrade(
network: &Network,
network_upgrade: NetworkUpgrade,
) -> Version {
Version(match (network, network_upgrade) {
(_, Genesis) | (_, BeforeOverwinter) => 170_002,
(Testnet(params), Overwinter) if params.is_default_testnet() => 170_003,
(Mainnet, Overwinter) => 170_005,
(Testnet(params), Sapling) if params.is_default_testnet() => 170_007,
(Testnet(params), Sapling) if params.is_regtest() => 170_006,
(Mainnet, Sapling) => 170_007,
(Testnet(params), Blossom) if params.is_default_testnet() => 170_008,
(Mainnet, Blossom) => 170_009,
(Testnet(params), Heartwood) if params.is_default_testnet() => 170_010,
(Mainnet, Heartwood) => 170_011,
(Testnet(params), Canopy) if params.is_default_testnet() => 170_012,
(Mainnet, Canopy) => 170_013,
(Testnet(params), Nu5) if params.is_default_testnet() => 170_050,
(Mainnet, Nu5) => 170_100,
(Testnet(params), Nu6) if params.is_default_testnet() => 170_110,
(Mainnet, Nu6) => 170_120,
(Testnet(_), _) => CURRENT_NETWORK_PROTOCOL_VERSION.0,
})
}
}
bitflags! {
#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct PeerServices: u64 {
const NODE_NETWORK = 1;
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
pub struct Nonce(pub u64);
impl Default for Nonce {
fn default() -> Self {
use rand::{thread_rng, Rng};
Self(thread_rng().gen())
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
pub struct Tweak(pub u32);
impl Default for Tweak {
fn default() -> Self {
use rand::{thread_rng, Rng};
Self(thread_rng().gen())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
pub struct Filter(pub Vec<u8>);
#[cfg(test)]
mod test {
use super::*;
#[test]
fn version_extremes_mainnet() {
version_extremes(&Mainnet)
}
#[test]
fn version_extremes_testnet() {
version_extremes(&Network::new_default_testnet())
}
fn version_extremes(network: &Network) {
let _init_guard = zebra_test::init();
assert_eq!(
Version::min_specified_for_height(network, block::Height(0)),
Version::min_specified_for_upgrade(network, BeforeOverwinter),
);
assert_ne!(
Version::min_specified_for_height(network, block::Height::MAX),
Version::min_specified_for_upgrade(network, BeforeOverwinter),
);
}
#[test]
fn version_consistent_mainnet() {
version_consistent(&Mainnet)
}
#[test]
fn version_consistent_testnet() {
version_consistent(&Network::new_default_testnet())
}
fn version_consistent(network: &Network) {
let _init_guard = zebra_test::init();
let highest_network_upgrade = NetworkUpgrade::current(network, block::Height::MAX);
assert!(highest_network_upgrade == Nu6 || highest_network_upgrade == Nu5,
"expected coverage of all network upgrades: add the new network upgrade to the list in this test");
for &network_upgrade in &[
BeforeOverwinter,
Overwinter,
Sapling,
Blossom,
Heartwood,
Canopy,
Nu5,
Nu6,
] {
let height = network_upgrade.activation_height(network);
if let Some(height) = height {
assert_eq!(
Version::min_specified_for_upgrade(network, network_upgrade),
Version::min_specified_for_height(network, height)
);
}
}
}
}