Introduce AnnexError

Split the annex related error out of the general `sighash::Error`.
This commit is contained in:
Tobin C. Harding 2024-01-17 12:06:10 +11:00
parent a1a2056829
commit b0f20903a5
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
1 changed files with 43 additions and 13 deletions

View File

@ -235,9 +235,6 @@ pub enum Error {
/// `SIGHASH_ANYONECANPAY`. /// `SIGHASH_ANYONECANPAY`.
PrevoutsKind(PrevoutsKindError), PrevoutsKind(PrevoutsKindError),
/// Annex must be at least one byte long and the first bytes must be `0x50`.
WrongAnnex,
/// Invalid Sighash type. /// Invalid Sighash type.
InvalidSighashType(u32), InvalidSighashType(u32),
@ -256,7 +253,6 @@ impl fmt::Display for Error {
PrevoutsSize(ref e) => write_err!(f, "prevouts size"; e), PrevoutsSize(ref e) => write_err!(f, "prevouts size"; e),
PrevoutsIndex(ref e) => write_err!(f, "prevouts index"; e), PrevoutsIndex(ref e) => write_err!(f, "prevouts index"; e),
PrevoutsKind(ref e) => write_err!(f, "prevouts kind"; e), PrevoutsKind(ref e) => write_err!(f, "prevouts kind"; e),
WrongAnnex => write!(f, "annex must be at least one byte long and the first bytes must be `0x50`"),
InvalidSighashType(hash_ty) => write!(f, "Invalid taproot signature hash type : {} ", hash_ty), InvalidSighashType(hash_ty) => write!(f, "Invalid taproot signature hash type : {} ", hash_ty),
NotP2wpkhScript => write!(f, "script is not a script pubkey for a p2wpkh output"), NotP2wpkhScript => write!(f, "script is not a script pubkey for a p2wpkh output"),
} }
@ -275,7 +271,6 @@ impl std::error::Error for Error {
Io(_) Io(_)
| IndexOutOfInputsBounds { .. } | IndexOutOfInputsBounds { .. }
| SingleWithoutCorrespondingOutput { .. } | SingleWithoutCorrespondingOutput { .. }
| WrongAnnex
| InvalidSighashType(_) | InvalidSighashType(_)
| NotP2wpkhScript => None, | NotP2wpkhScript => None,
} }
@ -1227,11 +1222,13 @@ pub struct Annex<'a>(&'a [u8]);
impl<'a> Annex<'a> { impl<'a> Annex<'a> {
/// Creates a new `Annex` struct checking the first byte is `0x50`. /// Creates a new `Annex` struct checking the first byte is `0x50`.
pub fn new(annex_bytes: &'a [u8]) -> Result<Self, Error> { pub fn new(annex_bytes: &'a [u8]) -> Result<Self, AnnexError> {
if annex_bytes.first() == Some(&TAPROOT_ANNEX_PREFIX) { use AnnexError::*;
Ok(Annex(annex_bytes))
} else { match annex_bytes.first() {
Err(Error::WrongAnnex) Some(&TAPROOT_ANNEX_PREFIX) => Ok(Annex(annex_bytes)),
Some(other) => Err(IncorrectPrefix(*other)),
None => Err(Empty),
} }
} }
@ -1245,6 +1242,39 @@ impl<'a> Encodable for Annex<'a> {
} }
} }
/// Annex must be at least one byte long and the first bytes must be `0x50`.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum AnnexError {
/// The annex is empty.
Empty,
/// Incorrect prefix byte in the annex.
IncorrectPrefix(u8),
}
impl fmt::Display for AnnexError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use AnnexError::*;
match *self {
Empty => write!(f, "the annex is empty"),
IncorrectPrefix(byte) =>
write!(f, "incorrect prefix byte in the annex {:02x}, expecting 0x50", byte),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for AnnexError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use AnnexError::*;
match *self {
Empty | IncorrectPrefix(_) => None,
}
}
}
fn is_invalid_use_of_sighash_single(sighash: u32, input_index: usize, output_len: usize) -> bool { fn is_invalid_use_of_sighash_single(sighash: u32, input_index: usize, output_len: usize) -> bool {
let ty = EcdsaSighashType::from_consensus(sighash); let ty = EcdsaSighashType::from_consensus(sighash);
ty == EcdsaSighashType::Single && input_index >= output_len ty == EcdsaSighashType::Single && input_index >= output_len
@ -1583,9 +1613,9 @@ mod tests {
#[test] #[test]
fn test_annex_errors() { fn test_annex_errors() {
assert_eq!(Annex::new(&[]), Err(Error::WrongAnnex)); assert_eq!(Annex::new(&[]), Err(AnnexError::Empty));
assert_eq!(Annex::new(&[0x51]), Err(Error::WrongAnnex)); assert_eq!(Annex::new(&[0x51]), Err(AnnexError::IncorrectPrefix(0x51)));
assert_eq!(Annex::new(&[0x51, 0x50]), Err(Error::WrongAnnex)); assert_eq!(Annex::new(&[0x51, 0x50]), Err(AnnexError::IncorrectPrefix(0x51)));
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]