1use std::{cmp::max, fmt};
23use zebra_chain::{
4 block,
5 parameters::{
6 Network::{self, *},
7 NetworkUpgrade::{self, *},
8 },
9};
1011use crate::constants::{self, CURRENT_NETWORK_PROTOCOL_VERSION};
1213#[cfg(any(test, feature = "proptest-impl"))]
14use proptest_derive::Arbitrary;
1516/// A protocol version number.
17#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
18pub struct Version(pub u32);
1920impl fmt::Display for Version {
21fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 f.write_str(&self.0.to_string())
23 }
24}
2526impl Version {
27/// Returns the minimum remote node network protocol version for `network` and
28 /// `height`. Zebra disconnects from peers with lower versions.
29 ///
30 /// # Panics
31 ///
32 /// If we are incompatible with our own minimum remote protocol version.
33pub fn min_remote_for_height(
34 network: &Network,
35 height: impl Into<Option<block::Height>>,
36 ) -> Version {
37let height = height.into().unwrap_or(block::Height(0));
38let min_spec = Version::min_specified_for_height(network, height);
3940// shut down if our own version is too old
41assert!(
42 constants::CURRENT_NETWORK_PROTOCOL_VERSION >= min_spec,
43"Zebra does not implement the minimum specified {:?} protocol version for {:?} at {:?}",
44 NetworkUpgrade::current(network, height),
45 network,
46 height,
47 );
4849 max(min_spec, Version::initial_min_for_network(network))
50 }
5152/// Returns the minimum supported network protocol version for `network`.
53 ///
54 /// This is the minimum peer version when Zebra is significantly behind current tip:
55 /// - during the initial block download,
56 /// - after Zebra restarts, and
57 /// - after Zebra's local network is slow or shut down.
58fn initial_min_for_network(network: &Network) -> Version {
59*constants::INITIAL_MIN_NETWORK_PROTOCOL_VERSION
60 .get(&network.kind())
61 .expect("We always have a value for testnet or mainnet")
62 }
6364/// Returns the minimum specified network protocol version for `network` and
65 /// `height`.
66 ///
67 /// This is the minimum peer version when Zebra is close to the current tip.
68fn min_specified_for_height(network: &Network, height: block::Height) -> Version {
69let network_upgrade = NetworkUpgrade::current(network, height);
70 Version::min_specified_for_upgrade(network, network_upgrade)
71 }
7273/// Returns the minimum specified network protocol version for `network` and
74 /// `network_upgrade`.
75 ///
76 /// ## ZIP-253
77 ///
78 /// > Nodes compatible with a network upgrade activation MUST advertise a network protocol
79 /// > version that is greater than or equal to the MIN_NETWORK_PROTOCOL_VERSION for that
80 /// > activation.
81 ///
82 /// <https://zips.z.cash/zip-0253>
83 ///
84 /// ### Notes
85 ///
86 /// - The citation above is a generalization of a statement in ZIP-253 since that ZIP is
87 /// concerned only with NU6 on Mainnet and Testnet.
88pub(crate) fn min_specified_for_upgrade(
89 network: &Network,
90 network_upgrade: NetworkUpgrade,
91 ) -> Version {
92 Version(match (network, network_upgrade) {
93 (_, Genesis) | (_, BeforeOverwinter) => 170_002,
94 (Testnet(params), Overwinter) if params.is_default_testnet() => 170_003,
95 (Mainnet, Overwinter) => 170_005,
96 (Testnet(params), Sapling) if params.is_default_testnet() => 170_007,
97 (Testnet(params), Sapling) if params.is_regtest() => 170_006,
98 (Mainnet, Sapling) => 170_007,
99 (Testnet(params), Blossom) if params.is_default_testnet() => 170_008,
100 (Mainnet, Blossom) => 170_009,
101 (Testnet(params), Heartwood) if params.is_default_testnet() => 170_010,
102 (Mainnet, Heartwood) => 170_011,
103 (Testnet(params), Canopy) if params.is_default_testnet() => 170_012,
104 (Mainnet, Canopy) => 170_013,
105 (Testnet(params), Nu5) if params.is_default_testnet() => 170_050,
106 (Mainnet, Nu5) => 170_100,
107 (Testnet(params), Nu6) if params.is_default_testnet() => 170_110,
108 (Mainnet, Nu6) => 170_120,
109 (Testnet(params), Nu6_1) if params.is_default_testnet() => 170_130,
110 (Mainnet, Nu6_1) => 170_140,
111 (Testnet(params), Nu7) if params.is_default_testnet() => 170_150,
112 (Mainnet, Nu7) => 170_160,
113114// It should be fine to reject peers with earlier network protocol versions on custom testnets for now.
115(Testnet(_), _) => CURRENT_NETWORK_PROTOCOL_VERSION.0,
116 })
117 }
118}
119120bitflags! {
121/// A bitflag describing services advertised by a node in the network.
122 ///
123 /// Note that bits 24-31 are reserved for temporary experiments; other
124 /// service bits should be allocated via the ZIP process.
125#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
126pub struct PeerServices: u64 {
127/// NODE_NETWORK means that the node is a full node capable of serving
128 /// blocks, as opposed to a light client that makes network requests but
129 /// does not provide network services.
130const NODE_NETWORK = 1;
131 }
132}
133134/// A nonce used in the networking layer to identify messages.
135#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
136#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
137pub struct Nonce(pub u64);
138139impl Default for Nonce {
140fn default() -> Self {
141use rand::{thread_rng, Rng};
142Self(thread_rng().gen())
143 }
144}
145146/// A random value to add to the seed value in a hash function.
147#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
148#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
149pub struct Tweak(pub u32);
150151impl Default for Tweak {
152fn default() -> Self {
153use rand::{thread_rng, Rng};
154Self(thread_rng().gen())
155 }
156}
157158/// A Bloom filter consisting of a bit field of arbitrary byte-aligned
159/// size, maximum size is 36,000 bytes.
160#[derive(Clone, Debug, Eq, PartialEq)]
161#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
162pub struct Filter(pub Vec<u8>);
163164#[cfg(test)]
165mod test {
166use super::*;
167168#[test]
169fn version_extremes_mainnet() {
170 version_extremes(&Mainnet)
171 }
172173#[test]
174fn version_extremes_testnet() {
175 version_extremes(&Network::new_default_testnet())
176 }
177178/// Test the min_specified_for_upgrade and min_specified_for_height functions for `network` with
179 /// extreme values.
180fn version_extremes(network: &Network) {
181let _init_guard = zebra_test::init();
182183assert_eq!(
184 Version::min_specified_for_height(network, block::Height(0)),
185 Version::min_specified_for_upgrade(network, BeforeOverwinter),
186 );
187188// We assume that the last version we know about continues forever
189 // (even if we suspect that won't be true)
190assert_ne!(
191 Version::min_specified_for_height(network, block::Height::MAX),
192 Version::min_specified_for_upgrade(network, BeforeOverwinter),
193 );
194 }
195196#[test]
197fn version_consistent_mainnet() {
198 version_consistent(&Mainnet)
199 }
200201#[test]
202fn version_consistent_testnet() {
203 version_consistent(&Network::new_default_testnet())
204 }
205206/// Check that the min_specified_for_upgrade and min_specified_for_height functions
207 /// are consistent for `network`.
208fn version_consistent(network: &Network) {
209let _init_guard = zebra_test::init();
210211let highest_network_upgrade = NetworkUpgrade::current(network, block::Height::MAX);
212assert!(
213matches!(highest_network_upgrade, Nu6 | Nu6_1 | Nu7),
214"expected coverage of all network upgrades: \
215 add the new network upgrade to the list in this test"
216);
217218for &network_upgrade in &[
219 BeforeOverwinter,
220 Overwinter,
221 Sapling,
222 Blossom,
223 Heartwood,
224 Canopy,
225 Nu5,
226 Nu6,
227 Nu6_1,
228 Nu7,
229 ] {
230let height = network_upgrade.activation_height(network);
231if let Some(height) = height {
232assert_eq!(
233 Version::min_specified_for_upgrade(network, network_upgrade),
234 Version::min_specified_for_height(network, height)
235 );
236 }
237 }
238 }
239}