diff --git a/src/lib.rs b/src/lib.rs index 7fce7f3b..5005744c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,7 +136,7 @@ pub use util::amount::SignedAmount; pub use util::merkleblock::MerkleBlock; pub use util::sighash::SchnorrSigHashType; -pub use util::key::{self, EcdsaSig, EcdsaSigError}; +pub use util::ecdsa::{self, EcdsaSig, EcdsaSigError}; pub use util::schnorr::{self, SchnorrSig, SchnorrSigError}; pub use util::key::{PrivateKey, PublicKey, XOnlyPublicKey, KeyPair}; #[allow(deprecated)] diff --git a/src/util/ecdsa.rs b/src/util/ecdsa.rs new file mode 100644 index 00000000..52a2fe73 --- /dev/null +++ b/src/util/ecdsa.rs @@ -0,0 +1,135 @@ +// Rust Bitcoin Library +// Written in 2014 by +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! ECDSA Bitcoin signatures. +//! +//! This module provides ECDSA signatures used Bitcoin that can be roundtrip (de)serialized. + +use prelude::*; +use core::str::FromStr; +use core::fmt; +use hashes::hex::{self, FromHex}; +use blockdata::transaction::NonStandardSigHashType; +use secp256k1; +use EcdsaSigHashType; + +/// An ECDSA signature with the corresponding hash type. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct EcdsaSig { + /// The underlying ECDSA Signature + pub sig: secp256k1::ecdsa::Signature, + /// The corresponding hash type + pub hash_ty: EcdsaSigHashType, +} + +impl EcdsaSig { + /// Constructs ECDSA bitcoin signature for [`EcdsaSigHashType::All`] + pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig { + EcdsaSig { + sig, + hash_ty: EcdsaSigHashType::All + } + } + + /// Deserialize from slice + pub fn from_slice(sl: &[u8]) -> Result { + let (hash_ty, sig) = sl.split_last() + .ok_or(EcdsaSigError::EmptySignature)?; + let hash_ty = EcdsaSigHashType::from_u32_standard(*hash_ty as u32) + .map_err(|_| EcdsaSigError::NonStandardSigHashType(*hash_ty as u32))?; + let sig = secp256k1::ecdsa::Signature::from_der(sig) + .map_err(EcdsaSigError::Secp256k1)?; + Ok(EcdsaSig { sig, hash_ty }) + } + + /// Serialize EcdsaSig + pub fn to_vec(&self) -> Vec { + // TODO: add support to serialize to a writer to SerializedSig + let mut ser_sig = self.sig.serialize_der().to_vec(); + ser_sig.push(self.hash_ty.as_u32() as u8); + ser_sig + } +} + +impl fmt::Display for EcdsaSig { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + hex::format_hex(&self.sig.serialize_der(), f)?; + hex::format_hex(&[self.hash_ty as u8], f) + } +} + +impl FromStr for EcdsaSig { + type Err = EcdsaSigError; + + fn from_str(s: &str) -> Result { + let bytes = Vec::from_hex(s)?; + let (sighash_byte, signature) = bytes.split_last() + .ok_or(EcdsaSigError::EmptySignature)?; + Ok(EcdsaSig { + sig: secp256k1::ecdsa::Signature::from_der(signature)?, + hash_ty: EcdsaSigHashType::from_u32_standard(*sighash_byte as u32)? + }) + } +} + +/// A key-related error. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum EcdsaSigError { + /// Hex encoding error + HexEncoding(hex::Error), + /// Base58 encoding error + NonStandardSigHashType(u32), + /// Empty Signature + EmptySignature, + /// secp256k1-related error + Secp256k1(secp256k1::Error), +} + + +impl fmt::Display for EcdsaSigError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + EcdsaSigError::NonStandardSigHashType(hash_ty) => + write!(f, "Non standard signature hash type {}", hash_ty), + EcdsaSigError::Secp256k1(ref e) => + write!(f, "Invalid Ecdsa signature: {}", e), + EcdsaSigError::EmptySignature => + write!(f, "Empty ECDSA signature"), + EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e) + } + } +} + +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl ::std::error::Error for EcdsaSigError {} + +impl From for EcdsaSigError { + fn from(e: secp256k1::Error) -> EcdsaSigError { + EcdsaSigError::Secp256k1(e) + } +} + +impl From for EcdsaSigError { + fn from(err: NonStandardSigHashType) -> Self { + EcdsaSigError::NonStandardSigHashType(err.0) + } +} + +impl From for EcdsaSigError { + fn from(err: hex::Error) -> Self { + EcdsaSigError::HexEncoding(err) + } +} diff --git a/src/util/key.rs b/src/util/key.rs index 82937357..a4f50eba 100644 --- a/src/util/key.rs +++ b/src/util/key.rs @@ -27,11 +27,9 @@ use io; use secp256k1::{self, Secp256k1}; use network::constants::Network; -use hashes::{Hash, hash160, hex}; -use hashes::hex::FromHex; +use hashes::{Hash, hash160}; use hash_types::{PubkeyHash, WPubkeyHash}; use util::base58; -use blockdata::transaction::{EcdsaSigHashType, NonStandardSigHashType}; /// A key-related error. @@ -464,116 +462,6 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey { } } -/// An ECDSA signature with the corresponding hash type. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct EcdsaSig { - /// The underlying ECDSA Signature - pub sig: secp256k1::ecdsa::Signature, - /// The corresponding hash type - pub hash_ty: EcdsaSigHashType, -} - -impl EcdsaSig { - /// Constructs ECDSA bitcoin signature for [`EcdsaSigHashType::All`] - pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig { - EcdsaSig { - sig, - hash_ty: EcdsaSigHashType::All - } - } - - /// Deserialize from slice - pub fn from_slice(sl: &[u8]) -> Result { - let (hash_ty, sig) = sl.split_last() - .ok_or(EcdsaSigError::EmptySignature)?; - let hash_ty = EcdsaSigHashType::from_u32_standard(*hash_ty as u32) - .map_err(|_| EcdsaSigError::NonStandardSigHashType(*hash_ty as u32))?; - let sig = secp256k1::ecdsa::Signature::from_der(sig) - .map_err(EcdsaSigError::Secp256k1)?; - Ok(EcdsaSig { sig, hash_ty }) - } - - /// Serialize EcdsaSig - pub fn to_vec(&self) -> Vec { - // TODO: add support to serialize to a writer to SerializedSig - let mut ser_sig = self.sig.serialize_der().to_vec(); - ser_sig.push(self.hash_ty.as_u32() as u8); - ser_sig - } -} - -impl fmt::Display for EcdsaSig { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - hex::format_hex(&self.sig.serialize_der(), f)?; - hex::format_hex(&[self.hash_ty as u8], f) - } -} - -impl FromStr for EcdsaSig { - type Err = EcdsaSigError; - - fn from_str(s: &str) -> Result { - let bytes = Vec::from_hex(s)?; - let (sighash_byte, signature) = bytes.split_last() - .ok_or(EcdsaSigError::EmptySignature)?; - Ok(EcdsaSig { - sig: secp256k1::ecdsa::Signature::from_der(signature)?, - hash_ty: EcdsaSigHashType::from_u32_standard(*sighash_byte as u32)? - }) - } -} - -/// A key-related error. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub enum EcdsaSigError { - /// Hex encoding error - HexEncoding(hex::Error), - /// Base58 encoding error - NonStandardSigHashType(u32), - /// Empty Signature - EmptySignature, - /// secp256k1-related error - Secp256k1(secp256k1::Error), -} - - -impl fmt::Display for EcdsaSigError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - EcdsaSigError::NonStandardSigHashType(hash_ty) => - write!(f, "Non standard signature hash type {}", hash_ty), - EcdsaSigError::Secp256k1(ref e) => - write!(f, "Invalid Ecdsa signature: {}", e), - EcdsaSigError::EmptySignature => - write!(f, "Empty ECDSA signature"), - EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e) - } - } -} - -#[cfg(feature = "std")] -#[cfg_attr(docsrs, doc(cfg(feature = "std")))] -impl ::std::error::Error for EcdsaSigError {} - -impl From for EcdsaSigError { - fn from(e: secp256k1::Error) -> EcdsaSigError { - EcdsaSigError::Secp256k1(e) - } -} - -impl From for EcdsaSigError { - fn from(err: NonStandardSigHashType) -> Self { - EcdsaSigError::NonStandardSigHashType(err.0) - } -} - -impl From for EcdsaSigError { - fn from(err: hex::Error) -> Self { - EcdsaSigError::HexEncoding(err) - } -} - #[cfg(test)] mod tests { use io; diff --git a/src/util/mod.rs b/src/util/mod.rs index 6423ae39..ba02fd70 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -18,6 +18,7 @@ //! pub mod key; +pub mod ecdsa; pub mod schnorr; pub mod address; pub mod amount; @@ -36,14 +37,6 @@ pub mod sighash; pub(crate) mod endian; -pub mod ecdsa { - //! ECDSA Bitcoin signatures. - //! - //! This module provides ECDSA signatures used Bitcoin that can be roundtrip (de)serialized. - - pub use super::key::{EcdsaSig, EcdsaSigError}; -} - use prelude::*; use io; use core::fmt;