nakamoto_common/
network.rs1use std::str::FromStr;
3
4use bitcoin::blockdata::block::{Block, BlockHeader};
5use bitcoin::consensus::params::Params;
6use bitcoin::hash_types::BlockHash;
7use bitcoin::hashes::hex::FromHex;
8use bitcoin::network::constants::ServiceFlags;
9
10use bitcoin_hashes::sha256d;
11
12use crate::block::Height;
13
14#[derive(Debug, Copy, Clone)]
16pub enum Services {
17 All,
19 Chain,
21}
22
23impl From<Services> for ServiceFlags {
24 fn from(value: Services) -> Self {
25 match value {
26 Services::All => Self::COMPACT_FILTERS | Self::NETWORK,
27 Services::Chain => Self::NETWORK,
28 }
29 }
30}
31
32impl Default for Services {
33 fn default() -> Self {
34 Services::All
35 }
36}
37
38#[derive(Debug, Copy, Clone)]
40pub enum Network {
41 Mainnet,
43 Testnet,
45 Regtest,
47 Signet,
49}
50
51impl Default for Network {
52 fn default() -> Self {
53 Self::Mainnet
54 }
55}
56
57impl FromStr for Network {
58 type Err = String;
59
60 fn from_str(s: &str) -> Result<Self, Self::Err> {
61 match s {
62 "mainnet" | "bitcoin" => Ok(Self::Mainnet),
63 "testnet" => Ok(Self::Testnet),
64 "regtest" => Ok(Self::Regtest),
65 "signet" => Ok(Self::Signet),
66 _ => Err(format!("invalid network specified {:?}", s)),
67 }
68 }
69}
70
71impl From<Network> for bitcoin::Network {
72 fn from(value: Network) -> Self {
73 match value {
74 Network::Mainnet => Self::Bitcoin,
75 Network::Testnet => Self::Testnet,
76 Network::Regtest => Self::Regtest,
77 Network::Signet => Self::Signet,
78 }
79 }
80}
81
82impl From<bitcoin::Network> for Network {
83 fn from(value: bitcoin::Network) -> Self {
84 match value {
85 bitcoin::Network::Bitcoin => Self::Mainnet,
86 bitcoin::Network::Testnet => Self::Testnet,
87 bitcoin::Network::Signet => Self::Signet,
88 bitcoin::Network::Regtest => Self::Regtest,
89 }
90 }
91}
92
93impl Network {
94 pub fn port(&self) -> u16 {
96 match self {
97 Network::Mainnet => 8333,
98 Network::Testnet => 18333,
99 Network::Regtest => 18334,
100 Network::Signet => 38333,
101 }
102 }
103
104 pub fn checkpoints(&self) -> Box<dyn Iterator<Item = (Height, BlockHash)>> {
106 use crate::block::checkpoints;
107
108 let iter = match self {
109 Network::Mainnet => checkpoints::MAINNET,
110 Network::Testnet => checkpoints::TESTNET,
111 Network::Regtest => checkpoints::REGTEST,
112 Network::Signet => checkpoints::SIGNET,
113 }
114 .iter()
115 .cloned()
116 .map(|(height, hash)| {
117 let hash = BlockHash::from_hex(hash).unwrap();
118 (height, hash)
119 });
120
121 Box::new(iter)
122 }
123
124 pub fn as_str(&self) -> &'static str {
126 match self {
127 Network::Mainnet => "mainnet",
128 Network::Testnet => "testnet",
129 Network::Regtest => "regtest",
130 Network::Signet => "signet",
131 }
132 }
133
134 pub fn seeds(&self) -> &[&str] {
136 match self {
137 Network::Mainnet => &[
138 "seed.bitcoin.sipa.be", "dnsseed.bluematt.me", "dnsseed.bitcoin.dashjr.org", "seed.bitcoinstats.com", "seed.bitcoin.jonasschnelli.ch", "seed.btc.petertodd.org", "seed.bitcoin.sprovoost.nl", "dnsseed.emzy.de", "seed.bitcoin.wiz.biz", "seed.cloudhead.io", ],
149 Network::Testnet => &[
150 "testnet-seed.bitcoin.jonasschnelli.ch",
151 "seed.tbtc.petertodd.org",
152 "seed.testnet.bitcoin.sprovoost.nl",
153 "testnet-seed.bluematt.me",
154 ],
155 Network::Regtest => &[], Network::Signet => &["seed.signet.bitcoin.sprovoost.nl"],
157 }
158 }
159}
160
161impl Network {
162 pub fn genesis(&self) -> BlockHeader {
173 self.genesis_block().header
174 }
175
176 pub fn genesis_block(&self) -> Block {
178 use bitcoin::blockdata::constants;
179
180 constants::genesis_block((*self).into())
181 }
182
183 pub fn genesis_hash(&self) -> BlockHash {
185 use crate::block::genesis;
186 use bitcoin_hashes::Hash;
187
188 let hash = match self {
189 Self::Mainnet => genesis::MAINNET,
190 Self::Testnet => genesis::TESTNET,
191 Self::Regtest => genesis::REGTEST,
192 Self::Signet => genesis::SIGNET,
193 };
194 BlockHash::from_hash(
195 sha256d::Hash::from_slice(hash)
196 .expect("the genesis hash has the right number of bytes"),
197 )
198 }
199
200 pub fn params(&self) -> Params {
202 Params::new((*self).into())
203 }
204
205 pub fn magic(&self) -> u32 {
207 bitcoin::Network::from(*self).magic()
208 }
209}