diff --git a/bitcoin/src/address/error.rs b/bitcoin/src/address/error.rs index 9c5fd46c..3f5854cf 100644 --- a/bitcoin/src/address/error.rs +++ b/bitcoin/src/address/error.rs @@ -4,7 +4,6 @@ use internals::write_err; use crate::address::{Address, NetworkUnchecked}; use crate::blockdata::script::{witness_program, witness_version}; -use crate::error::impl_std_error; use crate::prelude::String; use crate::{base58, Network}; @@ -83,6 +82,7 @@ impl From for Error { /// Address type is either invalid or not supported in rust-bitcoin. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct UnknownAddressTypeError(pub String); impl fmt::Display for UnknownAddressTypeError { @@ -91,10 +91,13 @@ impl fmt::Display for UnknownAddressTypeError { } } -impl_std_error!(UnknownAddressTypeError); +#[cfg(feature = "std")] +impl std::error::Error for UnknownAddressTypeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} /// Address parsing error. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum ParseError { /// Base58 error. diff --git a/bitcoin/src/amount.rs b/bitcoin/src/amount.rs index b93eeee6..394d469d 100644 --- a/bitcoin/src/amount.rs +++ b/bitcoin/src/amount.rs @@ -160,16 +160,17 @@ pub enum ParseAmountError { impl fmt::Display for ParseAmountError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ParseAmountError::*; + match *self { - ParseAmountError::Negative => f.write_str("amount is negative"), - ParseAmountError::TooBig => f.write_str("amount is too big"), - ParseAmountError::TooPrecise => f.write_str("amount has a too high precision"), - ParseAmountError::InvalidFormat => f.write_str("invalid number format"), - ParseAmountError::InputTooLarge => f.write_str("input string was too large"), - ParseAmountError::InvalidCharacter(c) => write!(f, "invalid character in input: {}", c), - ParseAmountError::UnknownDenomination(ref d) => - write!(f, "unknown denomination: {}", d), - ParseAmountError::PossiblyConfusingDenomination(ref d) => { + Negative => f.write_str("amount is negative"), + TooBig => f.write_str("amount is too big"), + TooPrecise => f.write_str("amount has a too high precision"), + InvalidFormat => f.write_str("invalid number format"), + InputTooLarge => f.write_str("input string was too large"), + InvalidCharacter(c) => write!(f, "invalid character in input: {}", c), + UnknownDenomination(ref d) => write!(f, "unknown denomination: {}", d), + PossiblyConfusingDenomination(ref d) => { let (letter, upper, lower) = match d.chars().next() { Some('M') => ('M', "Mega", "milli"), Some('P') => ('P', "Peta", "pico"), @@ -185,7 +186,7 @@ impl fmt::Display for ParseAmountError { #[cfg(feature = "std")] impl std::error::Error for ParseAmountError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::ParseAmountError::*; + use ParseAmountError::*; match *self { Negative diff --git a/bitcoin/src/base58.rs b/bitcoin/src/base58.rs index f4cdc6cf..4dcd0bd1 100644 --- a/bitcoin/src/base58.rs +++ b/bitcoin/src/base58.rs @@ -213,16 +213,18 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Error::*; + match *self { - Error::BadByte(b) => write!(f, "invalid base58 character {:#x}", b), - Error::BadChecksum(exp, actual) => + BadByte(b) => write!(f, "invalid base58 character {:#x}", b), + BadChecksum(exp, actual) => write!(f, "base58ck checksum {:#x} does not match expected {:#x}", actual, exp), - Error::InvalidLength(ell) => write!(f, "length {} invalid for this base58 type", ell), - Error::InvalidExtendedKeyVersion(ref v) => + InvalidLength(ell) => write!(f, "length {} invalid for this base58 type", ell), + InvalidExtendedKeyVersion(ref v) => write!(f, "extended key version {:#04x?} is invalid for this base58 type", v), - Error::InvalidAddressVersion(ref v) => + 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"), + TooShort(_) => write!(f, "base58ck data not even long enough for a checksum"), } } } @@ -230,7 +232,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; match self { BadByte(_) diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index a74a83d4..2ba70d73 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -314,7 +314,8 @@ impl Decodable for BlockTransactionsRequest { /// A transaction index is requested that is out of range from the /// corresponding block. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct TxIndexOutOfRangeError(u64); impl fmt::Display for TxIndexOutOfRangeError { @@ -329,7 +330,9 @@ impl fmt::Display for TxIndexOutOfRangeError { } #[cfg(feature = "std")] -impl error::Error for TxIndexOutOfRangeError {} +impl error::Error for TxIndexOutOfRangeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} /// A [BlockTransactions] structure is used to provide some of the transactions /// in a block, as requested. diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs index 97a4b222..cc93300d 100644 --- a/bitcoin/src/bip158.rs +++ b/bitcoin/src/bip158.rs @@ -70,9 +70,11 @@ pub enum Error { impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { + use Error::*; + match *self { - Error::UtxoMissing(ref coin) => write!(f, "unresolved UTXO {}", coin), - Error::Io(ref e) => write_err!(f, "IO error"; e), + UtxoMissing(ref coin) => write!(f, "unresolved UTXO {}", coin), + Io(ref e) => write_err!(f, "IO error"; e), } } } @@ -80,11 +82,11 @@ impl Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; - match self { + match *self { UtxoMissing(_) => None, - Io(e) => Some(e), + Io(ref e) => Some(e), } } } diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index 43b265f8..1d481800 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -494,21 +494,22 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Error::*; + match *self { - Error::CannotDeriveFromHardenedKey => + CannotDeriveFromHardenedKey => f.write_str("cannot derive hardened key from public key"), - Error::Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e), - Error::InvalidChildNumber(ref n) => + Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e), + InvalidChildNumber(ref n) => write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n), - Error::InvalidChildNumberFormat => f.write_str("invalid child number format"), - Error::InvalidDerivationPathFormat => f.write_str("invalid derivation path format"), - Error::UnknownVersion(ref bytes) => - write!(f, "unknown version magic bytes: {:?}", bytes), - Error::WrongExtendedKeyLength(ref len) => + InvalidChildNumberFormat => f.write_str("invalid child number format"), + InvalidDerivationPathFormat => f.write_str("invalid derivation path format"), + UnknownVersion(ref bytes) => write!(f, "unknown version magic bytes: {:?}", bytes), + WrongExtendedKeyLength(ref len) => write!(f, "encoded extended key data has wrong length {}", len), - Error::Base58(ref e) => write_err!(f, "base58 encoding error"; e), - Error::Hex(ref e) => write_err!(f, "Hexadecimal decoding error"; e), - Error::InvalidPublicKeyHexLength(got) => + Base58(ref e) => write_err!(f, "base58 encoding error"; e), + Hex(ref e) => write_err!(f, "Hexadecimal decoding error"; e), + InvalidPublicKeyHexLength(got) => write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got), } } @@ -517,12 +518,12 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; - match self { - Secp256k1(e) => Some(e), - Base58(e) => Some(e), - Hex(e) => Some(e), + match *self { + Secp256k1(ref e) => Some(e), + Base58(ref e) => Some(e), + Hex(ref e) => Some(e), CannotDeriveFromHardenedKey | InvalidChildNumber(_) | InvalidChildNumberFormat diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 3c103c5a..d04153b3 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -387,13 +387,15 @@ pub enum Bip34Error { impl fmt::Display for Bip34Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Bip34Error::*; + match *self { - Bip34Error::Unsupported => write!(f, "block doesn't support BIP34"), - Bip34Error::NotPresent => write!(f, "BIP34 push not present in block's coinbase"), - Bip34Error::UnexpectedPush(ref p) => { + Unsupported => write!(f, "block doesn't support BIP34"), + NotPresent => write!(f, "BIP34 push not present in block's coinbase"), + UnexpectedPush(ref p) => { write!(f, "unexpected byte push of > 8 bytes: {:?}", p) } - Bip34Error::NegativeHeight => write!(f, "negative BIP34 height"), + NegativeHeight => write!(f, "negative BIP34 height"), } } } @@ -401,16 +403,17 @@ impl fmt::Display for Bip34Error { #[cfg(feature = "std")] impl std::error::Error for Bip34Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Bip34Error::*; + use Bip34Error::*; - match self { + match *self { Unsupported | NotPresent | UnexpectedPush(_) | NegativeHeight => None, } } } /// A block validation error. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum ValidationError { /// The header hash is not below the target. BadProofOfWork, diff --git a/bitcoin/src/blockdata/locktime/absolute.rs b/bitcoin/src/blockdata/locktime/absolute.rs index b3b7ddd1..5f5a27bd 100644 --- a/bitcoin/src/blockdata/locktime/absolute.rs +++ b/bitcoin/src/blockdata/locktime/absolute.rs @@ -575,7 +575,7 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Error::*; + use Error::*; match *self { Conversion(ref e) => write_err!(f, "error converting lock time value"; e), @@ -588,7 +588,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; match *self { Conversion(ref e) => Some(e), @@ -614,7 +614,8 @@ impl From for Error { } /// An error that occurs when converting a `u32` to a lock time variant. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct ConversionError { /// The expected timelock unit, height (blocks) or time (seconds). unit: LockTimeUnit, @@ -637,7 +638,9 @@ impl fmt::Display for ConversionError { } #[cfg(feature = "std")] -impl std::error::Error for ConversionError {} +impl std::error::Error for ConversionError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} /// Describes the two types of locking, lock-by-blockheight and lock-by-blocktime. #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] @@ -669,7 +672,7 @@ pub enum OperationError { impl fmt::Display for OperationError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::OperationError::*; + use OperationError::*; match *self { InvalidComparison => @@ -679,7 +682,15 @@ impl fmt::Display for OperationError { } #[cfg(feature = "std")] -impl std::error::Error for OperationError {} +impl std::error::Error for OperationError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use OperationError::*; + + match *self { + InvalidComparison => None, + } + } +} #[cfg(test)] mod tests { diff --git a/bitcoin/src/blockdata/locktime/relative.rs b/bitcoin/src/blockdata/locktime/relative.rs index a61117c1..fca20938 100644 --- a/bitcoin/src/blockdata/locktime/relative.rs +++ b/bitcoin/src/blockdata/locktime/relative.rs @@ -311,15 +311,17 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Error::*; + match *self { - Self::IntegerOverflow(val) => write!( + IntegerOverflow(val) => write!( f, "{} seconds is too large to be encoded to a 16 bit 512 second interval", val ), - Self::IncompatibleHeight(lock, height) => + IncompatibleHeight(lock, height) => write!(f, "tried to satisfy lock {} with height: {}", lock, height), - Self::IncompatibleTime(lock, time) => + IncompatibleTime(lock, time) => write!(f, "tried to satisfy lock {} with time: {}", lock, time), } } @@ -328,7 +330,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; match *self { IntegerOverflow(_) | IncompatibleHeight(_, _) | IncompatibleTime(_, _) => None, diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs index 9fb09360..489bc716 100644 --- a/bitcoin/src/blockdata/script/mod.rs +++ b/bitcoin/src/blockdata/script/mod.rs @@ -698,13 +698,15 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Error::*; + match *self { - Error::NonMinimalPush => f.write_str("non-minimal datapush"), - Error::EarlyEndOfScript => f.write_str("unexpected end of script"), - Error::NumericOverflow => + NonMinimalPush => f.write_str("non-minimal datapush"), + EarlyEndOfScript => f.write_str("unexpected end of script"), + NumericOverflow => f.write_str("numeric overflow (number on stack larger than 4 bytes)"), - Error::UnknownSpentOutput(ref point) => write!(f, "unknown spent output: {}", point), - Error::Serialization => + UnknownSpentOutput(ref point) => write!(f, "unknown spent output: {}", point), + Serialization => f.write_str("can not serialize the spending transaction in Transaction::verify()"), } } @@ -713,7 +715,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; match *self { NonMinimalPush diff --git a/bitcoin/src/blockdata/script/push_bytes.rs b/bitcoin/src/blockdata/script/push_bytes.rs index c1c184a2..07cd6f28 100644 --- a/bitcoin/src/blockdata/script/push_bytes.rs +++ b/bitcoin/src/blockdata/script/push_bytes.rs @@ -413,4 +413,7 @@ mod error { } } -crate::error::impl_std_error!(PushBytesError); +#[cfg(feature = "std")] +impl std::error::Error for PushBytesError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs index 446e44c5..d030f64c 100644 --- a/bitcoin/src/blockdata/script/witness_program.rs +++ b/bitcoin/src/blockdata/script/witness_program.rs @@ -66,7 +66,7 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Error::*; + use Error::*; match *self { InvalidLength(len) => @@ -80,9 +80,9 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; - match self { + match *self { InvalidLength(_) | InvalidSegwitV0Length(_) => None, } } diff --git a/bitcoin/src/blockdata/script/witness_version.rs b/bitcoin/src/blockdata/script/witness_version.rs index 9dbb449e..cf933432 100644 --- a/bitcoin/src/blockdata/script/witness_version.rs +++ b/bitcoin/src/blockdata/script/witness_version.rs @@ -168,6 +168,7 @@ impl From for Opcode { /// Error parsing [`WitnessVersion`] from a string. #[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] pub enum FromStrError { /// Unable to parse integer from string. Unparsable(ParseIntError), @@ -204,6 +205,7 @@ impl From for FromStrError { /// Error attempting to create a [`WitnessVersion`] from an [`Instruction`] #[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] pub enum TryFromInstructionError { /// Cannot not convert OP to a witness version. TryFrom(TryFromError), @@ -240,6 +242,7 @@ impl From for TryFromInstructionError { /// Error attempting to create a [`WitnessVersion`] from an integer. #[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] pub struct TryFromError { /// The invalid non-witness version integer. pub invalid: u8, diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 27db0e61..08a926db 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -116,13 +116,14 @@ pub enum ParseOutPointError { impl fmt::Display for ParseOutPointError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ParseOutPointError::*; + match *self { - ParseOutPointError::Txid(ref e) => write_err!(f, "error parsing TXID"; e), - ParseOutPointError::Vout(ref e) => write_err!(f, "error parsing vout"; e), - ParseOutPointError::Format => write!(f, "OutPoint not in : format"), - ParseOutPointError::TooLong => write!(f, "vout should be at most 10 digits"), - ParseOutPointError::VoutNotCanonical => - write!(f, "no leading zeroes or + allowed in vout part"), + Txid(ref e) => write_err!(f, "error parsing TXID"; e), + Vout(ref e) => write_err!(f, "error parsing vout"; e), + Format => write!(f, "OutPoint not in : format"), + TooLong => write!(f, "vout should be at most 10 digits"), + VoutNotCanonical => write!(f, "no leading zeroes or + allowed in vout part"), } } } @@ -130,7 +131,7 @@ impl fmt::Display for ParseOutPointError { #[cfg(feature = "std")] impl std::error::Error for ParseOutPointError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::ParseOutPointError::*; + use ParseOutPointError::*; match self { Txid(e) => Some(e), diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs index 798cff30..a5c6a1db 100644 --- a/bitcoin/src/consensus/encode.rs +++ b/bitcoin/src/consensus/encode.rs @@ -63,15 +63,17 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Error::*; + match *self { - Error::Io(ref e) => write_err!(f, "IO error"; e), - Error::OversizedVectorAllocation { requested: ref r, max: ref m } => + Io(ref e) => write_err!(f, "IO error"; e), + OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m), - Error::InvalidChecksum { expected: ref e, actual: ref a } => + InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "invalid checksum: expected {:x}, actual {:x}", e.as_hex(), a.as_hex()), - Error::NonMinimalVarInt => write!(f, "non-minimal varint"), - Error::ParseFailed(ref s) => write!(f, "parse failed: {}", s), - Error::UnsupportedSegwitFlag(ref swflag) => + NonMinimalVarInt => write!(f, "non-minimal varint"), + ParseFailed(ref s) => write!(f, "parse failed: {}", s), + UnsupportedSegwitFlag(ref swflag) => write!(f, "unsupported segwit version: {}", swflag), } } @@ -80,7 +82,7 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; match self { Io(e) => Some(e), diff --git a/bitcoin/src/consensus/validation.rs b/bitcoin/src/consensus/validation.rs index 7667cc9d..988e1837 100644 --- a/bitcoin/src/consensus/validation.rs +++ b/bitcoin/src/consensus/validation.rs @@ -179,6 +179,7 @@ impl Transaction { // 2. We want to implement `std::error::Error` if the "std" feature is enabled in `rust-bitcoin` but // not in `bitcoinconsensus`. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct BitcoinconsensusError(bitcoinconsensus::Error); impl fmt::Display for BitcoinconsensusError { @@ -203,6 +204,7 @@ impl From for BitcoinconsensusError { /// An error during transaction validation. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum TxVerifyError { /// Error validating the script with bitcoinconsensus library. ScriptVerification(BitcoinconsensusError), diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs index c93fa33f..e982e522 100644 --- a/bitcoin/src/crypto/ecdsa.rs +++ b/bitcoin/src/crypto/ecdsa.rs @@ -212,12 +212,12 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; - match self { - Hex(e) => Some(e), - Secp256k1(e) => Some(e), - SighashType(e) => Some(e), + match *self { + Hex(ref e) => Some(e), + Secp256k1(ref e) => Some(e), + SighashType(ref e) => Some(e), EmptySignature => None, } } diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index 557ca32c..32b30f64 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -720,12 +720,12 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; - match self { - Base58(e) => Some(e), - Secp256k1(e) => Some(e), - Hex(e) => Some(e), + match *self { + Base58(ref e) => Some(e), + Secp256k1(ref e) => Some(e), + Hex(ref e) => Some(e), InvalidKeyPrefix(_) | InvalidHexLength(_) => None, } } diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index 64384b4c..d6593119 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -18,7 +18,6 @@ use hashes::{hash_newtype, sha256, sha256d, sha256t_hash_newtype, Hash}; use crate::blockdata::witness::Witness; use crate::consensus::{encode, Encodable}; -use crate::error::impl_std_error; use crate::prelude::*; use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX}; use crate::{io, Amount, Script, ScriptBuf, Sequence, Transaction, TxIn, TxOut}; @@ -248,7 +247,7 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use Error::*; - match self { + match *self { Io(error_kind) => write!(f, "writer errored: {:?}", error_kind), IndexOutOfInputsBounds { index, inputs_size } => write!(f, "requested index ({}) is greater or equal than the number of transaction inputs ({})", index, inputs_size), SingleWithoutCorrespondingOutput { index, outputs_size } => write!(f, "SIGHASH_SINGLE for input ({}) haven't a corresponding output (#outputs:{})", index, outputs_size), @@ -267,7 +266,7 @@ impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { use Error::*; - match self { + match *self { Io(_) | IndexOutOfInputsBounds { .. } | SingleWithoutCorrespondingOutput { .. } @@ -524,7 +523,8 @@ impl TapSighashType { } /// Integer is not a consensus valid sighash type. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct InvalidSighashTypeError(pub u32); impl fmt::Display for InvalidSighashTypeError { @@ -533,11 +533,15 @@ impl fmt::Display for InvalidSighashTypeError { } } -impl_std_error!(InvalidSighashTypeError); +#[cfg(feature = "std")] +impl std::error::Error for InvalidSighashTypeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} /// This type is consensus valid but an input including it would prevent the transaction from /// being relayed on today's Bitcoin network. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct NonStandardSighashTypeError(pub u32); impl fmt::Display for NonStandardSighashTypeError { @@ -546,12 +550,16 @@ impl fmt::Display for NonStandardSighashTypeError { } } -impl_std_error!(NonStandardSighashTypeError); +#[cfg(feature = "std")] +impl std::error::Error for NonStandardSighashTypeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} /// Error returned for failure during parsing one of the sighash types. /// /// This is currently returned for unrecognized sighash strings. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct SighashTypeParseError { /// The unrecognized string we attempted to parse. pub unrecognized: String, @@ -563,7 +571,10 @@ impl fmt::Display for SighashTypeParseError { } } -impl_std_error!(SighashTypeParseError); +#[cfg(feature = "std")] +impl std::error::Error for SighashTypeParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} impl> SighashCache { /// Constructs a new `SighashCache` from an unsigned transaction. diff --git a/bitcoin/src/crypto/taproot.rs b/bitcoin/src/crypto/taproot.rs index 360b0e62..737a8bf6 100644 --- a/bitcoin/src/crypto/taproot.rs +++ b/bitcoin/src/crypto/taproot.rs @@ -87,9 +87,9 @@ impl std::error::Error for SigFromSliceError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { use SigFromSliceError::*; - match self { - Secp256k1(e) => Some(e), - SighashType(e) => Some(e), + match *self { + Secp256k1(ref e) => Some(e), + SighashType(ref e) => Some(e), InvalidSignatureSize(_) => None, } } diff --git a/bitcoin/src/error.rs b/bitcoin/src/error.rs index ab296628..f5ea45c3 100644 --- a/bitcoin/src/error.rs +++ b/bitcoin/src/error.rs @@ -2,6 +2,4 @@ //! Contains error types and other error handling tools. -pub(crate) use internals::impl_std_error; - pub use crate::parse::ParseIntError; diff --git a/bitcoin/src/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs index d39fa074..25aa7262 100644 --- a/bitcoin/src/merkle_tree/block.rs +++ b/bitcoin/src/merkle_tree/block.rs @@ -501,7 +501,7 @@ pub enum MerkleBlockError { impl fmt::Display for MerkleBlockError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::MerkleBlockError::*; + use MerkleBlockError::*; match *self { MerkleRootMismatch => write!(f, "merkle header root doesn't match to the root calculated from the partial merkle tree"), @@ -521,7 +521,7 @@ impl fmt::Display for MerkleBlockError { #[cfg(feature = "std")] impl std::error::Error for MerkleBlockError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::MerkleBlockError::*; + use MerkleBlockError::*; match *self { MerkleRootMismatch | NoTransactions | TooManyTransactions | TooManyHashes diff --git a/bitcoin/src/network.rs b/bitcoin/src/network.rs index 9e128d4e..cd3d3042 100644 --- a/bitcoin/src/network.rs +++ b/bitcoin/src/network.rs @@ -28,7 +28,6 @@ use internals::write_err; use serde::{Deserialize, Serialize}; use crate::constants::ChainHash; -use crate::error::impl_std_error; use crate::p2p::Magic; use crate::prelude::{String, ToOwned}; @@ -195,6 +194,7 @@ pub mod as_core_arg { /// An error in parsing network string. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct ParseNetworkError(String); impl fmt::Display for ParseNetworkError { @@ -202,7 +202,11 @@ impl fmt::Display for ParseNetworkError { write_err!(f, "failed to parse {} as network", self.0; self) } } -impl_std_error!(ParseNetworkError); + +#[cfg(feature = "std")] +impl std::error::Error for ParseNetworkError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} impl FromStr for Network { type Err = ParseNetworkError; @@ -238,18 +242,22 @@ impl fmt::Display for Network { /// Error in parsing network from chain hash. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct UnknownChainHash(ChainHash); +#[non_exhaustive] +pub struct UnknownChainHashError(ChainHash); -impl Display for UnknownChainHash { +impl Display for UnknownChainHashError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "unknown chain hash: {}", self.0) } } -impl_std_error!(UnknownChainHash); +#[cfg(feature = "std")] +impl std::error::Error for UnknownChainHashError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} impl TryFrom for Network { - type Error = UnknownChainHash; + type Error = UnknownChainHashError; fn try_from(chain_hash: ChainHash) -> Result { match chain_hash { @@ -258,7 +266,7 @@ impl TryFrom for Network { ChainHash::TESTNET => Ok(Network::Testnet), ChainHash::SIGNET => Ok(Network::Signet), ChainHash::REGTEST => Ok(Network::Regtest), - _ => Err(UnknownChainHash(chain_hash)), + _ => Err(UnknownChainHashError(chain_hash)), } } } diff --git a/bitcoin/src/p2p/message.rs b/bitcoin/src/p2p/message.rs index 8b76e80e..7914dfb8 100644 --- a/bitcoin/src/p2p/message.rs +++ b/bitcoin/src/p2p/message.rs @@ -129,6 +129,7 @@ impl Decodable for CommandString { /// /// This is currently returned for command strings longer than 12. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct CommandStringError { cow: Cow<'static, str>, } @@ -144,7 +145,10 @@ impl fmt::Display for CommandStringError { } } -crate::error::impl_std_error!(CommandStringError); +#[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/bitcoin/src/p2p/mod.rs b/bitcoin/src/p2p/mod.rs index f4b7698c..c7f67570 100644 --- a/bitcoin/src/p2p/mod.rs +++ b/bitcoin/src/p2p/mod.rs @@ -30,7 +30,6 @@ use hex::FromHex; use internals::{debug_from_display, write_err}; use crate::consensus::encode::{self, Decodable, Encodable}; -use crate::error::impl_std_error; use crate::prelude::{Borrow, BorrowMut, String, ToOwned}; use crate::{io, Network}; @@ -221,15 +220,6 @@ impl Magic { pub fn to_bytes(self) -> [u8; 4] { self.0 } } -/// An error in parsing magic bytes. -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct ParseMagicError { - /// The error that occurred when parsing the string. - error: hex::HexToArrayError, - /// The byte string that failed to parse. - magic: String, -} - impl FromStr for Magic { type Err = ParseMagicError; @@ -253,12 +243,8 @@ impl From for Magic { } } -/// Error in creating a Network from Magic bytes. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct UnknownMagic(Magic); - impl TryFrom for Network { - type Error = UnknownMagic; + type Error = UnknownMagicError; fn try_from(magic: Magic) -> Result { match magic { @@ -267,7 +253,7 @@ impl TryFrom for Network { Magic::TESTNET => Ok(Network::Testnet), Magic::SIGNET => Ok(Network::Signet), Magic::REGTEST => Ok(Network::Regtest), - _ => Err(UnknownMagic(magic)), + _ => Err(UnknownMagicError(magic)), } } } @@ -338,19 +324,42 @@ impl BorrowMut<[u8; 4]> for Magic { fn borrow_mut(&mut self) -> &mut [u8; 4] { &mut self.0 } } +/// An error in parsing magic bytes. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct ParseMagicError { + /// The error that occurred when parsing the string. + error: hex::HexToArrayError, + /// The byte string that failed to parse. + magic: String, +} + impl fmt::Display for ParseMagicError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write_err!(f, "failed to parse {} as network magic", self.magic; self.error) } } -impl_std_error!(ParseMagicError, error); -impl fmt::Display for UnknownMagic { +#[cfg(feature = "std")] +impl std::error::Error for ParseMagicError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.error) } +} + +/// Error in creating a Network from Magic bytes. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct UnknownMagicError(Magic); + +impl fmt::Display for UnknownMagicError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "unknown network magic {}", self.0) } } -impl_std_error!(UnknownMagic); + +#[cfg(feature = "std")] +impl std::error::Error for UnknownMagicError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} #[cfg(test)] mod tests { diff --git a/bitcoin/src/parse.rs b/bitcoin/src/parse.rs index 3e04f5ae..aebc5f8d 100644 --- a/bitcoin/src/parse.rs +++ b/bitcoin/src/parse.rs @@ -6,7 +6,6 @@ use core::str::FromStr; use internals::write_err; -use crate::error::impl_std_error; use crate::prelude::*; /// Error with rich context returned when a string can't be parsed as an integer. @@ -19,6 +18,7 @@ use crate::prelude::*; /// in a performance-critical application you may want to box it or throw away the context by /// converting to `core` type. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct ParseIntError { input: String, // for displaying - see Display impl with nice error message below @@ -35,14 +35,6 @@ impl ParseIntError { pub fn input(&self) -> &str { &self.input } } -impl From for core::num::ParseIntError { - fn from(value: ParseIntError) -> Self { value.source } -} - -impl AsRef for ParseIntError { - fn as_ref(&self) -> &core::num::ParseIntError { &self.source } -} - impl fmt::Display for ParseIntError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let signed = if self.is_signed { "signed" } else { "unsigned" }; @@ -51,6 +43,19 @@ impl fmt::Display for ParseIntError { } } +#[cfg(feature = "std")] +impl std::error::Error for ParseIntError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.source) } +} + +impl From for core::num::ParseIntError { + fn from(value: ParseIntError) -> Self { value.source } +} + +impl AsRef for ParseIntError { + fn as_ref(&self) -> &core::num::ParseIntError { &self.source } +} + /// Not strictly neccessary but serves as a lint - avoids weird behavior if someone accidentally /// passes non-integer to the `parse()` function. pub(crate) trait Integer: @@ -95,8 +100,6 @@ pub(crate) fn hex_u32 + Into>(s: S) -> Result for $to` using `parse::int`, mapping the output using infallible /// conversion function `fn`. macro_rules! impl_tryfrom_str_from_int_infallible { diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index c49bab41..d7079b64 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -705,7 +705,8 @@ impl> From for U256 { } /// Error from `TryFrom` implementations, occurs when input is negative. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct TryFromError(i128); impl fmt::Display for TryFromError { @@ -715,7 +716,9 @@ impl fmt::Display for TryFromError { } #[cfg(feature = "std")] -impl std::error::Error for TryFromError {} +impl std::error::Error for TryFromError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} impl Add for U256 { type Output = Self; diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs index 934b228e..2ded0e26 100644 --- a/bitcoin/src/psbt/error.rs +++ b/bitcoin/src/psbt/error.rs @@ -93,7 +93,7 @@ pub enum Error { /// Parsing error indicating a taproot error Taproot(&'static str), /// Taproot tree deserilaization error - TapTree(crate::taproot::IncompleteBuilder), + TapTree(crate::taproot::IncompleteBuilderError), /// Error related to an xpub key XPubKey(&'static str), /// Error related to PSBT version @@ -106,57 +106,56 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Error::*; + 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 => + InvalidMagic => f.write_str("invalid magic"), + MissingUtxo => f.write_str("UTXO information is not present in PSBT"), + InvalidSeparator => f.write_str("invalid separator"), + 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 => + InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), + InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"), - Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), - Error::UnsignedTxHasScriptSigs => - f.write_str("the unsigned transaction has script sigs"), - Error::UnsignedTxHasScriptWitnesses => + DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), + UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"), + UnsignedTxHasScriptWitnesses => f.write_str("the unsigned transaction has script witnesses"), - Error::MustHaveUnsignedTx => + 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!( + NoMorePairs => f.write_str("no more key-value pairs for this psbt map"), + 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::InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e), - Error::InvalidPreimageHashPair { ref preimage, ref hash, ref hash_type } => { + NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), + InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e), + 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) => { + CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) } - Error::ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e), - Error::NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"), - Error::FeeOverflow => f.write_str("integer overflow in fee calculation"), - Error::InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e), - Error::InvalidSecp256k1PublicKey(ref e) => - write_err!(f, "invalid secp256k1 public key"; e), - Error::InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"), - Error::InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e), - Error::InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e), - Error::InvalidControlBlock => f.write_str("invalid control block"), - Error::InvalidLeafVersion => f.write_str("invalid leaf version"), - Error::Taproot(s) => write!(f, "taproot error - {}", s), - Error::TapTree(ref e) => write_err!(f, "taproot tree error"; e), - Error::XPubKey(s) => write!(f, "xpub key error - {}", s), - Error::Version(s) => write!(f, "version error {}", s), - Error::PartialDataConsumption => + ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e), + NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"), + FeeOverflow => f.write_str("integer overflow in fee calculation"), + InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e), + InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e), + InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"), + InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e), + InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e), + InvalidControlBlock => f.write_str("invalid control block"), + InvalidLeafVersion => f.write_str("invalid leaf version"), + Taproot(s) => write!(f, "taproot error - {}", s), + TapTree(ref e) => write_err!(f, "taproot tree error"; e), + XPubKey(s) => write!(f, "xpub key error - {}", s), + Version(s) => write!(f, "version error {}", s), + PartialDataConsumption => f.write_str("data not consumed entirely when explicitly deserializing"), - Error::Io(ref e) => write_err!(f, "I/O error"; e), + Io(ref e) => write_err!(f, "I/O error"; e), } } } @@ -164,12 +163,12 @@ impl fmt::Display for Error { #[cfg(feature = "std")] impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::Error::*; + use Error::*; - match self { - InvalidHash(e) => Some(e), - ConsensusEncoding(e) => Some(e), - Io(e) => Some(e), + match *self { + InvalidHash(ref e) => Some(e), + ConsensusEncoding(ref e) => Some(e), + Io(ref e) => Some(e), InvalidMagic | MissingUtxo | InvalidSeparator diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index deb9b4f8..2d6a360a 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -796,7 +796,7 @@ pub enum SignError { impl fmt::Display for SignError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use self::SignError::*; + use SignError::*; match *self { IndexOutOfBounds(ref e) => write_err!(f, "index out of bounds"; e), @@ -821,9 +821,11 @@ impl fmt::Display for SignError { #[cfg(feature = "std")] impl std::error::Error for SignError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::SignError::*; + use SignError::*; match *self { + SighashComputation(ref e) => Some(e), + IndexOutOfBounds(ref e) => Some(e), InvalidSighashType | MissingInputUtxo | MissingRedeemScript @@ -836,8 +838,6 @@ impl std::error::Error for SignError { | KeyNotFound | WrongSigningAlgorithm | Unsupported => None, - SighashComputation(ref e) => Some(e), - IndexOutOfBounds(ref e) => Some(e), } } } @@ -850,8 +850,9 @@ impl From for SignError { fn from(e: IndexOutOfBoundsError) -> Self { SignError::IndexOutOfBounds(e) } } -#[derive(Debug, Clone, PartialEq, Eq)] /// This error is returned when extracting a [`Transaction`] from a [`Psbt`]. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum ExtractTxError { /// The [`FeeRate`] is too high AbsurdFeeRate { @@ -874,14 +875,16 @@ pub enum ExtractTxError { impl fmt::Display for ExtractTxError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - ExtractTxError::AbsurdFeeRate { fee_rate, .. } => + use ExtractTxError::*; + + match *self { + AbsurdFeeRate { fee_rate, .. } => write!(f, "An absurdly high fee rate of {}", fee_rate), - ExtractTxError::MissingInputValue { .. } => write!( + MissingInputValue { .. } => write!( f, "One of the inputs lacked value information (witness_utxo or non_witness_utxo)" ), - ExtractTxError::SendingTooMuch { .. } => write!( + SendingTooMuch { .. } => write!( f, "Transaction would be invalid due to output value being greater than input value." ), @@ -890,10 +893,19 @@ impl fmt::Display for ExtractTxError { } #[cfg(feature = "std")] -impl std::error::Error for ExtractTxError {} +impl std::error::Error for ExtractTxError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use ExtractTxError::*; + + match *self { + AbsurdFeeRate { .. } | MissingInputValue { .. } | SendingTooMuch { .. } => None, + } + } +} /// Input index out of bounds (actual index, maximum index allowed). -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum IndexOutOfBoundsError { /// The index is out of bounds for the `psbt.inputs` vector. Inputs { @@ -931,7 +943,15 @@ impl fmt::Display for IndexOutOfBoundsError { } #[cfg(feature = "std")] -impl std::error::Error for IndexOutOfBoundsError {} +impl std::error::Error for IndexOutOfBoundsError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use IndexOutOfBoundsError::*; + + match *self { + Inputs { .. } | TxInput { .. } => None, + } + } +} #[cfg(feature = "base64")] mod display_from_str { diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs index 80cdb7a6..87953ad8 100644 --- a/bitcoin/src/sign_message.rs +++ b/bitcoin/src/sign_message.rs @@ -43,12 +43,13 @@ mod message_signing { impl fmt::Display for MessageSignatureError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use MessageSignatureError::*; + match *self { - MessageSignatureError::InvalidLength => write!(f, "length not 65 bytes"), - MessageSignatureError::InvalidEncoding(ref e) => - write_err!(f, "invalid encoding"; e), - MessageSignatureError::InvalidBase64 => write!(f, "invalid base64"), - MessageSignatureError::UnsupportedAddressType(ref address_type) => + InvalidLength => write!(f, "length not 65 bytes"), + InvalidEncoding(ref e) => write_err!(f, "invalid encoding"; e), + InvalidBase64 => write!(f, "invalid base64"), + UnsupportedAddressType(ref address_type) => write!(f, "unsupported address type: {}", address_type), } } @@ -57,10 +58,10 @@ mod message_signing { #[cfg(feature = "std")] impl std::error::Error for MessageSignatureError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::MessageSignatureError::*; + use MessageSignatureError::*; - match self { - InvalidEncoding(e) => Some(e), + match *self { + InvalidEncoding(ref e) => Some(e), InvalidLength | InvalidBase64 | UnsupportedAddressType(_) => None, } } diff --git a/bitcoin/src/string.rs b/bitcoin/src/string.rs index fd28e7c3..efe6ea30 100644 --- a/bitcoin/src/string.rs +++ b/bitcoin/src/string.rs @@ -36,6 +36,7 @@ pub trait FromHexStr: Sized { /// Hex parsing error #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub enum FromHexError { /// The input was not a valid hex string, contains the error that occurred while parsing. ParseHex(E), @@ -49,7 +50,7 @@ impl From for FromHexError { impl fmt::Display for FromHexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::FromHexError::*; + use FromHexError::*; match *self { ParseHex(ref e) => write_err!(f, "failed to parse hex string"; e), @@ -65,7 +66,7 @@ where E: std::error::Error + 'static, { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::FromHexError::*; + use FromHexError::*; match *self { ParseHex(ref e) => Some(e), diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs index 9c5a1e1a..477587fa 100644 --- a/bitcoin/src/taproot.rs +++ b/bitcoin/src/taproot.rs @@ -468,11 +468,11 @@ impl TaprootBuilder { /// /// # Errors: /// - /// [`IncompleteBuilder::NotFinalized`] if the builder is not finalized. The builder - /// can be restored by calling [`IncompleteBuilder::into_builder`] - pub fn try_into_node_info(mut self) -> Result { + /// [`IncompleteBuilderError::NotFinalized`] if the builder is not finalized. The builder + /// can be restored by calling [`IncompleteBuilderError::into_builder`] + pub fn try_into_node_info(mut self) -> Result { if self.branch().len() != 1 { - return Err(IncompleteBuilder::NotFinalized(self)); + return Err(IncompleteBuilderError::NotFinalized(self)); } Ok(self .branch @@ -483,11 +483,11 @@ impl TaprootBuilder { /// Converts the builder into a [`TapTree`] if the builder is a full tree and /// does not contain any hidden nodes - pub fn try_into_taptree(self) -> Result { + pub fn try_into_taptree(self) -> Result { let node = self.try_into_node_info()?; if node.has_hidden_nodes { // Reconstruct the builder as it was if it has hidden nodes - return Err(IncompleteBuilder::HiddenParts(TaprootBuilder { + return Err(IncompleteBuilderError::HiddenParts(TaprootBuilder { branch: vec![Some(node)], })); } @@ -574,42 +574,45 @@ impl Default for TaprootBuilder { /// Error happening when [`TapTree`] is constructed from a [`TaprootBuilder`] /// having hidden branches or not being finalized. -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] -pub enum IncompleteBuilder { +pub enum IncompleteBuilderError { /// Indicates an attempt to construct a tap tree from a builder containing incomplete branches. NotFinalized(TaprootBuilder), /// Indicates an attempt to construct a tap tree from a builder containing hidden parts. HiddenParts(TaprootBuilder), } -impl IncompleteBuilder { +impl IncompleteBuilderError { /// Converts error into the original incomplete [`TaprootBuilder`] instance. pub fn into_builder(self) -> TaprootBuilder { + use IncompleteBuilderError::*; + match self { - IncompleteBuilder::NotFinalized(builder) | IncompleteBuilder::HiddenParts(builder) => - builder, + NotFinalized(builder) | HiddenParts(builder) => builder, } } } -impl core::fmt::Display for IncompleteBuilder { +impl core::fmt::Display for IncompleteBuilderError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + use IncompleteBuilderError::*; + f.write_str(match self { - IncompleteBuilder::NotFinalized(_) => + NotFinalized(_) => "an attempt to construct a tap tree from a builder containing incomplete branches.", - IncompleteBuilder::HiddenParts(_) => + HiddenParts(_) => "an attempt to construct a tap tree from a builder containing hidden parts.", }) } } #[cfg(feature = "std")] -impl std::error::Error for IncompleteBuilder { +impl std::error::Error for IncompleteBuilderError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::IncompleteBuilder::*; + use IncompleteBuilderError::*; - match self { + match *self { NotFinalized(_) | HiddenParts(_) => None, } } @@ -617,35 +620,39 @@ impl std::error::Error for IncompleteBuilder { /// Error happening when [`TapTree`] is constructed from a [`NodeInfo`] /// having hidden branches. -#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +#[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] -pub enum HiddenNodes { +pub enum HiddenNodesError { /// Indicates an attempt to construct a tap tree from a builder containing hidden parts. HiddenParts(NodeInfo), } -impl HiddenNodes { +impl HiddenNodesError { /// Converts error into the original incomplete [`NodeInfo`] instance. pub fn into_node_info(self) -> NodeInfo { + use HiddenNodesError::*; + match self { - HiddenNodes::HiddenParts(node_info) => node_info, + HiddenParts(node_info) => node_info, } } } -impl core::fmt::Display for HiddenNodes { +impl core::fmt::Display for HiddenNodesError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + use HiddenNodesError::*; + f.write_str(match self { - HiddenNodes::HiddenParts(_) => + HiddenParts(_) => "an attempt to construct a tap tree from a node_info containing hidden parts.", }) } } #[cfg(feature = "std")] -impl std::error::Error for HiddenNodes { +impl std::error::Error for HiddenNodesError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::HiddenNodes::*; + use HiddenNodesError::*; match self { HiddenParts(_) => None, @@ -685,29 +692,29 @@ impl TapTree { } impl TryFrom for TapTree { - type Error = IncompleteBuilder; + type Error = IncompleteBuilderError; /// Constructs [`TapTree`] from a [`TaprootBuilder`] if it is complete binary tree. /// /// # Returns /// - /// A [`TapTree`] iff the `builder` is complete, otherwise return [`IncompleteBuilder`] + /// A [`TapTree`] iff the `builder` is complete, otherwise return [`IncompleteBuilderError`] /// error with the content of incomplete `builder` instance. fn try_from(builder: TaprootBuilder) -> Result { builder.try_into_taptree() } } impl TryFrom for TapTree { - type Error = HiddenNodes; + type Error = HiddenNodesError; /// Constructs [`TapTree`] from a [`NodeInfo`] if it is complete binary tree. /// /// # Returns /// - /// A [`TapTree`] iff the [`NodeInfo`] has no hidden nodes, otherwise return [`HiddenNodes`] - /// error with the content of incomplete [`NodeInfo`] instance. + /// A [`TapTree`] iff the [`NodeInfo`] has no hidden nodes, otherwise return + /// [`HiddenNodesError`] error with the content of incomplete [`NodeInfo`] instance. fn try_from(node_info: NodeInfo) -> Result { if node_info.has_hidden_nodes { - Err(HiddenNodes::HiddenParts(node_info)) + Err(HiddenNodesError::HiddenParts(node_info)) } else { Ok(TapTree(node_info)) } @@ -834,7 +841,7 @@ impl NodeInfo { } impl TryFrom for NodeInfo { - type Error = IncompleteBuilder; + type Error = IncompleteBuilderError; fn try_from(builder: TaprootBuilder) -> Result { builder.try_into_node_info() @@ -1444,26 +1451,28 @@ pub enum TaprootBuilderError { impl fmt::Display for TaprootBuilderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use TaprootBuilderError::*; + match *self { - TaprootBuilderError::InvalidMerkleTreeDepth(d) => { + InvalidMerkleTreeDepth(d) => { write!( f, "Merkle Tree depth({}) must be less than {}", d, TAPROOT_CONTROL_MAX_NODE_COUNT ) } - TaprootBuilderError::NodeNotInDfsOrder => { + NodeNotInDfsOrder => { write!(f, "add_leaf/add_hidden must be called in DFS walk order",) } - TaprootBuilderError::OverCompleteTree => write!( + OverCompleteTree => write!( f, "Attempted to create a tree with two nodes at depth 0. There must\ only be a exactly one node at depth 0", ), - TaprootBuilderError::InvalidInternalKey(ref e) => { + InvalidInternalKey(ref e) => { write_err!(f, "invalid internal x-only key"; e) } - TaprootBuilderError::EmptyTree => { + EmptyTree => { write!(f, "Called finalize on an empty tree") } } @@ -1473,7 +1482,7 @@ impl fmt::Display for TaprootBuilderError { #[cfg(feature = "std")] impl std::error::Error for TaprootBuilderError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::TaprootBuilderError::*; + use TaprootBuilderError::*; match self { InvalidInternalKey(e) => Some(e), @@ -1504,30 +1513,32 @@ pub enum TaprootError { impl fmt::Display for TaprootError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use TaprootError::*; + match *self { - TaprootError::InvalidMerkleBranchSize(sz) => write!( + InvalidMerkleBranchSize(sz) => write!( f, "Merkle branch size({}) must be a multiple of {}", sz, TAPROOT_CONTROL_NODE_SIZE ), - TaprootError::InvalidMerkleTreeDepth(d) => write!( + InvalidMerkleTreeDepth(d) => write!( f, "Merkle Tree depth({}) must be less than {}", d, TAPROOT_CONTROL_MAX_NODE_COUNT ), - TaprootError::InvalidTaprootLeafVersion(v) => { + InvalidTaprootLeafVersion(v) => { write!(f, "Leaf version({}) must have the least significant bit 0", v) } - TaprootError::InvalidControlBlockSize(sz) => write!( + InvalidControlBlockSize(sz) => write!( f, "Control Block size({}) must be of the form 33 + 32*m where 0 <= m <= {} ", sz, TAPROOT_CONTROL_MAX_NODE_COUNT ), - TaprootError::InvalidInternalKey(ref e) => { + InvalidInternalKey(ref e) => { write_err!(f, "invalid internal x-only key"; e) } - TaprootError::InvalidParity(_) => write!(f, "invalid parity value for internal key"), - TaprootError::EmptyTree => write!(f, "Taproot Tree must contain at least one script"), + InvalidParity(_) => write!(f, "invalid parity value for internal key"), + EmptyTree => write!(f, "Taproot Tree must contain at least one script"), } } } @@ -1535,7 +1546,7 @@ impl fmt::Display for TaprootError { #[cfg(feature = "std")] impl std::error::Error for TaprootError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::TaprootError::*; + use TaprootError::*; match self { InvalidInternalKey(e) => Some(e), diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs index fa92397a..667d2df9 100644 --- a/hashes/src/lib.rs +++ b/hashes/src/lib.rs @@ -225,7 +225,8 @@ pub trait Hash: } /// Attempted to create a hash from an invalid length slice. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct FromSliceError { expected: usize, got: usize, diff --git a/internals/src/error.rs b/internals/src/error.rs index 31580fc7..6731ae13 100644 --- a/internals/src/error.rs +++ b/internals/src/error.rs @@ -31,21 +31,3 @@ macro_rules! write_err { } } } - -/// Impls std::error::Error for the specified type with appropriate attributes, possibly returning -/// source. -#[macro_export] -macro_rules! impl_std_error { - // No source available - ($type:ty) => { - #[cfg(feature = "std")] - impl std::error::Error for $type {} - }; - // Struct with $field as source - ($type:ty, $field:ident) => { - #[cfg(feature = "std")] - impl std::error::Error for $type { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.$field) } - } - }; -} diff --git a/internals/src/error/parse_error.rs b/internals/src/error/parse_error.rs index 15552fbd..7bcf8ceb 100644 --- a/internals/src/error/parse_error.rs +++ b/internals/src/error/parse_error.rs @@ -40,6 +40,9 @@ macro_rules! parse_error_type { } } - $crate::error::impl_std_error!($name, source); + #[cfg(feature = "std")] + impl std::error::Error for $name { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.source) } + } } }