2022-06-29 04:05:31 +00:00
|
|
|
// SPDX-License-Identifier: CC0-1.0
|
2014-07-18 13:56:17 +00:00
|
|
|
|
2023-06-09 06:18:39 +00:00
|
|
|
//! Bitcoin network.
|
2014-07-18 13:56:17 +00:00
|
|
|
//!
|
2023-06-09 06:18:39 +00:00
|
|
|
//! The term "network" is overloaded, here [`Network`] refers to the specific
|
|
|
|
//! Bitcoin network we are operating on e.g., signet, regtest. The terms
|
|
|
|
//! "network" and "chain" are often used interchangeably for this concept.
|
2018-08-10 17:09:22 +00:00
|
|
|
//!
|
|
|
|
//! # Example: encoding a network's magic bytes
|
|
|
|
//!
|
|
|
|
//! ```rust
|
2023-06-09 06:18:39 +00:00
|
|
|
//! use bitcoin::Network;
|
Move relevant names into consensus::encode
- Move network::encodable::* to consensus::encode::*
- Rename Consensus{En,De}codable to {En,De}codable (now under
consensus::encode)
- Move network::serialize::Error to consensus::encode::Error
- Remove Raw{En,De}coder, implement {En,De}coder for T: {Write,Read}
instead
- Move network::serialize::Simple{En,De}coder to
consensus::encode::{En,De}coder
- Rename util::Error::Serialize to util::Error::Encode
- Modify comments to refer to new names
- Modify files to refer to new names
- Expose {En,De}cod{able,er}, {de,}serialize, Params
- Do not return Result for serialize{,_hex} as serializing to a Vec
should never fail
2018-09-20 10:15:45 +00:00
|
|
|
//! use bitcoin::consensus::encode::serialize;
|
2018-08-10 17:09:22 +00:00
|
|
|
//!
|
|
|
|
//! let network = Network::Bitcoin;
|
2019-05-23 20:28:10 +00:00
|
|
|
//! let bytes = serialize(&network.magic());
|
2018-08-10 17:09:22 +00:00
|
|
|
//!
|
|
|
|
//! assert_eq!(&bytes[..], &[0xF9, 0xBE, 0xB4, 0xD9]);
|
|
|
|
//! ```
|
2014-07-18 13:56:17 +00:00
|
|
|
|
2023-05-31 06:41:20 +00:00
|
|
|
use core::fmt;
|
2022-11-02 22:36:37 +00:00
|
|
|
use core::fmt::Display;
|
2022-09-20 05:27:25 +00:00
|
|
|
use core::str::FromStr;
|
|
|
|
|
2023-06-09 06:12:31 +00:00
|
|
|
use internals::write_err;
|
2022-09-20 05:27:25 +00:00
|
|
|
#[cfg(feature = "serde")]
|
|
|
|
use serde::{Deserialize, Serialize};
|
2019-11-22 00:42:15 +00:00
|
|
|
|
2023-11-05 10:16:53 +00:00
|
|
|
use crate::consensus::Params;
|
2023-02-27 06:20:57 +00:00
|
|
|
use crate::constants::ChainHash;
|
2023-06-09 06:12:31 +00:00
|
|
|
use crate::p2p::Magic;
|
2024-02-20 05:11:14 +00:00
|
|
|
use crate::prelude::*;
|
2019-11-22 00:42:15 +00:00
|
|
|
|
2023-11-17 02:21:06 +00:00
|
|
|
/// What kind of network we are on.
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
pub enum NetworkKind {
|
|
|
|
/// The Bitcoin mainnet network.
|
|
|
|
Main,
|
|
|
|
/// Some kind of testnet network.
|
|
|
|
Test,
|
|
|
|
}
|
|
|
|
|
|
|
|
// We explicitly do not provide `is_testnet`, using `!network.is_mainnet()` is less
|
|
|
|
// ambiguous due to confusion caused by signet/testnet/regtest.
|
|
|
|
impl NetworkKind {
|
|
|
|
/// Returns true if this is real mainnet bitcoin.
|
|
|
|
pub fn is_mainnet(&self) -> bool { *self == NetworkKind::Main }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Network> for NetworkKind {
|
|
|
|
fn from(n: Network) -> Self {
|
|
|
|
use Network::*;
|
|
|
|
|
|
|
|
match n {
|
|
|
|
Bitcoin => NetworkKind::Main,
|
|
|
|
Testnet | Signet | Regtest => NetworkKind::Test,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-20 05:27:25 +00:00
|
|
|
/// The cryptocurrency network to act on.
|
|
|
|
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
|
|
|
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
|
|
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
|
|
|
|
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
|
|
|
|
#[non_exhaustive]
|
|
|
|
pub enum Network {
|
|
|
|
/// Mainnet Bitcoin.
|
|
|
|
Bitcoin,
|
|
|
|
/// Bitcoin's testnet network.
|
|
|
|
Testnet,
|
|
|
|
/// Bitcoin's signet network.
|
|
|
|
Signet,
|
|
|
|
/// Bitcoin's regtest network.
|
|
|
|
Regtest,
|
2015-01-18 18:16:01 +00:00
|
|
|
}
|
2014-08-03 13:03:00 +00:00
|
|
|
|
2018-08-10 17:09:22 +00:00
|
|
|
impl Network {
|
|
|
|
/// Creates a `Network` from the magic bytes.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
2023-06-09 06:12:31 +00:00
|
|
|
/// use bitcoin::p2p::Magic;
|
|
|
|
/// use bitcoin::Network;
|
2018-08-10 17:09:22 +00:00
|
|
|
///
|
2022-09-28 00:32:47 +00:00
|
|
|
/// assert_eq!(Ok(Network::Bitcoin), Network::try_from(Magic::from_bytes([0xF9, 0xBE, 0xB4, 0xD9])));
|
|
|
|
/// assert_eq!(None, Network::from_magic(Magic::from_bytes([0xFF, 0xFF, 0xFF, 0xFF])));
|
2018-08-10 17:09:22 +00:00
|
|
|
/// ```
|
2022-11-15 23:23:01 +00:00
|
|
|
pub fn from_magic(magic: Magic) -> Option<Network> { Network::try_from(magic).ok() }
|
2014-07-18 13:56:17 +00:00
|
|
|
|
2018-08-10 17:09:22 +00:00
|
|
|
/// Return the network magic bytes, which should be encoded little-endian
|
|
|
|
/// at the start of every message
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
2023-06-09 06:12:31 +00:00
|
|
|
/// use bitcoin::p2p::Magic;
|
|
|
|
/// use bitcoin::Network;
|
2018-08-10 17:09:22 +00:00
|
|
|
///
|
|
|
|
/// let network = Network::Bitcoin;
|
2022-09-28 00:32:47 +00:00
|
|
|
/// assert_eq!(network.magic(), Magic::from_bytes([0xF9, 0xBE, 0xB4, 0xD9]));
|
2018-08-10 17:09:22 +00:00
|
|
|
/// ```
|
2022-11-15 23:23:01 +00:00
|
|
|
pub fn magic(self) -> Magic { Magic::from(self) }
|
2022-11-17 22:25:00 +00:00
|
|
|
|
|
|
|
/// Converts a `Network` to its equivalent `bitcoind -chain` argument name.
|
|
|
|
///
|
2022-12-01 20:24:42 +00:00
|
|
|
/// ```bash
|
2022-11-17 22:25:00 +00:00
|
|
|
/// $ bitcoin-23.0/bin/bitcoind --help | grep -C 3 '\-chain=<chain>'
|
|
|
|
/// Chain selection options:
|
|
|
|
///
|
|
|
|
/// -chain=<chain>
|
|
|
|
/// Use the chain <chain> (default: main). Allowed values: main, test, signet, regtest
|
|
|
|
/// ```
|
|
|
|
pub fn to_core_arg(self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
Network::Bitcoin => "main",
|
|
|
|
Network::Testnet => "test",
|
|
|
|
Network::Signet => "signet",
|
|
|
|
Network::Regtest => "regtest",
|
|
|
|
}
|
|
|
|
}
|
2022-12-01 11:05:40 +00:00
|
|
|
|
|
|
|
/// Converts a `bitcoind -chain` argument name to its equivalent `Network`.
|
|
|
|
///
|
|
|
|
/// ```bash
|
|
|
|
/// $ bitcoin-23.0/bin/bitcoind --help | grep -C 3 '\-chain=<chain>'
|
|
|
|
/// Chain selection options:
|
|
|
|
///
|
|
|
|
/// -chain=<chain>
|
|
|
|
/// Use the chain <chain> (default: main). Allowed values: main, test, signet, regtest
|
|
|
|
/// ```
|
|
|
|
pub fn from_core_arg(core_arg: &str) -> Result<Self, ParseNetworkError> {
|
|
|
|
use Network::*;
|
|
|
|
|
|
|
|
let network = match core_arg {
|
2022-10-19 16:51:41 +00:00
|
|
|
"main" => Bitcoin,
|
|
|
|
"test" => Testnet,
|
|
|
|
"signet" => Signet,
|
|
|
|
"regtest" => Regtest,
|
|
|
|
_ => return Err(ParseNetworkError(core_arg.to_owned())),
|
2022-12-01 11:05:40 +00:00
|
|
|
};
|
|
|
|
Ok(network)
|
|
|
|
}
|
2023-02-27 06:20:57 +00:00
|
|
|
|
|
|
|
/// Return the network's chain hash (genesis block hash).
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
2023-06-09 06:18:39 +00:00
|
|
|
/// use bitcoin::Network;
|
2023-02-27 06:20:57 +00:00
|
|
|
/// use bitcoin::blockdata::constants::ChainHash;
|
|
|
|
///
|
|
|
|
/// let network = Network::Bitcoin;
|
|
|
|
/// assert_eq!(network.chain_hash(), ChainHash::BITCOIN);
|
|
|
|
/// ```
|
2022-11-02 22:36:37 +00:00
|
|
|
pub fn chain_hash(self) -> ChainHash { ChainHash::using_genesis_block(self) }
|
2023-02-27 06:20:57 +00:00
|
|
|
|
|
|
|
/// Creates a `Network` from the chain hash (genesis block hash).
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```rust
|
2023-06-09 06:18:39 +00:00
|
|
|
/// use bitcoin::Network;
|
2023-02-27 06:20:57 +00:00
|
|
|
/// use bitcoin::blockdata::constants::ChainHash;
|
|
|
|
///
|
|
|
|
/// assert_eq!(Ok(Network::Bitcoin), Network::try_from(ChainHash::BITCOIN));
|
|
|
|
/// ```
|
2022-11-02 22:36:37 +00:00
|
|
|
pub fn from_chain_hash(chain_hash: ChainHash) -> Option<Network> {
|
|
|
|
Network::try_from(chain_hash).ok()
|
|
|
|
}
|
2023-11-05 10:16:53 +00:00
|
|
|
|
|
|
|
/// Returns the associated network parameters.
|
|
|
|
pub const fn params(self) -> &'static Params {
|
|
|
|
const PARAMS: [Params; 4] = [
|
|
|
|
Params::new(Network::Bitcoin),
|
|
|
|
Params::new(Network::Testnet),
|
|
|
|
Params::new(Network::Signet),
|
|
|
|
Params::new(Network::Regtest),
|
|
|
|
];
|
|
|
|
&PARAMS[self as usize]
|
|
|
|
}
|
2022-09-20 05:27:25 +00:00
|
|
|
}
|
|
|
|
|
2023-04-15 06:49:45 +00:00
|
|
|
#[cfg(feature = "serde")]
|
|
|
|
pub mod as_core_arg {
|
|
|
|
//! Module for serialization/deserialization of network variants into/from Bitcoin Core values
|
|
|
|
#![allow(missing_docs)]
|
|
|
|
|
|
|
|
use crate::Network;
|
|
|
|
|
|
|
|
pub fn serialize<S>(network: &Network, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: serde::Serializer,
|
|
|
|
{
|
|
|
|
serializer.serialize_str(network.to_core_arg())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<Network, D::Error>
|
|
|
|
where
|
|
|
|
D: serde::Deserializer<'de>,
|
|
|
|
{
|
|
|
|
struct NetworkVisitor;
|
|
|
|
|
|
|
|
impl<'de> serde::de::Visitor<'de> for NetworkVisitor {
|
|
|
|
type Value = Network;
|
|
|
|
|
|
|
|
fn visit_str<E: serde::de::Error>(self, s: &str) -> Result<Self::Value, E> {
|
|
|
|
Network::from_core_arg(s).map_err(|_| {
|
|
|
|
E::invalid_value(
|
|
|
|
serde::de::Unexpected::Str(s),
|
|
|
|
&"bitcoin network encoded as a string (either main, test, signet or regtest)",
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
|
|
|
|
write!(
|
|
|
|
formatter,
|
|
|
|
"bitcoin network encoded as a string (either main, test, signet or regtest)"
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
deserializer.deserialize_str(NetworkVisitor)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 08:37:14 +00:00
|
|
|
/// An error in parsing network string.
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
Make error types uniform
On our way to v1.0.0 we are defining a standard for our error types,
this includes:
- Uses the following derives (unless not possible, usually because of `io::Error`)
`#[derive(Debug, Clone, PartialEq, Eq)]`
- Has `non_exhaustive` unless we really know we can commit to not adding
anything.
Furthermore, we are trying to make the codebase easy to read. Error code
is write-once-read-many (well it should be) so if we make all the error
code super uniform the users can flick to an error and quickly see what
it includes. In an effort to achieve this I have made up a style and
over recent times have change much of the error code to that new style,
this PR audits _all_ error types in the code base and enforces the
style, specifically:
- Is layed out: definition, [impl block], Display impl, error::Error impl, From impls
- `error::Error` impl matches on enum even if it returns `None` for all variants
- Display/Error impls import enum variants locally
- match uses *self and `ref e`
- error::Error variants that return `Some` come first, `None` after
Re: non_exhaustive
To make dev and review easier I have added `non_exhaustive` to _every_
error type. We can then remove it error by error as we see fit. This is
because it takes a bit of thinking to do and review where as this patch
should not take much brain power to review.
2023-10-04 02:55:45 +00:00
|
|
|
#[non_exhaustive]
|
2022-10-10 08:37:14 +00:00
|
|
|
pub struct ParseNetworkError(String);
|
|
|
|
|
|
|
|
impl fmt::Display for ParseNetworkError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
|
|
write_err!(f, "failed to parse {} as network", self.0; self)
|
|
|
|
}
|
|
|
|
}
|
2023-10-04 01:35:01 +00:00
|
|
|
|
|
|
|
#[cfg(feature = "std")]
|
|
|
|
impl std::error::Error for ParseNetworkError {
|
|
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
|
|
|
|
}
|
2022-10-10 08:37:14 +00:00
|
|
|
|
2022-09-20 05:27:25 +00:00
|
|
|
impl FromStr for Network {
|
2022-10-10 08:37:14 +00:00
|
|
|
type Err = ParseNetworkError;
|
|
|
|
|
2022-09-20 05:27:25 +00:00
|
|
|
#[inline]
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
use Network::*;
|
|
|
|
|
|
|
|
let network = match s {
|
|
|
|
"bitcoin" => Bitcoin,
|
|
|
|
"testnet" => Testnet,
|
|
|
|
"signet" => Signet,
|
|
|
|
"regtest" => Regtest,
|
2022-11-15 23:23:01 +00:00
|
|
|
_ => return Err(ParseNetworkError(s.to_owned())),
|
2022-09-20 05:27:25 +00:00
|
|
|
};
|
|
|
|
Ok(network)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-28 00:32:47 +00:00
|
|
|
impl fmt::Display for Network {
|
|
|
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
|
|
|
use Network::*;
|
|
|
|
|
|
|
|
let s = match *self {
|
|
|
|
Bitcoin => "bitcoin",
|
|
|
|
Testnet => "testnet",
|
|
|
|
Signet => "signet",
|
|
|
|
Regtest => "regtest",
|
|
|
|
};
|
|
|
|
write!(f, "{}", s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-27 06:20:57 +00:00
|
|
|
/// Error in parsing network from chain hash.
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
Make error types uniform
On our way to v1.0.0 we are defining a standard for our error types,
this includes:
- Uses the following derives (unless not possible, usually because of `io::Error`)
`#[derive(Debug, Clone, PartialEq, Eq)]`
- Has `non_exhaustive` unless we really know we can commit to not adding
anything.
Furthermore, we are trying to make the codebase easy to read. Error code
is write-once-read-many (well it should be) so if we make all the error
code super uniform the users can flick to an error and quickly see what
it includes. In an effort to achieve this I have made up a style and
over recent times have change much of the error code to that new style,
this PR audits _all_ error types in the code base and enforces the
style, specifically:
- Is layed out: definition, [impl block], Display impl, error::Error impl, From impls
- `error::Error` impl matches on enum even if it returns `None` for all variants
- Display/Error impls import enum variants locally
- match uses *self and `ref e`
- error::Error variants that return `Some` come first, `None` after
Re: non_exhaustive
To make dev and review easier I have added `non_exhaustive` to _every_
error type. We can then remove it error by error as we see fit. This is
because it takes a bit of thinking to do and review where as this patch
should not take much brain power to review.
2023-10-04 02:55:45 +00:00
|
|
|
#[non_exhaustive]
|
2023-10-04 01:21:10 +00:00
|
|
|
pub struct UnknownChainHashError(ChainHash);
|
2023-02-27 06:20:57 +00:00
|
|
|
|
2023-10-04 01:21:10 +00:00
|
|
|
impl Display for UnknownChainHashError {
|
2023-02-27 06:20:57 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "unknown chain hash: {}", self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 01:35:01 +00:00
|
|
|
#[cfg(feature = "std")]
|
|
|
|
impl std::error::Error for UnknownChainHashError {
|
|
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
|
|
|
|
}
|
2023-02-27 06:20:57 +00:00
|
|
|
|
|
|
|
impl TryFrom<ChainHash> for Network {
|
2023-10-04 01:21:10 +00:00
|
|
|
type Error = UnknownChainHashError;
|
2023-02-27 06:20:57 +00:00
|
|
|
|
|
|
|
fn try_from(chain_hash: ChainHash) -> Result<Self, Self::Error> {
|
|
|
|
match chain_hash {
|
|
|
|
// Note: any new network entries must be matched against here.
|
|
|
|
ChainHash::BITCOIN => Ok(Network::Bitcoin),
|
|
|
|
ChainHash::TESTNET => Ok(Network::Testnet),
|
|
|
|
ChainHash::SIGNET => Ok(Network::Signet),
|
|
|
|
ChainHash::REGTEST => Ok(Network::Regtest),
|
2023-10-04 01:21:10 +00:00
|
|
|
_ => Err(UnknownChainHashError(chain_hash)),
|
2023-02-27 06:20:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-03 13:03:00 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2023-06-09 06:12:31 +00:00
|
|
|
use super::Network;
|
2022-11-15 23:23:01 +00:00
|
|
|
use crate::consensus::encode::{deserialize, serialize};
|
2023-05-31 06:41:20 +00:00
|
|
|
use crate::p2p::ServiceFlags;
|
2022-11-15 23:23:01 +00:00
|
|
|
|
2019-05-23 20:28:10 +00:00
|
|
|
#[test]
|
|
|
|
fn serialize_test() {
|
2022-01-24 00:31:39 +00:00
|
|
|
assert_eq!(serialize(&Network::Bitcoin.magic()), &[0xf9, 0xbe, 0xb4, 0xd9]);
|
|
|
|
assert_eq!(serialize(&Network::Testnet.magic()), &[0x0b, 0x11, 0x09, 0x07]);
|
|
|
|
assert_eq!(serialize(&Network::Signet.magic()), &[0x0a, 0x03, 0xcf, 0x40]);
|
|
|
|
assert_eq!(serialize(&Network::Regtest.magic()), &[0xfa, 0xbf, 0xb5, 0xda]);
|
|
|
|
|
|
|
|
assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin.magic()));
|
|
|
|
assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet.magic()));
|
|
|
|
assert_eq!(deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), Some(Network::Signet.magic()));
|
|
|
|
assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest.magic()));
|
2019-05-23 20:28:10 +00:00
|
|
|
}
|
2018-05-16 09:22:07 +00:00
|
|
|
|
2019-11-22 00:42:15 +00:00
|
|
|
#[test]
|
|
|
|
fn string_test() {
|
|
|
|
assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
|
|
|
|
assert_eq!(Network::Testnet.to_string(), "testnet");
|
|
|
|
assert_eq!(Network::Regtest.to_string(), "regtest");
|
2019-07-10 04:53:53 +00:00
|
|
|
assert_eq!(Network::Signet.to_string(), "signet");
|
2019-11-22 00:42:15 +00:00
|
|
|
|
|
|
|
assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
|
|
|
|
assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
|
|
|
|
assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
|
2019-07-10 04:53:53 +00:00
|
|
|
assert_eq!("signet".parse::<Network>().unwrap(), Network::Signet);
|
2019-11-22 00:42:15 +00:00
|
|
|
assert!("fakenet".parse::<Network>().is_err());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn service_flags_test() {
|
|
|
|
let all = [
|
|
|
|
ServiceFlags::NETWORK,
|
|
|
|
ServiceFlags::GETUTXO,
|
|
|
|
ServiceFlags::BLOOM,
|
|
|
|
ServiceFlags::WITNESS,
|
2019-12-21 01:39:30 +00:00
|
|
|
ServiceFlags::COMPACT_FILTERS,
|
2019-11-22 00:42:15 +00:00
|
|
|
ServiceFlags::NETWORK_LIMITED,
|
|
|
|
];
|
|
|
|
|
|
|
|
let mut flags = ServiceFlags::NONE;
|
|
|
|
for f in all.iter() {
|
|
|
|
assert!(!flags.has(*f));
|
|
|
|
}
|
|
|
|
|
|
|
|
flags |= ServiceFlags::WITNESS;
|
|
|
|
assert_eq!(flags, ServiceFlags::WITNESS);
|
2018-05-16 09:22:07 +00:00
|
|
|
|
2019-11-22 00:42:15 +00:00
|
|
|
let mut flags2 = flags | ServiceFlags::GETUTXO;
|
|
|
|
for f in all.iter() {
|
|
|
|
assert_eq!(flags2.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO);
|
|
|
|
}
|
|
|
|
|
|
|
|
flags2 ^= ServiceFlags::WITNESS;
|
|
|
|
assert_eq!(flags2, ServiceFlags::GETUTXO);
|
2022-01-24 00:24:32 +00:00
|
|
|
|
2019-12-21 01:39:30 +00:00
|
|
|
flags2 |= ServiceFlags::COMPACT_FILTERS;
|
|
|
|
flags2 ^= ServiceFlags::GETUTXO;
|
|
|
|
assert_eq!(flags2, ServiceFlags::COMPACT_FILTERS);
|
2019-12-05 20:13:45 +00:00
|
|
|
|
|
|
|
// Test formatting.
|
|
|
|
assert_eq!("ServiceFlags(NONE)", ServiceFlags::NONE.to_string());
|
|
|
|
assert_eq!("ServiceFlags(WITNESS)", ServiceFlags::WITNESS.to_string());
|
|
|
|
let flag = ServiceFlags::WITNESS | ServiceFlags::BLOOM | ServiceFlags::NETWORK;
|
|
|
|
assert_eq!("ServiceFlags(NETWORK|BLOOM|WITNESS)", flag.to_string());
|
|
|
|
let flag = ServiceFlags::WITNESS | 0xf0.into();
|
2019-12-21 02:36:47 +00:00
|
|
|
assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string());
|
2019-11-22 00:42:15 +00:00
|
|
|
}
|
2022-09-20 05:19:47 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(feature = "serde")]
|
|
|
|
fn serde_roundtrip() {
|
|
|
|
use Network::*;
|
2022-11-15 23:23:01 +00:00
|
|
|
let tests = vec![
|
|
|
|
(Bitcoin, "bitcoin"),
|
|
|
|
(Testnet, "testnet"),
|
|
|
|
(Signet, "signet"),
|
|
|
|
(Regtest, "regtest"),
|
|
|
|
];
|
2022-09-20 05:19:47 +00:00
|
|
|
|
|
|
|
for tc in tests {
|
|
|
|
let network = tc.0;
|
|
|
|
|
|
|
|
let want = format!("\"{}\"", tc.1);
|
|
|
|
let got = serde_json::to_string(&tc.0).expect("failed to serialize network");
|
|
|
|
assert_eq!(got, want);
|
|
|
|
|
|
|
|
let back: Network = serde_json::from_str(&got).expect("failed to deserialize network");
|
|
|
|
assert_eq!(back, network);
|
|
|
|
}
|
|
|
|
}
|
2022-09-28 00:32:47 +00:00
|
|
|
|
2022-12-08 12:18:34 +00:00
|
|
|
#[test]
|
|
|
|
fn from_to_core_arg() {
|
|
|
|
let expected_pairs = [
|
|
|
|
(Network::Bitcoin, "main"),
|
|
|
|
(Network::Testnet, "test"),
|
|
|
|
(Network::Regtest, "regtest"),
|
|
|
|
(Network::Signet, "signet"),
|
|
|
|
];
|
|
|
|
|
|
|
|
for (net, core_arg) in &expected_pairs {
|
|
|
|
assert_eq!(Network::from_core_arg(core_arg), Ok(*net));
|
|
|
|
assert_eq!(net.to_core_arg(), *core_arg);
|
|
|
|
}
|
|
|
|
}
|
2023-04-15 06:49:45 +00:00
|
|
|
|
|
|
|
#[cfg(feature = "serde")]
|
|
|
|
#[test]
|
|
|
|
fn serde_as_core_arg() {
|
|
|
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
|
|
#[serde(crate = "actual_serde")]
|
|
|
|
struct T {
|
2023-06-09 06:18:39 +00:00
|
|
|
#[serde(with = "crate::network::as_core_arg")]
|
2023-04-15 06:49:45 +00:00
|
|
|
pub network: Network,
|
|
|
|
}
|
|
|
|
|
|
|
|
serde_test::assert_tokens(
|
|
|
|
&T { network: Network::Bitcoin },
|
|
|
|
&[
|
|
|
|
serde_test::Token::Struct { name: "T", len: 1 },
|
|
|
|
serde_test::Token::Str("network"),
|
|
|
|
serde_test::Token::Str("main"),
|
|
|
|
serde_test::Token::StructEnd,
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
2014-08-03 13:03:00 +00:00
|
|
|
}
|