adds constraints on valid network names and a test

This commit is contained in:
Arya 2024-04-17 22:41:11 -04:00
parent 1173faf894
commit 1608472f5a
2 changed files with 87 additions and 5 deletions

View File

@ -1,5 +1,5 @@
//! Types and implementation for Testnet consensus parameters
use std::collections::BTreeMap;
use std::{collections::BTreeMap, fmt};
use zcash_primitives::constants as zp_constants;
@ -11,6 +11,12 @@ use crate::{
},
};
/// Reserved network names that should not be allowed for configured Testnets.
pub const RESERVED_NETWORK_NAMES: [&str; 3] = ["Mainnet", "Testnet", "Regtest"];
/// Maximum length for a configured network name.
pub const MAX_NETWORK_NAME_LENGTH: usize = 30;
/// Configurable activation heights for Regtest and configured Testnets.
#[derive(Deserialize, Default)]
#[serde(rename_all = "PascalCase")]
@ -50,7 +56,7 @@ pub struct ParametersBuilder {
impl Default for ParametersBuilder {
fn default() -> Self {
Self {
network_name: "Testnet".to_string(),
network_name: "UnknownTestnet".to_string(),
// # Correctness
//
// `Genesis` network upgrade activation height must always be 0
@ -73,8 +79,26 @@ impl Default for ParametersBuilder {
impl ParametersBuilder {
/// Sets the network name to be used in the [`Parameters`] being built.
pub fn network_name(mut self, network_name: String) -> Self {
self.network_name = network_name;
pub fn network_name(mut self, network_name: impl fmt::Display) -> Self {
self.network_name = network_name.to_string();
assert!(
!RESERVED_NETWORK_NAMES.contains(&self.network_name.as_str()),
"cannot use reserved network name '{network_name}' as configured Testnet name, reserved names: {RESERVED_NETWORK_NAMES:?}"
);
assert!(
self.network_name.len() <= MAX_NETWORK_NAME_LENGTH,
"network name {network_name} is too long, must be {MAX_NETWORK_NAME_LENGTH} characters or less"
);
assert!(
self.network_name
.chars()
.all(|x| x.is_alphanumeric() || x == '_'),
"network name must include only alphanumeric characters or '_'"
);
self
}
@ -188,6 +212,7 @@ impl Default for Parameters {
/// Returns an instance of the default public testnet [`Parameters`].
fn default() -> Self {
Self {
network_name: "Testnet".to_string(),
activation_heights: TESTNET_ACTIVATION_HEIGHTS.iter().cloned().collect(),
..Self::build().finish()
}

View File

@ -5,7 +5,9 @@ use zcash_primitives::consensus::{self as zp_consensus, Parameters};
use crate::{
block::Height,
parameters::{
testnet::{self, ConfiguredActivationHeights},
testnet::{
self, ConfiguredActivationHeights, MAX_NETWORK_NAME_LENGTH, RESERVED_NETWORK_NAMES,
},
Network, NetworkUpgrade, NETWORK_UPGRADES_IN_ORDER,
},
};
@ -125,3 +127,58 @@ fn activates_network_upgrades_correctly() {
);
}
}
/// Checks that configured testnet names are validated and used correctly.
#[test]
fn check_network_name() {
// Sets a no-op panic hook to avoid long output.
std::panic::set_hook(Box::new(|_| {}));
// Checks that reserved network names cannot be used for configured testnets.
for reserved_network_name in RESERVED_NETWORK_NAMES {
std::panic::catch_unwind(|| {
testnet::Parameters::build().network_name(reserved_network_name)
})
.expect_err("should panic when attempting to set network name as a reserved name");
}
// Check that max length is enforced, and that network names may only contain alphanumeric characters and '_'.
for invalid_network_name in [
"a".repeat(MAX_NETWORK_NAME_LENGTH + 1),
"!!!!non-alphanumeric-name".to_string(),
] {
std::panic::catch_unwind(|| {
testnet::Parameters::build().network_name(invalid_network_name)
})
.expect_err("should panic when setting network name that's too long or contains non-alphanumeric characters (except '_')");
}
// Checks that network names are displayed correctly
assert_eq!(
Network::new_default_testnet().to_string(),
"Testnet",
"default testnet should be displayed as 'Testnet'"
);
assert_eq!(
Network::Mainnet.to_string(),
"Mainnet",
"Mainnet should be displayed as 'Mainnet'"
);
// TODO: Check Regtest
// Check that network name can contain alphanumeric characters and '_'.
let expected_name = "ConfiguredTestnet_1";
let network = testnet::Parameters::build()
// Check that network name can contain `MAX_NETWORK_NAME_LENGTH` characters
.network_name("a".repeat(MAX_NETWORK_NAME_LENGTH))
.network_name(expected_name)
.to_network();
// Check that configured network name is displayed
assert_eq!(
network.to_string(),
expected_name,
"network must be displayed as configured network name"
);
}