zebra_chain/parameters/
network.rs1use std::{fmt, str::FromStr, sync::Arc};
4
5use thiserror::Error;
6
7use crate::{
8 block::{self, Height},
9 parameters::NetworkUpgrade,
10};
11
12pub mod magic;
13pub mod subsidy;
14pub mod testnet;
15
16#[cfg(test)]
17mod tests;
18
19#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
24pub enum NetworkKind {
25 #[default]
27 Mainnet,
28
29 Testnet,
31
32 Regtest,
34}
35
36impl From<Network> for NetworkKind {
37 fn from(net: Network) -> Self {
38 NetworkKind::from(&net)
39 }
40}
41
42impl From<&Network> for NetworkKind {
43 fn from(net: &Network) -> Self {
44 net.kind()
45 }
46}
47
48#[derive(Clone, Default, Eq, PartialEq, Serialize)]
50#[serde(into = "NetworkKind")]
51pub enum Network {
52 #[default]
54 Mainnet,
55
56 Testnet(Arc<testnet::Parameters>),
59}
60
61impl NetworkKind {
62 pub fn b58_pubkey_address_prefix(self) -> [u8; 2] {
65 match self {
66 Self::Mainnet => zcash_primitives::constants::mainnet::B58_PUBKEY_ADDRESS_PREFIX,
67 Self::Testnet | Self::Regtest => {
68 zcash_primitives::constants::testnet::B58_PUBKEY_ADDRESS_PREFIX
69 }
70 }
71 }
72
73 pub fn b58_script_address_prefix(self) -> [u8; 2] {
76 match self {
77 Self::Mainnet => zcash_primitives::constants::mainnet::B58_SCRIPT_ADDRESS_PREFIX,
78 Self::Testnet | Self::Regtest => {
79 zcash_primitives::constants::testnet::B58_SCRIPT_ADDRESS_PREFIX
80 }
81 }
82 }
83
84 pub fn bip70_network_name(&self) -> String {
87 if *self == Self::Mainnet {
88 "main".to_string()
89 } else {
90 "test".to_string()
91 }
92 }
93
94 pub fn tex_address_prefix(self) -> [u8; 2] {
97 match self {
99 Self::Mainnet => [0x1c, 0xb8],
100 Self::Testnet | Self::Regtest => [0x1d, 0x25],
101 }
102 }
103}
104
105impl From<NetworkKind> for &'static str {
106 fn from(network: NetworkKind) -> &'static str {
107 match network {
111 NetworkKind::Mainnet => "MainnetKind",
112 NetworkKind::Testnet => "TestnetKind",
113 NetworkKind::Regtest => "RegtestKind",
114 }
115 }
116}
117
118impl fmt::Display for NetworkKind {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 f.write_str((*self).into())
121 }
122}
123
124impl<'a> From<&'a Network> for &'a str {
125 fn from(network: &'a Network) -> &'a str {
126 match network {
127 Network::Mainnet => "Mainnet",
128 Network::Testnet(params) => params.network_name(),
129 }
130 }
131}
132
133impl fmt::Display for Network {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.write_str(self.into())
136 }
137}
138
139impl std::fmt::Debug for Network {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 match self {
142 Self::Mainnet => write!(f, "{self}"),
143 Self::Testnet(params) if params.is_regtest() => f
144 .debug_struct("Regtest")
145 .field("activation_heights", params.activation_heights())
146 .finish(),
147 Self::Testnet(params) if params.is_default_testnet() => {
148 write!(f, "{self}")
149 }
150 Self::Testnet(params) => f.debug_tuple("ConfiguredTestnet").field(params).finish(),
151 }
152 }
153}
154
155impl Network {
156 pub fn new_default_testnet() -> Self {
158 Self::Testnet(Arc::new(testnet::Parameters::default()))
159 }
160
161 pub fn new_configured_testnet(params: testnet::Parameters) -> Self {
163 Self::Testnet(Arc::new(params))
164 }
165
166 pub fn new_regtest(
168 configured_activation_heights: testnet::ConfiguredActivationHeights,
169 ) -> Self {
170 Self::new_configured_testnet(testnet::Parameters::new_regtest(
171 configured_activation_heights,
172 ))
173 }
174
175 pub fn is_default_testnet(&self) -> bool {
177 if let Self::Testnet(params) = self {
178 params.is_default_testnet()
179 } else {
180 false
181 }
182 }
183
184 pub fn is_regtest(&self) -> bool {
186 if let Self::Testnet(params) = self {
187 params.is_regtest()
188 } else {
189 false
190 }
191 }
192
193 pub fn kind(&self) -> NetworkKind {
195 match self {
196 Network::Mainnet => NetworkKind::Mainnet,
197 Network::Testnet(params) if params.is_regtest() => NetworkKind::Regtest,
198 Network::Testnet(_) => NetworkKind::Testnet,
199 }
200 }
201
202 pub fn t_addr_kind(&self) -> NetworkKind {
206 match self {
207 Network::Mainnet => NetworkKind::Mainnet,
208 Network::Testnet(_) => NetworkKind::Testnet,
209 }
210 }
211
212 pub fn iter() -> impl Iterator<Item = Self> {
214 [Self::Mainnet, Self::new_default_testnet()].into_iter()
215 }
216
217 pub fn is_max_block_time_enforced(&self, height: block::Height) -> bool {
226 match self {
227 Network::Mainnet => true,
228 Network::Testnet(_params) => height >= super::TESTNET_MAX_TIME_START_HEIGHT,
230 }
231 }
232
233 pub fn default_port(&self) -> u16 {
235 match self {
236 Network::Mainnet => 8233,
237 Network::Testnet(_params) => 18233,
239 }
240 }
241
242 pub fn mandatory_checkpoint_height(&self) -> Height {
252 NetworkUpgrade::Canopy
254 .activation_height(self)
255 .expect("Canopy activation height must be present on all networks")
256 .previous()
257 .expect("Canopy activation height must be above min height")
258 }
259
260 pub fn bip70_network_name(&self) -> String {
263 self.kind().bip70_network_name()
264 }
265
266 pub fn lowercase_name(&self) -> String {
268 self.to_string().to_ascii_lowercase()
269 }
270
271 pub fn is_a_test_network(&self) -> bool {
273 *self != Network::Mainnet
274 }
275
276 pub fn sapling_activation_height(&self) -> Height {
279 super::NetworkUpgrade::Sapling
280 .activation_height(self)
281 .expect("Sapling activation height needs to be set")
282 }
283}
284
285impl FromStr for Network {
287 type Err = InvalidNetworkError;
288
289 fn from_str(string: &str) -> Result<Self, Self::Err> {
290 match string.to_lowercase().as_str() {
291 "mainnet" => Ok(Network::Mainnet),
292 "testnet" => Ok(Network::new_default_testnet()),
293 _ => Err(InvalidNetworkError(string.to_owned())),
294 }
295 }
296}
297
298#[derive(Clone, Debug, Error)]
299#[error("Invalid network: {0}")]
300pub struct InvalidNetworkError(String);
301
302impl zcash_protocol::consensus::Parameters for Network {
303 fn network_type(&self) -> zcash_protocol::consensus::NetworkType {
304 self.kind().into()
305 }
306
307 fn activation_height(
308 &self,
309 nu: zcash_protocol::consensus::NetworkUpgrade,
310 ) -> Option<zcash_protocol::consensus::BlockHeight> {
311 NetworkUpgrade::from(nu)
312 .activation_height(self)
313 .map(|Height(h)| zcash_protocol::consensus::BlockHeight::from_u32(h))
314 }
315}