From 39314ad52f65039ec29fd8ad3a1b482cdeeaebe4 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 12:11:07 +1100 Subject: [PATCH 1/9] Move error code to match conventional layout We typically layout error code as: definition, [impl block], `Display` impl, `error::Error` impl, from imlps. Code move only, no other changes. --- bitcoin/src/parse.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/bitcoin/src/parse.rs b/bitcoin/src/parse.rs index 3e04f5ae..8d5a9813 100644 --- a/bitcoin/src/parse.rs +++ b/bitcoin/src/parse.rs @@ -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,16 @@ impl fmt::Display for ParseIntError { } } +impl_std_error!(ParseIntError, 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 +97,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 { From 2fb71dd9436eb77c375af2f014a318d932108632 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 12:24:51 +1100 Subject: [PATCH 2/9] Move p2p error types to bottom of file Move the p2p error types to the bottom of the file next to the various impls for these types. Code move only, no other changes. --- bitcoin/src/p2p/mod.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/bitcoin/src/p2p/mod.rs b/bitcoin/src/p2p/mod.rs index f4b7698c..f758c2ce 100644 --- a/bitcoin/src/p2p/mod.rs +++ b/bitcoin/src/p2p/mod.rs @@ -221,15 +221,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,10 +244,6 @@ 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; @@ -338,6 +325,15 @@ 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, 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 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) @@ -345,6 +341,10 @@ impl fmt::Display for ParseMagicError { } impl_std_error!(ParseMagicError, error); +/// Error in creating a Network from Magic bytes. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct UnknownMagic(Magic); + impl fmt::Display for UnknownMagic { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "unknown network magic {}", self.0) From 5658dac02484e28e9455c45b454e054422b7e135 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 12:21:10 +1100 Subject: [PATCH 3/9] Add suffix to UnknownChainHash error type By convention we always include the suffix "Error" on our error types. Rename the error type `UnknownChainHash` to `UnknownChainHashError`. --- bitcoin/src/network.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bitcoin/src/network.rs b/bitcoin/src/network.rs index 9e128d4e..895a4d93 100644 --- a/bitcoin/src/network.rs +++ b/bitcoin/src/network.rs @@ -238,18 +238,18 @@ impl fmt::Display for Network { /// Error in parsing network from chain hash. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct UnknownChainHash(ChainHash); +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); +impl_std_error!(UnknownChainHashError); impl TryFrom for Network { - type Error = UnknownChainHash; + type Error = UnknownChainHashError; fn try_from(chain_hash: ChainHash) -> Result { match chain_hash { @@ -258,7 +258,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)), } } } From f41416a0ea8cbd3f3bdd00586546e2008c048974 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 12:29:05 +1100 Subject: [PATCH 4/9] Add suffix to UnknownMagic error type By convention we always include the suffix "Error" on our error types. Rename the error type `UnknownMagic` to `UnknownMagicError`. --- bitcoin/src/p2p/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bitcoin/src/p2p/mod.rs b/bitcoin/src/p2p/mod.rs index f758c2ce..861506c8 100644 --- a/bitcoin/src/p2p/mod.rs +++ b/bitcoin/src/p2p/mod.rs @@ -245,7 +245,7 @@ impl From for Magic { } impl TryFrom for Network { - type Error = UnknownMagic; + type Error = UnknownMagicError; fn try_from(magic: Magic) -> Result { match magic { @@ -254,7 +254,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)), } } } @@ -343,14 +343,14 @@ impl_std_error!(ParseMagicError, error); /// Error in creating a Network from Magic bytes. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct UnknownMagic(Magic); +pub struct UnknownMagicError(Magic); -impl fmt::Display for UnknownMagic { +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); +impl_std_error!(UnknownMagicError); #[cfg(test)] mod tests { From 2b40ea24fb90153bc7e89d9149d45c9a678d58bb Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 13:44:07 +1100 Subject: [PATCH 5/9] Add suffix to IncompleteBuilder error type By convention we always include the suffix "Error" on our error types. Rename the error type `IncompleteBuilder` to `IncompleteBuilderError`. --- bitcoin/src/psbt/error.rs | 2 +- bitcoin/src/taproot.rs | 41 +++++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs index 934b228e..f490700a 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 diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs index 9c5a1e1a..a70bdc70 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)], })); } @@ -576,40 +576,43 @@ impl Default for TaprootBuilder { /// having hidden branches or not being finalized. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] #[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, } } @@ -685,13 +688,13 @@ 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() } } @@ -834,7 +837,7 @@ impl NodeInfo { } impl TryFrom for NodeInfo { - type Error = IncompleteBuilder; + type Error = IncompleteBuilderError; fn try_from(builder: TaprootBuilder) -> Result { builder.try_into_node_info() From 6933ca4fc227256a622ffcebc20d17bd248baba6 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 13:48:24 +1100 Subject: [PATCH 6/9] Add suffix to HiddenNodes error type By convention we always include the suffix "Error" on our error types. Rename the error type `HiddenNodes` to `HiddenNodesError`. --- bitcoin/src/taproot.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/bitcoin/src/taproot.rs b/bitcoin/src/taproot.rs index a70bdc70..40ba5aa3 100644 --- a/bitcoin/src/taproot.rs +++ b/bitcoin/src/taproot.rs @@ -622,33 +622,33 @@ impl std::error::Error for IncompleteBuilderError { /// having hidden branches. #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] #[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 { match self { - HiddenNodes::HiddenParts(node_info) => node_info, + HiddenNodesError::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 { f.write_str(match self { - HiddenNodes::HiddenParts(_) => + HiddenNodesError::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 self::HiddenNodesError::*; match self { HiddenParts(_) => None, @@ -700,17 +700,17 @@ impl TryFrom for 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)) } From 2512dbafc298c713d3c799f7c1d60c6f24d66c85 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 12:35:01 +1100 Subject: [PATCH 7/9] Remove impl_std_error macro We would like the codebase to be optimized for readability not ease of development, as such code that is write-once-read-many should not use macros. Currently we use the `impl_std_error` macro to implement `std::error::Error` for struct error types. This makes the code harder to read at a glance because one has to think what the macro does. Remove the `impl_std_error` macro and write the code explicitly. --- bitcoin/src/address/error.rs | 6 ++++-- bitcoin/src/blockdata/script/push_bytes.rs | 5 ++++- bitcoin/src/crypto/sighash.rs | 16 ++++++++++++---- bitcoin/src/error.rs | 2 -- bitcoin/src/network.rs | 12 +++++++++--- bitcoin/src/p2p/message.rs | 5 ++++- bitcoin/src/p2p/mod.rs | 13 ++++++++++--- bitcoin/src/parse.rs | 6 ++++-- internals/src/error.rs | 18 ------------------ internals/src/error/parse_error.rs | 5 ++++- 10 files changed, 51 insertions(+), 37 deletions(-) diff --git a/bitcoin/src/address/error.rs b/bitcoin/src/address/error.rs index 9c5fd46c..43d11a73 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}; @@ -91,7 +90,10 @@ 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)] 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/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index 64384b4c..0e73c808 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}; @@ -533,7 +532,10 @@ 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. @@ -546,7 +548,10 @@ 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. /// @@ -563,7 +568,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/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/network.rs b/bitcoin/src/network.rs index 895a4d93..67807e96 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}; @@ -202,7 +201,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; @@ -246,7 +249,10 @@ impl Display for UnknownChainHashError { } } -impl_std_error!(UnknownChainHashError); +#[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 = UnknownChainHashError; diff --git a/bitcoin/src/p2p/message.rs b/bitcoin/src/p2p/message.rs index 8b76e80e..ee0c64b2 100644 --- a/bitcoin/src/p2p/message.rs +++ b/bitcoin/src/p2p/message.rs @@ -144,7 +144,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 861506c8..0e32c620 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}; @@ -339,7 +338,11 @@ impl fmt::Display for ParseMagicError { write_err!(f, "failed to parse {} as network magic", self.magic; self.error) } } -impl_std_error!(ParseMagicError, error); + +#[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)] @@ -350,7 +353,11 @@ impl fmt::Display for UnknownMagicError { write!(f, "unknown network magic {}", self.0) } } -impl_std_error!(UnknownMagicError); + +#[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 8d5a9813..1826c5c3 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. @@ -43,7 +42,10 @@ impl fmt::Display for ParseIntError { } } -impl_std_error!(ParseIntError, source); +#[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 } 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) } + } } } From 43d3306822737195edb7079ae42245c25a1dddd4 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 13:01:43 +1100 Subject: [PATCH 8/9] Use explicit error::Error impl instead of the default In a further effort to make the code brain-dead easy to read; use an explicit implementation of `std::error::Error` that returns `None` instead of relying on the default trait implementation. --- bitcoin/src/bip152.rs | 4 +++- bitcoin/src/blockdata/locktime/absolute.rs | 8 ++++++-- bitcoin/src/pow.rs | 4 +++- bitcoin/src/psbt/mod.rs | 8 ++++++-- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index a74a83d4..539b46b1 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -329,7 +329,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/blockdata/locktime/absolute.rs b/bitcoin/src/blockdata/locktime/absolute.rs index b3b7ddd1..2a565932 100644 --- a/bitcoin/src/blockdata/locktime/absolute.rs +++ b/bitcoin/src/blockdata/locktime/absolute.rs @@ -637,7 +637,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)] @@ -679,7 +681,9 @@ 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)> { None } +} #[cfg(test)] mod tests { diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index e49348c5..bb28427c 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -717,7 +717,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/mod.rs b/bitcoin/src/psbt/mod.rs index deb9b4f8..a1b1e103 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -890,7 +890,9 @@ 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)> { None } +} /// Input index out of bounds (actual index, maximum index allowed). #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -931,7 +933,9 @@ 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)> { None } +} #[cfg(feature = "base64")] mod display_from_str { From 10374af75c06f3fb0376e44f325a976fae97dccc Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 4 Oct 2023 13:55:45 +1100 Subject: [PATCH 9/9] Make error types uniform On our way to v1.0.0 we are defining a standard for our error types, this includes: - Uses the following derives (unless not possible, usually because of `io::Error`) `#[derive(Debug, Clone, PartialEq, Eq)]` - Has `non_exhaustive` unless we really know we can commit to not adding anything. Furthermore, we are trying to make the codebase easy to read. Error code is write-once-read-many (well it should be) so if we make all the error code super uniform the users can flick to an error and quickly see what it includes. In an effort to achieve this I have made up a style and over recent times have change much of the error code to that new style, this PR audits _all_ error types in the code base and enforces the style, specifically: - Is layed out: definition, [impl block], Display impl, error::Error impl, From impls - `error::Error` impl matches on enum even if it returns `None` for all variants - Display/Error impls import enum variants locally - match uses *self and `ref e` - error::Error variants that return `Some` come first, `None` after Re: non_exhaustive To make dev and review easier I have added `non_exhaustive` to _every_ error type. We can then remove it error by error as we see fit. This is because it takes a bit of thinking to do and review where as this patch should not take much brain power to review. --- bitcoin/src/address/error.rs | 3 +- bitcoin/src/amount.rs | 21 ++--- bitcoin/src/base58.rs | 16 ++-- bitcoin/src/bip152.rs | 3 +- bitcoin/src/bip158.rs | 12 +-- bitcoin/src/bip32.rs | 33 ++++---- bitcoin/src/blockdata/block.rs | 17 ++-- bitcoin/src/blockdata/locktime/absolute.rs | 17 ++-- bitcoin/src/blockdata/locktime/relative.rs | 10 ++- bitcoin/src/blockdata/script/mod.rs | 14 ++-- .../src/blockdata/script/witness_program.rs | 6 +- .../src/blockdata/script/witness_version.rs | 3 + bitcoin/src/blockdata/transaction.rs | 15 ++-- bitcoin/src/consensus/encode.rs | 16 ++-- bitcoin/src/consensus/validation.rs | 2 + bitcoin/src/crypto/ecdsa.rs | 10 +-- bitcoin/src/crypto/key.rs | 10 +-- bitcoin/src/crypto/sighash.rs | 11 ++- bitcoin/src/crypto/taproot.rs | 6 +- bitcoin/src/merkle_tree/block.rs | 4 +- bitcoin/src/network.rs | 2 + bitcoin/src/p2p/message.rs | 1 + bitcoin/src/p2p/mod.rs | 4 +- bitcoin/src/parse.rs | 1 + bitcoin/src/pow.rs | 3 +- bitcoin/src/psbt/error.rs | 79 +++++++++---------- bitcoin/src/psbt/mod.rs | 40 +++++++--- bitcoin/src/sign_message.rs | 17 ++-- bitcoin/src/string.rs | 5 +- bitcoin/src/taproot.rs | 46 ++++++----- hashes/src/lib.rs | 3 +- 31 files changed, 248 insertions(+), 182 deletions(-) diff --git a/bitcoin/src/address/error.rs b/bitcoin/src/address/error.rs index 43d11a73..3f5854cf 100644 --- a/bitcoin/src/address/error.rs +++ b/bitcoin/src/address/error.rs @@ -82,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 { @@ -96,7 +97,7 @@ impl std::error::Error for UnknownAddressTypeError { } /// 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 539b46b1..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 { 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 2a565932..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, @@ -671,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 => @@ -682,7 +683,13 @@ impl fmt::Display for OperationError { #[cfg(feature = "std")] impl std::error::Error for OperationError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use OperationError::*; + + match *self { + InvalidComparison => None, + } + } } #[cfg(test)] 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/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 0e73c808..d6593119 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -247,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), @@ -266,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 { .. } @@ -523,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 { @@ -539,7 +540,8 @@ impl std::error::Error for InvalidSighashTypeError { /// 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 { @@ -557,6 +559,7 @@ impl std::error::Error for NonStandardSighashTypeError { /// /// 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, 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/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs index 95d51bdd..a8e3c3cc 100644 --- a/bitcoin/src/merkle_tree/block.rs +++ b/bitcoin/src/merkle_tree/block.rs @@ -497,7 +497,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"), @@ -517,7 +517,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 67807e96..cd3d3042 100644 --- a/bitcoin/src/network.rs +++ b/bitcoin/src/network.rs @@ -194,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 { @@ -241,6 +242,7 @@ impl fmt::Display for Network { /// Error in parsing network from chain hash. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct UnknownChainHashError(ChainHash); impl Display for UnknownChainHashError { diff --git a/bitcoin/src/p2p/message.rs b/bitcoin/src/p2p/message.rs index ee0c64b2..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>, } diff --git a/bitcoin/src/p2p/mod.rs b/bitcoin/src/p2p/mod.rs index 0e32c620..c7f67570 100644 --- a/bitcoin/src/p2p/mod.rs +++ b/bitcoin/src/p2p/mod.rs @@ -325,7 +325,8 @@ impl BorrowMut<[u8; 4]> for Magic { } /// An error in parsing magic bytes. -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct ParseMagicError { /// The error that occurred when parsing the string. error: hex::HexToArrayError, @@ -346,6 +347,7 @@ impl std::error::Error for ParseMagicError { /// Error in creating a Network from Magic bytes. #[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] pub struct UnknownMagicError(Magic); impl fmt::Display for UnknownMagicError { diff --git a/bitcoin/src/parse.rs b/bitcoin/src/parse.rs index 1826c5c3..aebc5f8d 100644 --- a/bitcoin/src/parse.rs +++ b/bitcoin/src/parse.rs @@ -18,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 diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index bb28427c..40ca27a2 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -707,7 +707,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 { diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs index f490700a..2ded0e26 100644 --- a/bitcoin/src/psbt/error.rs +++ b/bitcoin/src/psbt/error.rs @@ -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 a1b1e103..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." ), @@ -891,11 +894,18 @@ impl fmt::Display for ExtractTxError { #[cfg(feature = "std")] impl std::error::Error for ExtractTxError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } + 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 { @@ -934,7 +944,13 @@ impl fmt::Display for IndexOutOfBoundsError { #[cfg(feature = "std")] impl std::error::Error for IndexOutOfBoundsError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use IndexOutOfBoundsError::*; + + match *self { + Inputs { .. } | TxInput { .. } => None, + } + } } #[cfg(feature = "base64")] 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 40ba5aa3..477587fa 100644 --- a/bitcoin/src/taproot.rs +++ b/bitcoin/src/taproot.rs @@ -574,7 +574,7 @@ 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 IncompleteBuilderError { /// Indicates an attempt to construct a tap tree from a builder containing incomplete branches. @@ -620,7 +620,7 @@ impl std::error::Error for IncompleteBuilderError { /// 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 HiddenNodesError { /// Indicates an attempt to construct a tap tree from a builder containing hidden parts. @@ -630,16 +630,20 @@ pub enum HiddenNodesError { impl HiddenNodesError { /// Converts error into the original incomplete [`NodeInfo`] instance. pub fn into_node_info(self) -> NodeInfo { + use HiddenNodesError::*; + match self { - HiddenNodesError::HiddenParts(node_info) => node_info, + HiddenParts(node_info) => node_info, } } } impl core::fmt::Display for HiddenNodesError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + use HiddenNodesError::*; + f.write_str(match self { - HiddenNodesError::HiddenParts(_) => + HiddenParts(_) => "an attempt to construct a tap tree from a node_info containing hidden parts.", }) } @@ -648,7 +652,7 @@ impl core::fmt::Display for HiddenNodesError { #[cfg(feature = "std")] impl std::error::Error for HiddenNodesError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use self::HiddenNodesError::*; + use HiddenNodesError::*; match self { HiddenParts(_) => None, @@ -1447,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") } } @@ -1476,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), @@ -1507,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"), } } } @@ -1538,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,