Skip to main content

amaru_kernel/cardano/
network_name.rs

1// Copyright 2025 PRAGMA
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{
16    EraHistory, GlobalParameters, MAINNET_ERA_HISTORY, MAINNET_GLOBAL_PARAMETERS, Network, NetworkMagic,
17    PREPROD_ERA_HISTORY, PREPROD_GLOBAL_PARAMETERS, PREPROD_INITIAL_PROTOCOL_PARAMETERS, PREVIEW_ERA_HISTORY,
18    PREVIEW_GLOBAL_PARAMETERS, PREVIEW_INITIAL_PROTOCOL_PARAMETERS, ProtocolParameters, Slot, TESTNET_ERA_HISTORY,
19    TESTNET_GLOBAL_PARAMETERS,
20};
21
22#[derive(Debug, PartialEq, Clone, Copy)]
23pub enum NetworkName {
24    Mainnet,
25    Preprod,
26    Preview,
27    Testnet(u32),
28}
29
30impl From<NetworkName> for &EraHistory {
31    fn from(value: NetworkName) -> Self {
32        match value {
33            NetworkName::Mainnet => &MAINNET_ERA_HISTORY,
34            NetworkName::Preprod => &PREPROD_ERA_HISTORY,
35            NetworkName::Preview => &PREVIEW_ERA_HISTORY,
36            NetworkName::Testnet(_) => &TESTNET_ERA_HISTORY,
37        }
38    }
39}
40
41impl From<NetworkName> for &GlobalParameters {
42    fn from(value: NetworkName) -> Self {
43        match value {
44            NetworkName::Mainnet => &MAINNET_GLOBAL_PARAMETERS,
45            NetworkName::Preprod => &PREPROD_GLOBAL_PARAMETERS,
46            NetworkName::Preview => &PREVIEW_GLOBAL_PARAMETERS,
47            NetworkName::Testnet(_) => &TESTNET_GLOBAL_PARAMETERS,
48        }
49    }
50}
51
52impl TryFrom<NetworkName> for &ProtocolParameters {
53    type Error = String;
54
55    /// TODO: define protocol parameters for all the networks
56    fn try_from(value: NetworkName) -> Result<Self, String> {
57        match value {
58            NetworkName::Preprod => Ok(&PREPROD_INITIAL_PROTOCOL_PARAMETERS),
59            NetworkName::Preview => Ok(&PREVIEW_INITIAL_PROTOCOL_PARAMETERS),
60            other @ NetworkName::Mainnet | other @ NetworkName::Testnet(_) => {
61                Err(format!("no initial protocol parameters for {other}"))
62            }
63        }
64    }
65}
66
67impl std::fmt::Display for NetworkName {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        match self {
70            Self::Mainnet => write!(f, "mainnet"),
71            Self::Preprod => write!(f, "preprod"),
72            Self::Preview => write!(f, "preview"),
73            Self::Testnet(magic) => write!(f, "testnet_{}", magic),
74        }
75    }
76}
77
78impl std::str::FromStr for NetworkName {
79    type Err = String;
80
81    fn from_str(s: &str) -> Result<Self, Self::Err> {
82        match s {
83            "mainnet" => Ok(Self::Mainnet),
84            "preprod" => Ok(Self::Preprod),
85            "preview" => Ok(Self::Preview),
86            _ => {
87                let magic = s.strip_prefix("testnet_").ok_or(format!("Invalid network name {}", s))?;
88
89                magic.parse::<u32>().map(NetworkName::Testnet).map_err(|e| e.to_string())
90            }
91        }
92    }
93}
94
95impl From<NetworkName> for Network {
96    fn from(value: NetworkName) -> Self {
97        if value == NetworkName::Mainnet { Network::Mainnet } else { Network::Testnet }
98    }
99}
100
101impl NetworkName {
102    pub fn to_network_magic(self) -> NetworkMagic {
103        match self {
104            Self::Mainnet => NetworkMagic::MAINNET,
105            Self::Preprod => NetworkMagic::PREPROD,
106            Self::Preview => NetworkMagic::PREVIEW,
107            Self::Testnet(magic) => NetworkMagic::new(magic as u64),
108        }
109    }
110
111    /// Compute the default epoch length for this network.
112    ///
113    /// This is an over-simplification as _theoretically_ each era can
114    /// have a different epoch length but in practice, except for
115    /// Byron era, all eras for each network have always had the same
116    /// length
117    pub fn default_epoch_size_in_slots(&self) -> u64 {
118        match self {
119            NetworkName::Mainnet => 432000,
120            NetworkName::Preprod => 432000,
121            NetworkName::Preview => 86400,
122            NetworkName::Testnet(_) => 86400,
123        }
124    }
125
126    /// Provide stability window for given network.
127    pub fn default_stability_window(&self) -> Slot {
128        match self {
129            NetworkName::Mainnet => MAINNET_GLOBAL_PARAMETERS.stability_window,
130            NetworkName::Preprod => PREPROD_GLOBAL_PARAMETERS.stability_window,
131            NetworkName::Preview => PREVIEW_GLOBAL_PARAMETERS.stability_window,
132            NetworkName::Testnet(_) => TESTNET_GLOBAL_PARAMETERS.stability_window,
133        }
134    }
135}
136
137#[cfg(any(test, feature = "test-utils"))]
138pub use tests::*;
139
140#[cfg(any(test, feature = "test-utils"))]
141mod tests {
142    use proptest::{prelude::*, prop_oneof};
143
144    use super::NetworkName::{self, *};
145
146    pub fn any_network_name() -> impl Strategy<Value = NetworkName> {
147        prop_oneof![Just(Mainnet), Just(Preprod), Just(Preview), (3..u32::MAX).prop_map(Testnet)]
148    }
149}