Add `P2shError` for handling errors related to P2sh

Added a new `P2shError` struct for handling errors emmited while
generating addresses from P2sh scripts.
This commit is contained in:
harshit933 2024-02-23 03:44:12 +05:30
parent 5182a8d7a8
commit c2d658ac05
2 changed files with 42 additions and 14 deletions

View File

@ -13,8 +13,6 @@ use crate::{base58, Network};
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
/// Address size more than 520 bytes is not allowed.
ExcessiveScriptSize,
/// Address's network differs from required one.
NetworkValidation {
/// Network that was required.
@ -31,7 +29,6 @@ impl fmt::Display for Error {
use Error::*;
match *self {
ExcessiveScriptSize => write!(f, "script size exceed 520 bytes"),
NetworkValidation { required, ref address } => {
write!(f, "address ")?;
fmt::Display::fmt(&address.0, f)?;
@ -47,15 +44,16 @@ impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use Error::*;
match self {
UnknownHrp(e) => Some(e),
ExcessiveScriptSize | NetworkValidation { .. } => None,
match *self {
UnknownHrp(ref e) => Some(e),
NetworkValidation { .. } => None,
}
}
}
/// Error while generating address from script.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum FromScriptError {
/// Script is not a p2pkh, p2sh or witness program.
UnrecognizedScript,
@ -82,20 +80,49 @@ 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),
match *self {
UnrecognizedScript => None,
WitnessVersion(ref e) => Some(e),
WitnessProgram(ref e) => Some(e),
}
}
}
impl From<witness_program::Error> for FromScriptError {
fn from(e : witness_program::Error) -> Self { FromScriptError::WitnessProgram(e)}
fn from(e : witness_program::Error) -> Self { Self::WitnessProgram(e) }
}
impl From<witness_version::TryFromError> for FromScriptError {
fn from(e: witness_version::TryFromError) -> Self { FromScriptError::WitnessVersion(e) }
fn from(e: witness_version::TryFromError) -> Self { Self::WitnessVersion(e) }
}
/// Error while generating address from a p2sh script.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum P2shError {
/// Address size more than 520 bytes is not allowed.
ExcessiveScriptSize,
}
impl fmt::Display for P2shError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use P2shError::*;
match *self {
ExcessiveScriptSize => write!(f, "script size exceed 520 bytes"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for P2shError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use P2shError::*;
match self {
ExcessiveScriptSize => None,
}
}
}
/// Address type is either invalid or not supported in rust-bitcoin.

View File

@ -51,6 +51,7 @@ use crate::network::{Network, NetworkKind};
use crate::prelude::*;
use crate::taproot::TapNodeHash;
use self::error::P2shError;
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(inline)]
pub use self::{
@ -373,9 +374,9 @@ impl Address {
/// This address type was introduced with BIP16 and is the popular type to implement multi-sig
/// these days.
#[inline]
pub fn p2sh(script: &Script, network: impl Into<NetworkKind>) -> Result<Address, Error> {
pub fn p2sh(script: &Script, network: impl Into<NetworkKind>) -> Result<Address, P2shError> {
if script.len() > MAX_SCRIPT_ELEMENT_SIZE {
return Err(Error::ExcessiveScriptSize);
return Err(P2shError::ExcessiveScriptSize);
}
let hash = script.script_hash();
Ok(Address::p2sh_from_hash(hash, network))
@ -861,7 +862,7 @@ mod tests {
#[test]
fn test_p2sh_parse_for_large_script() {
let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap();
assert_eq!(Address::p2sh(&script, NetworkKind::Test), Err(Error::ExcessiveScriptSize));
assert_eq!(Address::p2sh(&script, NetworkKind::Test), Err(P2shError::ExcessiveScriptSize));
}
#[test]