Return correct errors for incorrectly encoded unified containers.
This commit is contained in:
parent
ba3ff42e13
commit
76082e4287
|
@ -46,11 +46,19 @@ impl FromStr for ZcashAddress {
|
|||
let s = s.trim();
|
||||
|
||||
// Try decoding as a unified address
|
||||
if let Ok((net, data)) = unified::Address::decode(s) {
|
||||
return Ok(ZcashAddress {
|
||||
net,
|
||||
kind: AddressKind::Unified(data),
|
||||
});
|
||||
match unified::Address::decode(s) {
|
||||
Ok((net, data)) => {
|
||||
return Ok(ZcashAddress {
|
||||
net,
|
||||
kind: AddressKind::Unified(data),
|
||||
});
|
||||
}
|
||||
Err(unified::ParseError::NotUnified) => {
|
||||
// allow decoding to fall through to Sapling/Transparent
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(ParseError::Unified(e));
|
||||
}
|
||||
}
|
||||
|
||||
// Try decoding as a Sapling address (Bech32)
|
||||
|
|
|
@ -112,6 +112,10 @@ pub enum ParseError {
|
|||
InvalidEncoding(String),
|
||||
/// The unified container only contains transparent items.
|
||||
OnlyTransparent,
|
||||
/// The string is not Bech32m encoded, and so cannot be a unified address.
|
||||
NotUnified,
|
||||
/// The Bech32m string has an unrecognized human-readable prefix.
|
||||
UnknownPrefix(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
|
@ -122,6 +126,10 @@ impl fmt::Display for ParseError {
|
|||
ParseError::InvalidTypecodeValue(v) => write!(f, "Typecode value out of range {}", v),
|
||||
ParseError::InvalidEncoding(msg) => write!(f, "Invalid encoding: {}", msg),
|
||||
ParseError::OnlyTransparent => write!(f, "UA only contains transparent items"),
|
||||
ParseError::NotUnified => write!(f, "Address is not Bech32m encoded"),
|
||||
ParseError::UnknownPrefix(s) => {
|
||||
write!(f, "Unrecognized Bech32m human-readable prefix: {}", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -303,25 +311,20 @@ pub trait Encoding: private::SealedContainer + std::marker::Sized {
|
|||
}
|
||||
|
||||
fn decode(s: &str) -> Result<(Network, Self), ParseError> {
|
||||
match bech32::decode(s) {
|
||||
Ok((hrp, data, Variant::Bech32m)) => {
|
||||
let hrp = hrp.as_str();
|
||||
// validate that the HRP corresponds to a known network.
|
||||
let net = Self::hrp_network(hrp).ok_or_else(|| {
|
||||
ParseError::InvalidEncoding(format!(
|
||||
"Unrecognized Bech32m human-readable prefix {}",
|
||||
hrp
|
||||
))
|
||||
})?;
|
||||
if let Ok((hrp, data, Variant::Bech32m)) = bech32::decode(s) {
|
||||
let hrp = hrp.as_str();
|
||||
// validate that the HRP corresponds to a known network.
|
||||
let net =
|
||||
Self::hrp_network(hrp).ok_or_else(|| ParseError::UnknownPrefix(hrp.to_string()))?;
|
||||
|
||||
let data = Vec::<u8>::from_base32(&data)
|
||||
.map_err(|e| ParseError::InvalidEncoding(e.to_string()))?;
|
||||
let data = Vec::<u8>::from_base32(&data)
|
||||
.map_err(|e| ParseError::InvalidEncoding(e.to_string()))?;
|
||||
|
||||
Self::parse_items(hrp, &data[..])
|
||||
.and_then(Self::try_from_items)
|
||||
.map(|value| (net, value))
|
||||
}
|
||||
_ => Err(ParseError::InvalidEncoding("Expected bech32m".to_string())),
|
||||
Self::parse_items(hrp, &data[..])
|
||||
.and_then(Self::try_from_items)
|
||||
.map(|value| (net, value))
|
||||
} else {
|
||||
Err(ParseError::NotUnified)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue