invoice/
network.rs

1// Modern, minimalistic & standard-compliant cold wallet library.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2020-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2020-2024 LNP/BP Standards Association. All rights reserved.
9// Copyright (C) 2020-2024 Dr Maxim Orlovsky. All rights reserved.
10//
11// Licensed under the Apache License, Version 2.0 (the "License");
12// you may not use this file except in compliance with the License.
13// You may obtain a copy of the License at
14//
15//     http://www.apache.org/licenses/LICENSE-2.0
16//
17// Unless required by applicable law or agreed to in writing, software
18// distributed under the License is distributed on an "AS IS" BASIS,
19// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20// See the License for the specific language governing permissions and
21// limitations under the License.
22
23use std::str::FromStr;
24
25use bc::BlockHash;
26
27use crate::AddressNetwork;
28
29/// Bitcoin network used by the address
30#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
31#[cfg_attr(
32    feature = "serde",
33    derive(serde::Serialize, serde::Deserialize),
34    serde(rename_all = "camelCase",)
35)]
36#[display(lowercase)]
37pub enum Network {
38    /// Bitcoin mainnet
39    #[display("bitcoin")]
40    Mainnet,
41
42    /// Bitcoin testnet3
43    Testnet3,
44
45    /// Bitcoin testnet4
46    Testnet4,
47
48    /// Bitcoin signet
49    Signet,
50
51    /// Bitcoin regtest networks
52    Regtest,
53}
54
55impl Network {
56    /// Detects whether the network is a kind of test network (testnet, signet,
57    /// regtest).
58    pub fn is_testnet(self) -> bool { self != Self::Mainnet }
59
60    pub const fn genesis_hash(self) -> BlockHash {
61        match self {
62            Network::Mainnet => BlockHash::GENESIS_MAINNET,
63            Network::Testnet3 => BlockHash::GENESIS_TESTNET3,
64            Network::Testnet4 => BlockHash::GENESIS_TESTNET4,
65            Network::Signet => BlockHash::GENESIS_SIGNET,
66            Network::Regtest => BlockHash::GENESIS_REGTEST,
67        }
68    }
69}
70
71impl From<Network> for AddressNetwork {
72    fn from(network: Network) -> Self {
73        match network {
74            Network::Mainnet => AddressNetwork::Mainnet,
75            Network::Testnet3 | Network::Testnet4 | Network::Signet => AddressNetwork::Testnet,
76            Network::Regtest => AddressNetwork::Regtest,
77        }
78    }
79}
80
81#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)]
82#[display("unknown genesis block hash '{0}'")]
83pub struct UnknownGenesisBlock(pub BlockHash);
84
85impl TryFrom<BlockHash> for Network {
86    type Error = UnknownGenesisBlock;
87
88    fn try_from(hash: BlockHash) -> Result<Self, Self::Error> {
89        match hash {
90            BlockHash::GENESIS_MAINNET => Ok(Network::Mainnet),
91            BlockHash::GENESIS_TESTNET3 => Ok(Network::Testnet3),
92            BlockHash::GENESIS_TESTNET4 => Ok(Network::Testnet4),
93            BlockHash::GENESIS_SIGNET => Ok(Network::Signet),
94            BlockHash::GENESIS_REGTEST => Ok(Network::Regtest),
95            _ => Err(UnknownGenesisBlock(hash)),
96        }
97    }
98}
99
100#[derive(Clone, Eq, PartialEq, Debug, Display, Error)]
101#[display("unknown bitcoin network '{0}'")]
102pub struct UnknownNetwork(pub String);
103
104impl FromStr for Network {
105    type Err = UnknownNetwork;
106
107    fn from_str(s: &str) -> Result<Self, Self::Err> {
108        Ok(match s {
109            "bitcoin" | "mainnet" => Network::Mainnet,
110            "testnet" | "testnet3" => Network::Testnet3,
111            "testnet4" => Network::Testnet4,
112            "signet" => Network::Signet,
113            "regtest" => Network::Regtest,
114            other => return Err(UnknownNetwork(other.to_owned())),
115        })
116    }
117}