diff --git a/src/blockdata/block.rs b/src/blockdata/block.rs index 85f0fc04..06a53298 100644 --- a/src/blockdata/block.rs +++ b/src/blockdata/block.rs @@ -355,7 +355,16 @@ impl fmt::Display for Bip34Error { } #[cfg(feature = "std")] -impl ::std::error::Error for Bip34Error {} +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for Bip34Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Bip34Error::*; + + match self { + Unsupported | NotPresent | UnexpectedPush(_) => None, + } + } +} #[cfg(test)] mod tests { diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 7f50ff04..839a7c29 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -188,7 +188,20 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for Error {} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + NonMinimalPush + | EarlyEndOfScript + | NumericOverflow + | BitcoinConsensus(_) // TODO: This should return `Some` but bitcoinconsensus::Error does not implement Error. + | UnknownSpentOutput(_) + | SerializationError => None, + } + } +} // Our internal error proves that we only return these two cases from `read_uint_iter`. // Since it's private we don't bother with trait impls besides From. diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 7beac35c..c35a1b65 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -27,7 +27,6 @@ use crate::prelude::*; use crate::io; use core::{fmt, str, default::Default}; -#[cfg(feature = "std")] use std::error; use crate::hashes::{self, Hash, sha256d}; use crate::hashes::hex::FromHex; @@ -142,12 +141,14 @@ impl fmt::Display for ParseOutPointError { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl error::Error for ParseOutPointError { - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - ParseOutPointError::Txid(ref e) => Some(e), - ParseOutPointError::Vout(ref e) => Some(e), - _ => None, +impl std::error::Error for ParseOutPointError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::ParseOutPointError::*; + + match self { + Txid(e) => Some(e), + Vout(e) => Some(e), + Format | TooLong | VoutNotCanonical => None, } } } @@ -733,7 +734,11 @@ impl fmt::Display for NonStandardSighashType { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl error::Error for NonStandardSighashType {} +impl std::error::Error for NonStandardSighashType { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} /// Legacy Hashtype of an input's signature #[deprecated(since = "0.28.0", note = "Please use [`EcdsaSighashType`] instead")] @@ -886,9 +891,13 @@ impl fmt::Display for SighashTypeParseError { } } -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg(feature = "std")] -impl ::std::error::Error for SighashTypeParseError {} +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for SighashTypeParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} #[cfg(test)] mod tests { diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index fe7dff14..6505df37 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -30,7 +30,6 @@ use crate::prelude::*; use core::{fmt, mem, u32, convert::From}; -#[cfg(feature = "std")] use std::error; use crate::hashes::{sha256d, Hash, sha256}; use crate::hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader}; @@ -106,18 +105,20 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - Error::Io(ref e) => Some(e), - Error::Psbt(ref e) => Some(e), - Error::UnexpectedNetworkMagic { .. } - | Error::OversizedVectorAllocation { .. } - | Error::InvalidChecksum { .. } - | Error::NonMinimalVarInt - | Error::UnknownNetworkMagic(..) - | Error::ParseFailed(..) - | Error::UnsupportedSegwitFlag(..) => None, +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + Io(e) => Some(e), + Psbt(e) => Some(e), + UnexpectedNetworkMagic { .. } + | OversizedVectorAllocation { .. } + | InvalidChecksum { .. } + | NonMinimalVarInt + | UnknownNetworkMagic(_) + | ParseFailed(_) + | UnsupportedSegwitFlag(_) => None, } } } diff --git a/src/network/message.rs b/src/network/message.rs index fe9bf4e8..ea676f6b 100644 --- a/src/network/message.rs +++ b/src/network/message.rs @@ -111,9 +111,13 @@ impl fmt::Display for CommandStringError { } } -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg(feature = "std")] -impl ::std::error::Error for CommandStringError {} +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for CommandStringError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} /// A Network message #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/network/mod.rs b/src/network/mod.rs index 362201d4..2686e0ef 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -20,7 +20,6 @@ use crate::io; use core::fmt; -#[cfg(feature = "std")] use std::error; pub mod constants; @@ -79,11 +78,13 @@ impl From for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - Error::Io(ref e) => Some(e), - Error::SocketMutexPoisoned | Error::SocketNotConnectedToPeer => None, +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + Io(e) => Some(e), + SocketMutexPoisoned | SocketNotConnectedToPeer => None, } } } diff --git a/src/util/address.rs b/src/util/address.rs index 5c7e10bf..afa4c714 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -37,7 +37,6 @@ use crate::prelude::*; use core::fmt; use core::num::ParseIntError; use core::str::FromStr; -#[cfg(feature = "std")] use std::error; use secp256k1::{Secp256k1, Verification, XOnlyPublicKey}; use bech32; @@ -104,13 +103,22 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - Error::Base58(ref e) => Some(e), - Error::Bech32(ref e) => Some(e), - Error::UnparsableWitnessVersion(ref e) => Some(e), - _ => None, +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + Base58(e) => Some(e), + Bech32(e) => Some(e), + UnparsableWitnessVersion(e) => Some(e), + EmptyBech32Payload + | InvalidBech32Variant { .. } + | InvalidWitnessVersion(_) + | MalformedWitnessVersion + | InvalidWitnessProgramLength(_) + | InvalidSegwitV0ProgramLength(_) + | UncompressedPubkey + | ExcessiveScriptSize => None, } } } diff --git a/src/util/amount.rs b/src/util/amount.rs index aa888f89..eebca346 100644 --- a/src/util/amount.rs +++ b/src/util/amount.rs @@ -192,7 +192,7 @@ impl fmt::Display for ParseAmountError { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for ParseAmountError {} +impl std::error::Error for ParseAmountError {} fn is_too_precise(s: &str, precision: usize) -> bool { s.contains('.') || precision >= s.len() || s.chars().rev().take(precision).any(|d| d != '0') diff --git a/src/util/base58.rs b/src/util/base58.rs index fc525d1b..70e8c5d4 100644 --- a/src/util/base58.rs +++ b/src/util/base58.rs @@ -57,8 +57,8 @@ impl fmt::Display for Error { Error::BadByte(b) => write!(f, "invalid base58 character 0x{:x}", b), Error::BadChecksum(exp, actual) => write!(f, "base58ck checksum 0x{:x} does not match expected 0x{:x}", actual, exp), Error::InvalidLength(ell) => write!(f, "length {} invalid for this base58 type", ell), - Error::InvalidAddressVersion(ref v) => write!(f, "address version {} is invalid for this base58 type", v), Error::InvalidExtendedKeyVersion(ref v) => write!(f, "extended key version {:#04x?} is invalid for this base58 type", v), + Error::InvalidAddressVersion(ref v) => write!(f, "address version {} is invalid for this base58 type", v), Error::TooShort(_) => write!(f, "base58ck data not even long enough for a checksum"), Error::Secp256k1(ref e) => fmt::Display::fmt(&e, f), Error::Hex(ref e) => write!(f, "Hexadecimal decoding error: {}", e) @@ -68,7 +68,22 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for Error {} +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + BadByte(_) + | BadChecksum(_, _) + | InvalidLength(_) + | InvalidExtendedKeyVersion(_) + | InvalidAddressVersion(_) + | TooShort(_) => None, + Secp256k1(e) => Some(e), + Hex(e) => Some(e), + } + } +} /// Vector-like object that holds the first 100 elements on the stack. If more space is needed it /// will be allocated on the heap. diff --git a/src/util/bip158.rs b/src/util/bip158.rs index 4422bcc4..4dda211b 100644 --- a/src/util/bip158.rs +++ b/src/util/bip158.rs @@ -74,10 +74,6 @@ pub enum Error { Io(io::Error), } -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for Error {} - impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { match *self { @@ -87,6 +83,20 @@ impl Display for Error { } } +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + UtxoMissing(_) => None, + Io(e) => Some(e), + } + } +} + + impl From for Error { fn from(io: io::Error) -> Self { Error::Io(io) diff --git a/src/util/bip32.rs b/src/util/bip32.rs index e268e1fc..0bc23c64 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -22,7 +22,6 @@ use crate::prelude::*; use crate::io::Write; use core::{fmt, str::FromStr, default::Default}; use core::ops::Index; -#[cfg(feature = "std")] use std::error; #[cfg(feature = "serde")] use serde; use crate::hash_types::XpubIdentifier; @@ -497,12 +496,20 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { - if let Error::Secp256k1(ref e) = *self { - Some(e) - } else { - None +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + Secp256k1(e) => Some(e), + Base58(e) => Some(e), + Hex(e) => Some(e), + CannotDeriveFromHardenedKey + | InvalidChildNumber(_) + | InvalidChildNumberFormat + | InvalidDerivationPathFormat + | UnknownVersion(_) + | WrongExtendedKeyLength(_) => None, } } } diff --git a/src/util/ecdsa.rs b/src/util/ecdsa.rs index 37a31649..185b22f6 100644 --- a/src/util/ecdsa.rs +++ b/src/util/ecdsa.rs @@ -102,20 +102,31 @@ pub enum EcdsaSigError { impl fmt::Display for EcdsaSigError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { + EcdsaSigError::HexEncoding(e) => + write!(f, "EcdsaSig hex encoding error: {}", e), EcdsaSigError::NonStandardSighashType(hash_ty) => write!(f, "Non standard signature hash type {}", hash_ty), - EcdsaSigError::Secp256k1(ref e) => - write!(f, "Invalid Ecdsa signature: {}", e), EcdsaSigError::EmptySignature => write!(f, "Empty ECDSA signature"), - EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e) + EcdsaSigError::Secp256k1(ref e) => + write!(f, "Invalid Ecdsa signature: {}", e), } } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for EcdsaSigError {} +impl std::error::Error for EcdsaSigError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::EcdsaSigError::*; + + match self { + HexEncoding(e) => Some(e), + Secp256k1(e) => Some(e), + NonStandardSighashType(_) | EmptySignature => None, + } + } +} impl From for EcdsaSigError { fn from(e: secp256k1::Error) -> EcdsaSigError { diff --git a/src/util/key.rs b/src/util/key.rs index 156dfc90..aab5e617 100644 --- a/src/util/key.rs +++ b/src/util/key.rs @@ -16,16 +16,14 @@ //! This module provides keys used in Bitcoin that can be roundtrip //! (de)serialized. -pub use secp256k1::{XOnlyPublicKey, KeyPair}; - use crate::prelude::*; use core::{ops, str::FromStr}; use core::fmt::{self, Write}; -use crate::io; -#[cfg(feature = "std")] use std::error; -use secp256k1::{self, Secp256k1}; +pub use secp256k1::{self, Secp256k1, XOnlyPublicKey, KeyPair}; + +use crate::io; use crate::network::constants::Network; use crate::hashes::{Hash, hash160, hex, hex::FromHex}; use crate::hash_types::{PubkeyHash, WPubkeyHash}; @@ -57,13 +55,15 @@ impl fmt::Display for Error { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - Error::Base58(ref e) => Some(e), - Error::Secp256k1(ref e) => Some(e), - Error::InvalidKeyPrefix(_) => None, - Error::Hex(ref e) => Some(e) +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + Base58(e) => Some(e), + Secp256k1(e) => Some(e), + InvalidKeyPrefix(_) => None, + Hex(e) => Some(e), } } } diff --git a/src/util/misc.rs b/src/util/misc.rs index 43659c5a..9f61f563 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -37,7 +37,6 @@ mod message_signing { #[cfg(feature = "base64")] use crate::prelude::*; use core::fmt; - #[cfg(feature = "std")] use std::error; use crate::hashes::sha256d; use secp256k1; @@ -73,11 +72,13 @@ mod message_signing { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] - impl error::Error for MessageSignatureError { - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - MessageSignatureError::InvalidEncoding(ref e) => Some(e), - _ => None, + impl std::error::Error for MessageSignatureError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::MessageSignatureError::*; + + match self { + InvalidEncoding(e) => Some(e), + InvalidLength | InvalidBase64 | UnsupportedAddressType(_) => None, } } } diff --git a/src/util/mod.rs b/src/util/mod.rs index e15210fa..2d3d8a23 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -39,7 +39,6 @@ pub(crate) mod endian; use crate::prelude::*; use crate::io; use core::fmt; -#[cfg(feature = "std")] use std::error; use crate::network; use crate::consensus::encode; @@ -91,12 +90,16 @@ impl fmt::Display for Error { } #[cfg(feature = "std")] -impl ::std::error::Error for Error { - fn cause(&self) -> Option<&dyn error::Error> { - match *self { - Error::Encode(ref e) => Some(e), - Error::Network(ref e) => Some(e), - Error::BlockBadProofOfWork | Error::BlockBadTarget => None +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + Encode(e) => Some(e), + Network(e) => Some(e), + BlockBadProofOfWork + | BlockBadTarget => None } } } diff --git a/src/util/psbt/error.rs b/src/util/psbt/error.rs index 4dbc3ae8..b191e28b 100644 --- a/src/util/psbt/error.rs +++ b/src/util/psbt/error.rs @@ -88,34 +88,59 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { + Error::InvalidMagic => f.write_str("invalid magic"), + Error::MissingUtxo => f.write_str("UTXO information is not present in PSBT"), + Error::InvalidSeparator => f.write_str("invalid separator"), + Error::PsbtUtxoOutOfbounds => f.write_str("output index is out of bounds of non witness script output array"), Error::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), Error::InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"), Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), - Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()), - Error::NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), - Error::InvalidMagic => f.write_str("invalid magic"), - Error::InvalidSeparator => f.write_str("invalid separator"), Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"), Error::UnsignedTxHasScriptWitnesses => f.write_str("the unsigned transaction has script witnesses"), Error::MustHaveUnsignedTx => { f.write_str("partially signed transactions must have an unsigned transaction") } Error::NoMorePairs => f.write_str("no more key-value pairs for this psbt map"), + Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()), + Error::NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), Error::HashParseError(e) => write!(f, "Hash Parse Error: {}", e), - Error::MissingUtxo => f.write_str("UTXO information is not present in PSBT"), - Error::PsbtUtxoOutOfbounds => f.write_str("output index is out of bounds of non witness script output array"), Error::InvalidPreimageHashPair{ref preimage, ref hash, ref hash_type} => { // directly using debug forms of psbthash enums write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash ) - } - Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) } + }, + Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) }, Error::ConsensusEncoding => f.write_str("bitcoin consensus or BIP-174 encoding error"), } } } #[cfg(feature = "std")] -impl ::std::error::Error for Error {} +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + HashParseError(e) => Some(e), + | InvalidMagic + | MissingUtxo + | InvalidSeparator + | PsbtUtxoOutOfbounds + | InvalidKey(_) + | InvalidProprietaryKey + | DuplicateKey(_) + | UnsignedTxHasScriptSigs + | UnsignedTxHasScriptWitnesses + | MustHaveUnsignedTx + | NoMorePairs + | UnexpectedUnsignedTx { .. } + | NonStandardSighashType(_) + | InvalidPreimageHashPair{ .. } + | CombineInconsistentKeySources(_) + | ConsensusEncoding => None, + } + } +} #[doc(hidden)] impl From for Error { diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 57d5a57a..08ba533d 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -110,7 +110,15 @@ impl core::fmt::Display for IncompleteTapTree { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for IncompleteTapTree {} +impl std::error::Error for IncompleteTapTree { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::IncompleteTapTree::*; + + match self { + NotFinalized(_) | HiddenParts(_) => None, + } + } +} /// Taproot Tree representing a finalized [`TaprootBuilder`] (a complete binary tree). #[derive(Clone, Debug)] diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index a1915226..81aeefa3 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -241,7 +241,16 @@ mod display_from_str { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] - impl ::std::error::Error for PsbtParseError {} + impl std::error::Error for PsbtParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::PsbtParseError::*; + + match self { + PsbtEncoding(e) => Some(e), + Base64Encoding(e) => Some(e), + } + } + } #[cfg_attr(docsrs, doc(cfg(feature = "base64")))] impl Display for PartiallySignedTransaction { diff --git a/src/util/schnorr.rs b/src/util/schnorr.rs index cb5f59f3..8d679120 100644 --- a/src/util/schnorr.rs +++ b/src/util/schnorr.rs @@ -286,7 +286,16 @@ impl fmt::Display for SchnorrSigError { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for SchnorrSigError {} +impl std::error::Error for SchnorrSigError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::SchnorrSigError::*; + + match self { + Secp256k1(e) => Some(e), + InvalidSighashType(_) | InvalidSchnorrSigSize(_) => None, + } + } +} impl From for SchnorrSigError { diff --git a/src/util/sighash.rs b/src/util/sighash.rs index 9de333df..63b1a147 100644 --- a/src/util/sighash.rs +++ b/src/util/sighash.rs @@ -224,7 +224,23 @@ impl fmt::Display for Error { } #[cfg(feature = "std")] -impl ::std::error::Error for Error {} +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::Error::*; + + match self { + Io(_) + | IndexOutOfInputsBounds { .. } + | SingleWithoutCorrespondingOutput { .. } + | PrevoutsSize + | PrevoutIndex + | PrevoutKind + | WrongAnnex + | InvalidSighashType(_) => None, + } + } +} impl<'u, T> Prevouts<'u, T> where T: Borrow { fn check_all(&self, tx: &Transaction) -> Result<(), Error> { diff --git a/src/util/taproot.rs b/src/util/taproot.rs index b6226736..b1efc1da 100644 --- a/src/util/taproot.rs +++ b/src/util/taproot.rs @@ -22,8 +22,6 @@ use secp256k1::{self, Secp256k1}; use core::fmt; use core::cmp::Reverse; -#[cfg(feature = "std")] -use std::error; use crate::hashes::{sha256, Hash, HashEngine}; use crate::schnorr::{TweakedPublicKey, UntweakedPublicKey, TapTweak}; @@ -486,7 +484,7 @@ impl TaprootBuilder { // We cannot insert a leaf at a lower depth while a deeper branch is unfinished. Doing // so would mean the add_leaf/add_hidden invocations do not correspond to a DFS traversal of a // binary tree. - if depth as usize + 1 < self.branch.len() { + if (depth as usize + 1) < self.branch.len() { return Err(TaprootBuilderError::NodeNotInDfsOrder); } @@ -989,6 +987,9 @@ pub enum TaprootBuilderError { impl fmt::Display for TaprootBuilderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { + TaprootBuilderError::InvalidMerkleTreeDepth(d) => { + write!(f, "Merkle Tree depth({}) must be less than {}", d, TAPROOT_CONTROL_MAX_NODE_COUNT) + } TaprootBuilderError::NodeNotInDfsOrder => { write!(f, "add_leaf/add_hidden must be called in DFS walk order",) } @@ -997,9 +998,6 @@ impl fmt::Display for TaprootBuilderError { "Attempted to create a tree with two nodes at depth 0. There must\ only be a exactly one node at depth 0", ), - TaprootBuilderError::InvalidMerkleTreeDepth(d) => { - write!(f, "Merkle Tree depth({}) must be less than {}", d, TAPROOT_CONTROL_MAX_NODE_COUNT) - } TaprootBuilderError::InvalidInternalKey(e) => { write!(f, "Invalid Internal XOnly key : {}", e) } @@ -1015,7 +1013,20 @@ impl fmt::Display for TaprootBuilderError { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl error::Error for TaprootBuilderError {} +impl std::error::Error for TaprootBuilderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::TaprootBuilderError::*; + + match self { + InvalidInternalKey(e) => Some(e), + InvalidMerkleTreeDepth(_) + | NodeNotInDfsOrder + | OverCompleteTree + | IncompleteTree + | EmptyTree => None + } + } +} /// Detailed error type for taproot utilities. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1069,7 +1080,23 @@ impl fmt::Display for TaprootError { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl error::Error for TaprootError {} +impl std::error::Error for TaprootError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use self::TaprootError::*; + + match self { + InvalidInternalKey(e) => Some(e), + InvalidMerkleBranchSize(_) + | InvalidMerkleTreeDepth(_) + | InvalidTaprootLeafVersion(_) + | InvalidControlBlockSize(_) + | InvalidParity(_) + | EmptyTree => None, + } + } +} + + #[cfg(test)] mod test { use crate::{Address, Network}; diff --git a/src/util/uint.rs b/src/util/uint.rs index f19db23f..ccb702e7 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -528,7 +528,11 @@ impl ::core::fmt::Display for ParseLengthError { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for ParseLengthError {} +impl std::error::Error for ParseLengthError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + None + } +} impl Uint256 { /// Decay to a uint128