sapio_bitcoin/util/
ecdsa.rs1use prelude::*;
20use core::str::FromStr;
21use core::{fmt, iter};
22use hashes::hex::{self, FromHex};
23use blockdata::transaction::NonStandardSighashType;
24use secp256k1;
25use EcdsaSighashType;
26
27#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30pub struct EcdsaSig {
31 pub sig: secp256k1::ecdsa::Signature,
33 pub hash_ty: EcdsaSighashType,
35}
36
37impl EcdsaSig {
38 pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig {
40 EcdsaSig {
41 sig,
42 hash_ty: EcdsaSighashType::All
43 }
44 }
45
46 pub fn from_slice(sl: &[u8]) -> Result<Self, EcdsaSigError> {
48 let (hash_ty, sig) = sl.split_last()
49 .ok_or(EcdsaSigError::EmptySignature)?;
50 let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32)
51 .map_err(|_| EcdsaSigError::NonStandardSighashType(*hash_ty as u32))?;
52 let sig = secp256k1::ecdsa::Signature::from_der(sig)
53 .map_err(EcdsaSigError::Secp256k1)?;
54 Ok(EcdsaSig { sig, hash_ty })
55 }
56
57 pub fn to_vec(&self) -> Vec<u8> {
59 self.sig.serialize_der()
61 .iter().map(|x| *x)
62 .chain(iter::once(self.hash_ty as u8))
63 .collect()
64 }
65}
66
67impl fmt::Display for EcdsaSig {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 hex::format_hex(&self.sig.serialize_der(), f)?;
70 hex::format_hex(&[self.hash_ty as u8], f)
71 }
72}
73
74impl FromStr for EcdsaSig {
75 type Err = EcdsaSigError;
76
77 fn from_str(s: &str) -> Result<Self, Self::Err> {
78 let bytes = Vec::from_hex(s)?;
79 let (sighash_byte, signature) = bytes.split_last()
80 .ok_or(EcdsaSigError::EmptySignature)?;
81 Ok(EcdsaSig {
82 sig: secp256k1::ecdsa::Signature::from_der(signature)?,
83 hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?
84 })
85 }
86}
87
88#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
90pub enum EcdsaSigError {
91 HexEncoding(hex::Error),
93 NonStandardSighashType(u32),
95 EmptySignature,
97 Secp256k1(secp256k1::Error),
99}
100
101
102impl fmt::Display for EcdsaSigError {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 match *self {
105 EcdsaSigError::NonStandardSighashType(hash_ty) =>
106 write!(f, "Non standard signature hash type {}", hash_ty),
107 EcdsaSigError::Secp256k1(ref e) =>
108 write!(f, "Invalid Ecdsa signature: {}", e),
109 EcdsaSigError::EmptySignature =>
110 write!(f, "Empty ECDSA signature"),
111 EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e)
112 }
113 }
114}
115
116#[cfg(feature = "std")]
117#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
118impl ::std::error::Error for EcdsaSigError {}
119
120impl From<secp256k1::Error> for EcdsaSigError {
121 fn from(e: secp256k1::Error) -> EcdsaSigError {
122 EcdsaSigError::Secp256k1(e)
123 }
124}
125
126impl From<NonStandardSighashType> for EcdsaSigError {
127 fn from(err: NonStandardSighashType) -> Self {
128 EcdsaSigError::NonStandardSighashType(err.0)
129 }
130}
131
132impl From<hex::Error> for EcdsaSigError {
133 fn from(err: hex::Error) -> Self {
134 EcdsaSigError::HexEncoding(err)
135 }
136}