zebra_network/peer/
minimum_peer_version.rs1use std::fmt;
4
5use zebra_chain::{block::Height, chain_tip::ChainTip, parameters::Network};
6
7use crate::protocol::external::types::Version;
8
9#[cfg(any(test, feature = "proptest-impl"))]
10mod tests;
11
12pub struct MinimumPeerVersion<C> {
15 network: Network,
16 chain_tip: C,
17 current_minimum: Version,
18 has_changed: bool,
19}
20
21impl<C> fmt::Debug for MinimumPeerVersion<C> {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 f.debug_struct(std::any::type_name::<MinimumPeerVersion<C>>())
25 .field("network", &self.network)
26 .field("current_minimum", &self.current_minimum)
27 .field("has_changed", &self.has_changed)
28 .finish()
29 }
30}
31
32impl<C> MinimumPeerVersion<C>
33where
34 C: ChainTip,
35{
36 pub fn new(chain_tip: C, network: &Network) -> Self {
39 MinimumPeerVersion {
40 network: network.clone(),
41 chain_tip,
42 current_minimum: Version::min_remote_for_height(network, None),
43 has_changed: true,
44 }
45 }
46
47 pub fn changed(&mut self) -> Option<Version> {
55 self.update();
56
57 if self.has_changed {
58 self.has_changed = false;
59 Some(self.current_minimum)
60 } else {
61 None
62 }
63 }
64
65 pub fn current(&mut self) -> Version {
67 self.update();
68 self.current_minimum
69 }
70
71 fn update(&mut self) {
74 let height = self.chain_tip.best_tip_height();
75 let new_minimum = Version::min_remote_for_height(&self.network, height);
76
77 if self.current_minimum != new_minimum {
78 self.current_minimum = new_minimum;
79 self.has_changed = true;
80 }
81 }
82
83 pub fn chain_tip_height(&self) -> Height {
87 match self.chain_tip.best_tip_height() {
88 Some(height) => height,
89 None => Height(0),
90 }
91 }
92}
93
94impl<C> Clone for MinimumPeerVersion<C>
97where
98 C: Clone,
99{
100 fn clone(&self) -> Self {
101 MinimumPeerVersion {
102 network: self.network.clone(),
103 chain_tip: self.chain_tip.clone(),
104 current_minimum: self.current_minimum,
105 has_changed: true,
106 }
107 }
108}