Add InvalidSighashTypeError

As we do for `NonStandardSighashErrorType` add an error struct for
invalid sighash type, used by the `taproot` module instead of returning
a generic error enum with loads of unused variants.
This commit is contained in:
Tobin C. Harding 2023-05-18 15:45:50 +10:00
parent baba0fde57
commit ae07786c27
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
4 changed files with 33 additions and 16 deletions

View File

@ -499,7 +499,7 @@ impl TapSighashType {
} }
/// Constructs a [`TapSighashType`] from a raw `u8`. /// Constructs a [`TapSighashType`] from a raw `u8`.
pub fn from_consensus_u8(hash_ty: u8) -> Result<Self, Error> { pub fn from_consensus_u8(hash_ty: u8) -> Result<Self, InvalidSighashTypeError> {
use TapSighashType::*; use TapSighashType::*;
Ok(match hash_ty { Ok(match hash_ty {
@ -510,11 +510,23 @@ impl TapSighashType {
0x81 => AllPlusAnyoneCanPay, 0x81 => AllPlusAnyoneCanPay,
0x82 => NonePlusAnyoneCanPay, 0x82 => NonePlusAnyoneCanPay,
0x83 => SinglePlusAnyoneCanPay, 0x83 => SinglePlusAnyoneCanPay,
x => return Err(Error::InvalidSighashType(x as u32)), x => return Err(InvalidSighashTypeError(x.into())),
}) })
} }
} }
/// Integer is not a consensus valid sighash type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InvalidSighashTypeError(pub u32);
impl fmt::Display for InvalidSighashTypeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "invalid sighash type {}", self.0)
}
}
impl_std_error!(InvalidSighashTypeError);
/// This type is consensus valid but an input including it would prevent the transaction from /// This type is consensus valid but an input including it would prevent the transaction from
/// being relayed on today's Bitcoin network. /// being relayed on today's Bitcoin network.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]

View File

@ -11,7 +11,7 @@ use internals::write_err;
pub use secp256k1::{self, constants, KeyPair, Parity, Secp256k1, Verification, XOnlyPublicKey}; pub use secp256k1::{self, constants, KeyPair, Parity, Secp256k1, Verification, XOnlyPublicKey};
use crate::prelude::*; use crate::prelude::*;
use crate::sighash::TapSighashType; use crate::sighash::{InvalidSighashTypeError, TapSighashType};
/// A BIP340-341 serialized taproot signature with the corresponding hash type. /// A BIP340-341 serialized taproot signature with the corresponding hash type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -35,8 +35,7 @@ impl Signature {
} }
65 => { 65 => {
let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65"); let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65");
let hash_ty = TapSighashType::from_consensus_u8(*hash_ty) let hash_ty = TapSighashType::from_consensus_u8(*hash_ty)?;
.map_err(|_| SigFromSliceError::InvalidSighashType(*hash_ty))?;
let sig = secp256k1::schnorr::Signature::from_slice(sig)?; let sig = secp256k1::schnorr::Signature::from_slice(sig)?;
Ok(Signature { sig, hash_ty }) Ok(Signature { sig, hash_ty })
} }
@ -64,7 +63,7 @@ impl Signature {
#[non_exhaustive] #[non_exhaustive]
pub enum SigFromSliceError { pub enum SigFromSliceError {
/// Invalid signature hash type. /// Invalid signature hash type.
InvalidSighashType(u8), SighashType(InvalidSighashTypeError),
/// Signature has valid size but does not parse correctly /// Signature has valid size but does not parse correctly
Secp256k1(secp256k1::Error), Secp256k1(secp256k1::Error),
/// Invalid taproot signature size /// Invalid taproot signature size
@ -76,7 +75,7 @@ impl fmt::Display for SigFromSliceError {
use SigFromSliceError::*; use SigFromSliceError::*;
match *self { match *self {
InvalidSighashType(hash_ty) => write!(f, "invalid signature hash type {}", hash_ty), SighashType(ref e) => write_err!(f, "invalid signature hash type"; e),
Secp256k1(ref e) => Secp256k1(ref e) =>
write_err!(f, "taproot signature has correct len but is malformed"; e), write_err!(f, "taproot signature has correct len but is malformed"; e),
InvalidSignatureSize(sz) => write!(f, "invalid taproot signature size: {}", sz), InvalidSignatureSize(sz) => write!(f, "invalid taproot signature size: {}", sz),
@ -91,11 +90,16 @@ impl std::error::Error for SigFromSliceError {
match self { match self {
Secp256k1(e) => Some(e), Secp256k1(e) => Some(e),
InvalidSighashType(_) | InvalidSignatureSize(_) => None, SighashType(e) => Some(e),
InvalidSignatureSize(_) => None,
} }
} }
} }
impl From<secp256k1::Error> for SigFromSliceError { impl From<secp256k1::Error> for SigFromSliceError {
fn from(e: secp256k1::Error) -> Self { SigFromSliceError::Secp256k1(e) } fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) }
}
impl From<InvalidSighashTypeError> for SigFromSliceError {
fn from(err: InvalidSighashTypeError) -> Self { Self::SighashType(err) }
} }

View File

@ -18,7 +18,8 @@ use crate::psbt::map::Map;
use crate::psbt::serialize::Deserialize; use crate::psbt::serialize::Deserialize;
use crate::psbt::{self, error, raw, Error}; use crate::psbt::{self, error, raw, Error};
use crate::sighash::{ use crate::sighash::{
self, EcdsaSighashType, NonStandardSighashTypeError, SighashTypeParseError, TapSighashType, EcdsaSighashType, InvalidSighashTypeError, NonStandardSighashTypeError, SighashTypeParseError,
TapSighashType,
}; };
use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash}; use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash};
@ -196,9 +197,9 @@ impl PsbtSighashType {
/// Returns the [`TapSighashType`] if the [`PsbtSighashType`] can be /// Returns the [`TapSighashType`] if the [`PsbtSighashType`] can be
/// converted to one. /// converted to one.
pub fn taproot_hash_ty(self) -> Result<TapSighashType, sighash::Error> { pub fn taproot_hash_ty(self) -> Result<TapSighashType, InvalidSighashTypeError> {
if self.inner > 0xffu32 { if self.inner > 0xffu32 {
Err(sighash::Error::InvalidSighashType(self.inner)) Err(InvalidSighashTypeError(self.inner))
} else { } else {
TapSighashType::from_consensus_u8(self.inner as u8) TapSighashType::from_consensus_u8(self.inner as u8)
} }
@ -235,7 +236,7 @@ impl Input {
/// # Errors /// # Errors
/// ///
/// If the `sighash_type` field is set to a invalid Taproot sighash value. /// If the `sighash_type` field is set to a invalid Taproot sighash value.
pub fn taproot_hash_ty(&self) -> Result<TapSighashType, sighash::Error> { pub fn taproot_hash_ty(&self) -> Result<TapSighashType, InvalidSighashTypeError> {
self.sighash_type self.sighash_type
.map(|sighash_type| sighash_type.taproot_hash_ty()) .map(|sighash_type| sighash_type.taproot_hash_ty())
.unwrap_or(Ok(TapSighashType::Default)) .unwrap_or(Ok(TapSighashType::Default))
@ -575,7 +576,7 @@ mod test {
let back = PsbtSighashType::from_str(&s).unwrap(); let back = PsbtSighashType::from_str(&s).unwrap();
assert_eq!(back, sighash); assert_eq!(back, sighash);
assert_eq!(back.ecdsa_hash_ty(), Err(sighash::NonStandardSighashTypeError(nonstd))); assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashTypeError(nonstd)));
assert_eq!(back.taproot_hash_ty(), Err(sighash::Error::InvalidSighashType(nonstd))); assert_eq!(back.taproot_hash_ty(), Err(InvalidSighashTypeError(nonstd)));
} }
} }

View File

@ -258,7 +258,7 @@ impl Deserialize for taproot::Signature {
use taproot::SigFromSliceError::*; use taproot::SigFromSliceError::*;
taproot::Signature::from_slice(bytes).map_err(|e| match e { taproot::Signature::from_slice(bytes).map_err(|e| match e {
InvalidSighashType(flag) => Error::NonStandardSighashType(flag as u32), SighashType(err) => Error::NonStandardSighashType(err.0),
InvalidSignatureSize(_) => Error::InvalidTaprootSignature(e), InvalidSignatureSize(_) => Error::InvalidTaprootSignature(e),
Secp256k1(..) => Error::InvalidTaprootSignature(e), Secp256k1(..) => Error::InvalidTaprootSignature(e),
}) })