Skip to content

Commit a8e6ab7

Browse files
committed
Merge rust-bitcoin#4640: Remove non_exhausive from Network
bcf0c3d bitcoin: Add a test for matching on network (Tobin C. Harding) 1e69e63 Remove non_exhausive from Network (Tobin C. Harding) Pull request description: Note that Kix is AWOL at the moment so we will need to let this sit for a good while so he gets a chance to see it since he is central to the debate in rust-bitcoin#2225. Issue rust-bitcoin#2225 is long and has many valid opposing opinions. The main argument for having non_exhaustive is that it helps future proof the ecosystem at the cost of pain now. The main argument against having non_exhaustive is why have pain now when adding a network is so rare that having pain then is ok. At the end of the thread Andrew posts: > I continue to think we should have an exhaustive enum, with a bunch of > documentation about how to use it properly. I am warming up to the > "don't have an enum, just have rules for defining your own" but I think > this would be needless work for people who just want to grab an > off-the-shelf set of networks or people who want to make their own enum > but want to see an example of how to do it first. In order to make some forward progress lets remove the `non_exhaustive` now and backport this change to 0.32, 0.31, an 0.30. Later we can add, and release in 0.33, whatever forward protection / libapocalyse protection we want to add. This removes the pain now and gives us a path to prevent future pain - that should keep all parties happy. ACKs for top commit: apoelstra: ACK bcf0c3d; successfully ran local tests luisschwab: ACK bcf0c3d Tree-SHA512: d8c24e8d2320b289aafdfa4b03a96407f40dd120dfcbd55973c35f62cd8f74eff8e0d961a7bb31ae7fa9dc4f6e68949c225bdbacbc1733042679c4913a2231b1
2 parents d996a9a + bcf0c3d commit a8e6ab7

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

bitcoin/src/network/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,18 @@ pub enum TestnetVersion {
5959
V4,
6060
}
6161

62+
6263
/// The cryptocurrency network to act on.
64+
///
65+
/// This is an exhaustive enum, meaning that we cannot add any future networks without defining a
66+
/// new, incompatible version of this type. If you are using this type directly and wish to support the
67+
/// new network, this will be a breaking change to your APIs and likely require changes in your code.
68+
///
69+
/// If you are concerned about forward compatibility, consider using `T: Into<Params>` instead of this
70+
/// this type as a parameter to functions in your public API, or directly using the `Params` type.
71+
// For extensive discussion on the usage of `non_exhaustive` please see:
72+
// https://github.com/rust-bitcoin/rust-bitcoin/issues/2225
6373
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
64-
#[non_exhaustive]
6574
pub enum Network {
6675
/// Mainnet Bitcoin.
6776
Bitcoin,

bitcoin/tests/network.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//! Tests what a user can do when pattern matching on `Network` and associated types.
2+
3+
use bitcoin::network::{Network, NetworkKind, TestnetVersion};
4+
5+
#[test]
6+
fn can_match_exhaustively_on_network() {
7+
// Returns true if `n` is mainnet.
8+
fn is_mainnet(n: Network) -> bool {
9+
matches!(n, Network::Bitcoin)
10+
}
11+
12+
assert!(is_mainnet(Network::Bitcoin));
13+
}
14+
15+
#[test]
16+
fn can_match_exhaustively_on_testnet() {
17+
// Returns true if `n` is any testnet.
18+
fn is_testnet(n: Network) -> bool {
19+
matches!(n, Network::Testnet(_))
20+
}
21+
22+
assert!(is_testnet(Network::Testnet(TestnetVersion::V3)));
23+
}
24+
25+
#[test]
26+
fn can_use_network_kind() {
27+
// Returns true if `n` is any mainnet.
28+
fn is_mainnet(n: Network) -> bool {
29+
NetworkKind::from(n).is_mainnet()
30+
}
31+
32+
// Returns true if `n` is a any testnet.
33+
fn is_testnet(n: Network) -> bool {
34+
!NetworkKind::from(n).is_mainnet()
35+
}
36+
37+
assert!(is_mainnet(Network::Bitcoin));
38+
assert!(!is_testnet(Network::Bitcoin));
39+
40+
assert!(is_testnet(Network::Testnet(TestnetVersion::V3)));
41+
assert!(!is_mainnet(Network::Testnet(TestnetVersion::V3)));
42+
43+
}
44+
45+
#[test]
46+
fn can_not_match_exaustively_on_testnet_version() {
47+
// Returns true if `n` is testnet version 3.
48+
fn is_testnet_v3(n: Network) -> bool {
49+
match n {
50+
Network::Testnet(TestnetVersion::V3) => true,
51+
Network::Testnet(TestnetVersion::V4) => false,
52+
// Catchall because of `non_exhaustive` attribute.
53+
Network::Testnet(_) => false,
54+
_ => false,
55+
}
56+
}
57+
58+
assert!(is_testnet_v3(Network::Testnet(TestnetVersion::V3)));
59+
}
60+
61+
#[test]
62+
fn can_match_on_testnet_version_3_only() {
63+
// Returns true if `n` is testnet version 3.
64+
fn is_testnet_v3(n: Network) -> bool {
65+
match n {
66+
Network::Testnet(TestnetVersion::V3) => true,
67+
// Catchall because its logically correct to do so.
68+
Network::Testnet(_) => false,
69+
_ => false,
70+
}
71+
}
72+
73+
assert!(is_testnet_v3(Network::Testnet(TestnetVersion::V3)));
74+
}

0 commit comments

Comments
 (0)