Add the `FromScriptError` for handling errors in `address`
This commit adds the `FromScriptError` struct to handle the errors while generating address from any script. It includes : - Unrecognized script error. - Witness Program error. - Witness Version error.
This commit is contained in:
parent
975ada3570
commit
05b24946eb
|
@ -73,6 +73,50 @@ impl From<witness_program::Error> for Error {
|
||||||
fn from(e: witness_program::Error) -> Error { Error::WitnessProgram(e) }
|
fn from(e: witness_program::Error) -> Error { Error::WitnessProgram(e) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error while generating address from script.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum FromScriptError {
|
||||||
|
/// Script is not a p2pkh, p2sh or witness program.
|
||||||
|
UnrecognizedScript,
|
||||||
|
/// A witness program error.
|
||||||
|
WitnessProgram(witness_program::Error),
|
||||||
|
/// A witness version construction error.
|
||||||
|
WitnessVersion(witness_version::TryFromError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FromScriptError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use FromScriptError::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
WitnessVersion(ref e) => write_err!(f, "witness version construction error"; e),
|
||||||
|
WitnessProgram(ref e) => write_err!(f, "witness program error"; e),
|
||||||
|
UnrecognizedScript => write!(f, "script is not a p2pkh, p2sh or witness program"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for FromScriptError {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use FromScriptError::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
WitnessVersion(e) => Some(e),
|
||||||
|
WitnessProgram(e) => Some(e),
|
||||||
|
UnrecognizedScript => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<witness_program::Error> for FromScriptError {
|
||||||
|
fn from(e : witness_program::Error) -> Self { FromScriptError::WitnessProgram(e)}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<witness_version::TryFromError> for FromScriptError {
|
||||||
|
fn from(e: witness_version::TryFromError) -> Self { FromScriptError::WitnessVersion(e) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Address type is either invalid or not supported in rust-bitcoin.
|
/// Address type is either invalid or not supported in rust-bitcoin.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
|
|
@ -54,7 +54,7 @@ use crate::taproot::TapNodeHash;
|
||||||
#[rustfmt::skip] // Keep public re-exports separate.
|
#[rustfmt::skip] // Keep public re-exports separate.
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use self::{
|
pub use self::{
|
||||||
error::{Error, ParseError, UnknownAddressTypeError, UnknownHrpError},
|
error::{Error, ParseError, UnknownAddressTypeError, UnknownHrpError, FromScriptError},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The different types of addresses.
|
/// The different types of addresses.
|
||||||
|
@ -503,7 +503,7 @@ impl Address {
|
||||||
pub fn is_spend_standard(&self) -> bool { self.address_type().is_some() }
|
pub fn is_spend_standard(&self) -> bool { self.address_type().is_some() }
|
||||||
|
|
||||||
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
|
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
|
||||||
pub fn from_script(script: &Script, network: Network) -> Result<Address, Error> {
|
pub fn from_script(script: &Script, network: Network) -> Result<Address, FromScriptError> {
|
||||||
if script.is_p2pkh() {
|
if script.is_p2pkh() {
|
||||||
let bytes = script.as_bytes()[3..23].try_into().expect("statically 20B long");
|
let bytes = script.as_bytes()[3..23].try_into().expect("statically 20B long");
|
||||||
let hash = PubkeyHash::from_byte_array(bytes);
|
let hash = PubkeyHash::from_byte_array(bytes);
|
||||||
|
@ -519,7 +519,7 @@ impl Address {
|
||||||
let program = WitnessProgram::new(version, &script.as_bytes()[2..])?;
|
let program = WitnessProgram::new(version, &script.as_bytes()[2..])?;
|
||||||
Ok(Address::from_witness_program(program, network))
|
Ok(Address::from_witness_program(program, network))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::UnrecognizedScript)
|
Err(FromScriptError::UnrecognizedScript)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1236,13 +1236,13 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let invalid_segwitv0_script =
|
let invalid_segwitv0_script =
|
||||||
ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
|
ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
|
||||||
let expected = Err(Error::UnrecognizedScript);
|
let expected = Err(FromScriptError::UnrecognizedScript);
|
||||||
|
|
||||||
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
|
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
|
||||||
assert_eq!(Address::from_script(&bad_p2wsh, Network::Bitcoin), expected);
|
assert_eq!(Address::from_script(&bad_p2wsh, Network::Bitcoin), expected);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Address::from_script(&invalid_segwitv0_script, Network::Bitcoin),
|
Address::from_script(&invalid_segwitv0_script, Network::Bitcoin),
|
||||||
Err(Error::WitnessProgram(witness_program::Error::InvalidSegwitV0Length(17)))
|
Err(FromScriptError::WitnessProgram(witness_program::Error::InvalidSegwitV0Length(17)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue