Adds `with_sapling_hrps()` method and uses it to set the Regtest HRPs in `new_regtest()`.
Adds a test for Sapling HRP validation
This commit is contained in:
parent
63623ae53f
commit
d8715909e2
|
@ -24,6 +24,9 @@ pub const RESERVED_NETWORK_NAMES: [&str; 6] = [
|
|||
/// Maximum length for a configured network name.
|
||||
pub const MAX_NETWORK_NAME_LENGTH: usize = 30;
|
||||
|
||||
/// Maximum length for a configured human-readable prefix.
|
||||
pub const MAX_HRP_LENGTH: usize = 30;
|
||||
|
||||
/// Configurable activation heights for Regtest and configured Testnets.
|
||||
#[derive(Deserialize, Default)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
|
@ -103,6 +106,44 @@ impl ParametersBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Checks that the provided Sapling human-readable prefixes (HRPs) are valid and unique, then
|
||||
/// sets the Sapling HRPs to be used in the [`Parameters`] being built.
|
||||
pub fn with_sapling_hrps(
|
||||
mut self,
|
||||
hrp_sapling_extended_spending_key: impl fmt::Display,
|
||||
hrp_sapling_extended_full_viewing_key: impl fmt::Display,
|
||||
hrp_sapling_payment_address: impl fmt::Display,
|
||||
) -> Self {
|
||||
self.hrp_sapling_extended_spending_key = hrp_sapling_extended_spending_key.to_string();
|
||||
self.hrp_sapling_extended_full_viewing_key =
|
||||
hrp_sapling_extended_full_viewing_key.to_string();
|
||||
self.hrp_sapling_payment_address = hrp_sapling_payment_address.to_string();
|
||||
|
||||
let sapling_hrps = [
|
||||
&self.hrp_sapling_extended_spending_key,
|
||||
&self.hrp_sapling_extended_full_viewing_key,
|
||||
&self.hrp_sapling_payment_address,
|
||||
];
|
||||
|
||||
for sapling_hrp in sapling_hrps {
|
||||
assert!(sapling_hrp.len() <= MAX_HRP_LENGTH, "Sapling human-readable prefix {sapling_hrp} is too long, must be {MAX_HRP_LENGTH} characters or less");
|
||||
assert!(
|
||||
sapling_hrp.chars().all(|c| c.is_ascii_lowercase() || c == '-'),
|
||||
"human-readable prefixes should contain only lowercase ASCII characters and dashes, hrp: {sapling_hrp}"
|
||||
);
|
||||
assert_eq!(
|
||||
sapling_hrps
|
||||
.iter()
|
||||
.filter(|&&hrp| hrp == sapling_hrp)
|
||||
.count(),
|
||||
1,
|
||||
"Sapling human-readable prefixes must be unique, repeated Sapling HRP: {sapling_hrp}"
|
||||
);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Checks that the provided network upgrade activation heights are in the correct order, then
|
||||
/// sets them as the new network upgrade activation heights.
|
||||
pub fn with_activation_heights(
|
||||
|
@ -233,7 +274,13 @@ impl Parameters {
|
|||
Self {
|
||||
network_name: "Regtest".to_string(),
|
||||
..Self::build()
|
||||
// Removes default Testnet activation heights, most network upgrades are disabled by default for Regtest
|
||||
.with_sapling_hrps(
|
||||
zp_constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY,
|
||||
zp_constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
|
||||
zp_constants::regtest::HRP_SAPLING_PAYMENT_ADDRESS,
|
||||
)
|
||||
// Removes default Testnet activation heights if not configured,
|
||||
// most network upgrades are disabled by default for Regtest in zcashd
|
||||
.with_activation_heights(activation_heights)
|
||||
.finish()
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ fn activates_network_upgrades_correctly() {
|
|||
|
||||
/// Checks that configured testnet names are validated and used correctly.
|
||||
#[test]
|
||||
fn check_network_name() {
|
||||
fn check_configured_network_name() {
|
||||
// Sets a no-op panic hook to avoid long output.
|
||||
std::panic::set_hook(Box::new(|_| {}));
|
||||
|
||||
|
@ -206,3 +206,64 @@ fn check_network_name() {
|
|||
"network must be displayed as configured network name"
|
||||
);
|
||||
}
|
||||
|
||||
/// Checks that configured Sapling human-readable prefixes (HRPs) are validated and used correctly.
|
||||
#[test]
|
||||
fn check_configured_sapling_hrps() {
|
||||
// Sets a no-op panic hook to avoid long output.
|
||||
std::panic::set_hook(Box::new(|_| {}));
|
||||
|
||||
// Check that configured Sapling HRPs must be unique.
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_sapling_hrps("", "", "");
|
||||
})
|
||||
.expect_err("should panic when setting non-unique Sapling HRPs");
|
||||
|
||||
// Check that max length is enforced, and that network names may only contain lowecase ASCII characters and dashes.
|
||||
for invalid_hrp in [
|
||||
"a".repeat(MAX_NETWORK_NAME_LENGTH + 1),
|
||||
"!!!!non-alphabetical-name".to_string(),
|
||||
"A".to_string(),
|
||||
] {
|
||||
std::panic::catch_unwind(|| {
|
||||
testnet::Parameters::build().with_sapling_hrps(invalid_hrp, "dummy-hrp-a", "dummy-hrp-b");
|
||||
})
|
||||
.expect_err("should panic when setting Sapling HRPs that are too long or contain non-alphanumeric characters (except '-')");
|
||||
}
|
||||
|
||||
// Check that Sapling HRPs can contain lowercase ascii characters and dashes.
|
||||
let expected_hrp_sapling_extended_spending_key = "sapling-hrp-a";
|
||||
let expected_hrp_sapling_extended_full_viewing_key = "sapling-hrp-b";
|
||||
let expected_hrp_sapling_payment_address = "sapling-hrp-c";
|
||||
|
||||
let network = testnet::Parameters::build()
|
||||
// Check that Sapling HRPs can contain `MAX_NETWORK_NAME_LENGTH` characters
|
||||
.with_sapling_hrps(
|
||||
"a".repeat(MAX_NETWORK_NAME_LENGTH),
|
||||
"dummy-hrp-a",
|
||||
"dummy-hrp-b",
|
||||
)
|
||||
.with_sapling_hrps(
|
||||
expected_hrp_sapling_extended_spending_key,
|
||||
expected_hrp_sapling_extended_full_viewing_key,
|
||||
expected_hrp_sapling_payment_address,
|
||||
)
|
||||
.to_network();
|
||||
|
||||
// Check that configured Sapling HRPs are returned by `Parameters` trait methods
|
||||
assert_eq!(
|
||||
network.hrp_sapling_extended_spending_key(),
|
||||
expected_hrp_sapling_extended_spending_key,
|
||||
"should return expected Sapling extended spending key HRP"
|
||||
);
|
||||
assert_eq!(
|
||||
network.hrp_sapling_extended_full_viewing_key(),
|
||||
expected_hrp_sapling_extended_full_viewing_key,
|
||||
"should return expected Sapling EFVK HRP"
|
||||
);
|
||||
assert_eq!(
|
||||
network.hrp_sapling_payment_address(),
|
||||
expected_hrp_sapling_payment_address,
|
||||
"should return expected Sapling payment address HRP"
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue