diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs index e1a1614b..47bd4df7 100644 --- a/bitcoin/src/psbt/error.rs +++ b/bitcoin/src/psbt/error.rs @@ -11,6 +11,7 @@ use crate::consensus::encode; use crate::psbt::raw; use crate::hashes; +use crate::io; use crate::bip32::ExtendedPubKey; /// Enum for marking psbt hash error. @@ -22,7 +23,7 @@ pub enum PsbtHash { Hash256, } /// Ways that a Partially Signed Transaction might fail. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Debug)] #[non_exhaustive] pub enum Error { /// Magic bytes for a PSBT must be the ASCII for "psbt" serialized in most @@ -73,7 +74,7 @@ pub enum Error { /// global extended public key has inconsistent key sources CombineInconsistentKeySources(Box), /// Serialization error in bitcoin consensus-encoded structures - ConsensusEncoding, + ConsensusEncoding(encode::Error), /// Negative fee NegativeFee, /// Integer overflow in fee calculation @@ -100,6 +101,8 @@ pub enum Error { Version(&'static str), /// PSBT data is not consumed entirely PartialDataConsumption, + /// I/O error. + Io(io::Error), } impl fmt::Display for Error { @@ -126,7 +129,7 @@ impl fmt::Display for Error { write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash ) }, Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) }, - Error::ConsensusEncoding => f.write_str("bitcoin consensus or BIP-174 encoding error"), + 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), @@ -140,6 +143,7 @@ impl fmt::Display for Error { Error::XPubKey(s) => write!(f, "xpub key error - {}", s), Error::Version(s) => write!(f, "version error {}", s), Error::PartialDataConsumption => f.write_str("data not consumed entirely when explicitly deserializing"), + Error::Io(ref e) => write_err!(f, "I/O error"; e), } } } @@ -152,6 +156,8 @@ impl std::error::Error for Error { match self { HashParse(e) => Some(e), + ConsensusEncoding(e) => Some(e), + Io(e) => Some(e), | InvalidMagic | MissingUtxo | InvalidSeparator @@ -167,7 +173,6 @@ impl std::error::Error for Error { | NonStandardSighashType(_) | InvalidPreimageHashPair{ .. } | CombineInconsistentKeySources(_) - | ConsensusEncoding | NegativeFee | FeeOverflow | InvalidPublicKey(_) @@ -180,7 +185,7 @@ impl std::error::Error for Error { | Taproot(_) | XPubKey(_) | Version(_) - | PartialDataConsumption=> None + | PartialDataConsumption=> None, } } } @@ -193,7 +198,13 @@ impl From for Error { } impl From for Error { - fn from(_: encode::Error) -> Self { - Error::ConsensusEncoding + fn from(e: encode::Error) -> Self { + Error::ConsensusEncoding(e) + } +} + +impl From for Error { + fn from(e: io::Error) -> Self { + Error::Io(e) } } diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index 9d83ca90..ebca2936 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -1732,15 +1732,24 @@ mod tests { // no previous output let mut t2 = t.clone(); t2.inputs[0].non_witness_utxo = None; - assert_eq!(t2.fee(), Err(Error::MissingUtxo)); + match t2.fee().unwrap_err() { + Error::MissingUtxo => {}, + e => panic!("unexpected error: {:?}", e) + } // negative fee let mut t3 = t.clone(); t3.unsigned_tx.output[0].value = prev_output_val; - assert_eq!(t3.fee(), Err(Error::NegativeFee)); + match t3.fee().unwrap_err() { + Error::NegativeFee => {}, + e => panic!("unexpected error: {:?}", e) + } // overflow t.unsigned_tx.output[0].value = u64::max_value(); t.unsigned_tx.output[1].value = u64::max_value(); - assert_eq!(t.fee(), Err(Error::FeeOverflow)); + match t.fee().unwrap_err() { + Error::FeeOverflow => {}, + e => panic!("unexpected error: {:?}", e) + } } #[test] diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs index 47a60a64..f908f975 100644 --- a/bitcoin/src/psbt/serialize.rs +++ b/bitcoin/src/psbt/serialize.rs @@ -225,7 +225,7 @@ impl Serialize for KeySource { impl Deserialize for KeySource { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 4 { - return Err(encode::Error::from(io::Error::from(io::ErrorKind::UnexpectedEof)).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) } let fprint: Fingerprint = bytes[0..4].try_into().expect("4 is the fingerprint length"); @@ -319,7 +319,7 @@ impl Serialize for (XOnlyPublicKey, TapLeafHash) { impl Deserialize for (XOnlyPublicKey, TapLeafHash) { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 32 { - return Err(encode::Error::from(io::Error::from(io::ErrorKind::UnexpectedEof)).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) } let a: XOnlyPublicKey = Deserialize::deserialize(&bytes[..32])?; let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?; @@ -353,7 +353,7 @@ impl Serialize for (ScriptBuf, LeafVersion) { impl Deserialize for (ScriptBuf, LeafVersion) { fn deserialize(bytes: &[u8]) -> Result { if bytes.is_empty() { - return Err(encode::Error::from(io::Error::from(io::ErrorKind::UnexpectedEof)).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) } // The last byte is LeafVersion. let script = ScriptBuf::deserialize(&bytes[..bytes.len() - 1])?;