Skip to content

Commit ccb1649

Browse files
committed
Re-org keys and ecdsa mods - pt.3
1 parent 90ee63d commit ccb1649

File tree

4 files changed

+138
-122
lines changed

4 files changed

+138
-122
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub use util::amount::SignedAmount;
136136
pub use util::merkleblock::MerkleBlock;
137137
pub use util::sighash::SchnorrSigHashType;
138138

139-
pub use util::key::{self, EcdsaSig, EcdsaSigError};
139+
pub use util::ecdsa::{self, EcdsaSig, EcdsaSigError};
140140
pub use util::schnorr::{self, SchnorrSig, SchnorrSigError};
141141
pub use util::key::{PrivateKey, PublicKey, XOnlyPublicKey, KeyPair};
142142
#[allow(deprecated)]

src/util/ecdsa.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Rust Bitcoin Library
2+
// Written in 2014 by
3+
// Andrew Poelstra <[email protected]>
4+
//
5+
// To the extent possible under law, the author(s) have dedicated all
6+
// copyright and related and neighboring rights to this software to
7+
// the public domain worldwide. This software is distributed without
8+
// any warranty.
9+
//
10+
// You should have received a copy of the CC0 Public Domain Dedication
11+
// along with this software.
12+
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13+
//
14+
15+
//! ECDSA Bitcoin signatures.
16+
//!
17+
//! This module provides ECDSA signatures used Bitcoin that can be roundtrip (de)serialized.
18+
19+
use prelude::*;
20+
use core::str::FromStr;
21+
use core::fmt;
22+
use hashes::hex::{self, FromHex};
23+
use blockdata::transaction::NonStandardSigHashType;
24+
use secp256k1;
25+
use EcdsaSigHashType;
26+
27+
/// An ECDSA signature with the corresponding hash type.
28+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30+
pub struct EcdsaSig {
31+
/// The underlying ECDSA Signature
32+
pub sig: secp256k1::ecdsa::Signature,
33+
/// The corresponding hash type
34+
pub hash_ty: EcdsaSigHashType,
35+
}
36+
37+
impl EcdsaSig {
38+
/// Constructs ECDSA bitcoin signature for [`EcdsaSigHashType::All`]
39+
pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig {
40+
EcdsaSig {
41+
sig,
42+
hash_ty: EcdsaSigHashType::All
43+
}
44+
}
45+
46+
/// Deserialize from slice
47+
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_u32_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+
/// Serialize EcdsaSig
58+
pub fn to_vec(&self) -> Vec<u8> {
59+
// TODO: add support to serialize to a writer to SerializedSig
60+
let mut ser_sig = self.sig.serialize_der().to_vec();
61+
ser_sig.push(self.hash_ty.as_u32() as u8);
62+
ser_sig
63+
}
64+
}
65+
66+
impl fmt::Display for EcdsaSig {
67+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68+
hex::format_hex(&self.sig.serialize_der(), f)?;
69+
hex::format_hex(&[self.hash_ty as u8], f)
70+
}
71+
}
72+
73+
impl FromStr for EcdsaSig {
74+
type Err = EcdsaSigError;
75+
76+
fn from_str(s: &str) -> Result<Self, Self::Err> {
77+
let bytes = Vec::from_hex(s)?;
78+
let (sighash_byte, signature) = bytes.split_last()
79+
.ok_or(EcdsaSigError::EmptySignature)?;
80+
Ok(EcdsaSig {
81+
sig: secp256k1::ecdsa::Signature::from_der(signature)?,
82+
hash_ty: EcdsaSigHashType::from_u32_standard(*sighash_byte as u32)?
83+
})
84+
}
85+
}
86+
87+
/// A key-related error.
88+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
89+
pub enum EcdsaSigError {
90+
/// Hex encoding error
91+
HexEncoding(hex::Error),
92+
/// Base58 encoding error
93+
NonStandardSigHashType(u32),
94+
/// Empty Signature
95+
EmptySignature,
96+
/// secp256k1-related error
97+
Secp256k1(secp256k1::Error),
98+
}
99+
100+
101+
impl fmt::Display for EcdsaSigError {
102+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103+
match *self {
104+
EcdsaSigError::NonStandardSigHashType(hash_ty) =>
105+
write!(f, "Non standard signature hash type {}", hash_ty),
106+
EcdsaSigError::Secp256k1(ref e) =>
107+
write!(f, "Invalid Ecdsa signature: {}", e),
108+
EcdsaSigError::EmptySignature =>
109+
write!(f, "Empty ECDSA signature"),
110+
EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e)
111+
}
112+
}
113+
}
114+
115+
#[cfg(feature = "std")]
116+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
117+
impl ::std::error::Error for EcdsaSigError {}
118+
119+
impl From<secp256k1::Error> for EcdsaSigError {
120+
fn from(e: secp256k1::Error) -> EcdsaSigError {
121+
EcdsaSigError::Secp256k1(e)
122+
}
123+
}
124+
125+
impl From<NonStandardSigHashType> for EcdsaSigError {
126+
fn from(err: NonStandardSigHashType) -> Self {
127+
EcdsaSigError::NonStandardSigHashType(err.0)
128+
}
129+
}
130+
131+
impl From<hex::Error> for EcdsaSigError {
132+
fn from(err: hex::Error) -> Self {
133+
EcdsaSigError::HexEncoding(err)
134+
}
135+
}

src/util/key.rs

Lines changed: 1 addition & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ use io;
2727

2828
use secp256k1::{self, Secp256k1};
2929
use network::constants::Network;
30-
use hashes::{Hash, hash160, hex};
31-
use hashes::hex::FromHex;
30+
use hashes::{Hash, hash160};
3231
use hash_types::{PubkeyHash, WPubkeyHash};
3332
use util::base58;
34-
use blockdata::transaction::{EcdsaSigHashType, NonStandardSigHashType};
3533

3634

3735
/// A key-related error.
@@ -464,116 +462,6 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey {
464462
}
465463
}
466464

467-
/// An ECDSA signature with the corresponding hash type.
468-
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
469-
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
470-
pub struct EcdsaSig {
471-
/// The underlying ECDSA Signature
472-
pub sig: secp256k1::ecdsa::Signature,
473-
/// The corresponding hash type
474-
pub hash_ty: EcdsaSigHashType,
475-
}
476-
477-
impl EcdsaSig {
478-
/// Constructs ECDSA bitcoin signature for [`EcdsaSigHashType::All`]
479-
pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> EcdsaSig {
480-
EcdsaSig {
481-
sig,
482-
hash_ty: EcdsaSigHashType::All
483-
}
484-
}
485-
486-
/// Deserialize from slice
487-
pub fn from_slice(sl: &[u8]) -> Result<Self, EcdsaSigError> {
488-
let (hash_ty, sig) = sl.split_last()
489-
.ok_or(EcdsaSigError::EmptySignature)?;
490-
let hash_ty = EcdsaSigHashType::from_u32_standard(*hash_ty as u32)
491-
.map_err(|_| EcdsaSigError::NonStandardSigHashType(*hash_ty as u32))?;
492-
let sig = secp256k1::ecdsa::Signature::from_der(sig)
493-
.map_err(EcdsaSigError::Secp256k1)?;
494-
Ok(EcdsaSig { sig, hash_ty })
495-
}
496-
497-
/// Serialize EcdsaSig
498-
pub fn to_vec(&self) -> Vec<u8> {
499-
// TODO: add support to serialize to a writer to SerializedSig
500-
let mut ser_sig = self.sig.serialize_der().to_vec();
501-
ser_sig.push(self.hash_ty.as_u32() as u8);
502-
ser_sig
503-
}
504-
}
505-
506-
impl fmt::Display for EcdsaSig {
507-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
508-
hex::format_hex(&self.sig.serialize_der(), f)?;
509-
hex::format_hex(&[self.hash_ty as u8], f)
510-
}
511-
}
512-
513-
impl FromStr for EcdsaSig {
514-
type Err = EcdsaSigError;
515-
516-
fn from_str(s: &str) -> Result<Self, Self::Err> {
517-
let bytes = Vec::from_hex(s)?;
518-
let (sighash_byte, signature) = bytes.split_last()
519-
.ok_or(EcdsaSigError::EmptySignature)?;
520-
Ok(EcdsaSig {
521-
sig: secp256k1::ecdsa::Signature::from_der(signature)?,
522-
hash_ty: EcdsaSigHashType::from_u32_standard(*sighash_byte as u32)?
523-
})
524-
}
525-
}
526-
527-
/// A key-related error.
528-
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
529-
pub enum EcdsaSigError {
530-
/// Hex encoding error
531-
HexEncoding(hex::Error),
532-
/// Base58 encoding error
533-
NonStandardSigHashType(u32),
534-
/// Empty Signature
535-
EmptySignature,
536-
/// secp256k1-related error
537-
Secp256k1(secp256k1::Error),
538-
}
539-
540-
541-
impl fmt::Display for EcdsaSigError {
542-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
543-
match *self {
544-
EcdsaSigError::NonStandardSigHashType(hash_ty) =>
545-
write!(f, "Non standard signature hash type {}", hash_ty),
546-
EcdsaSigError::Secp256k1(ref e) =>
547-
write!(f, "Invalid Ecdsa signature: {}", e),
548-
EcdsaSigError::EmptySignature =>
549-
write!(f, "Empty ECDSA signature"),
550-
EcdsaSigError::HexEncoding(e) => write!(f, "EcdsaSig hex encoding error: {}", e)
551-
}
552-
}
553-
}
554-
555-
#[cfg(feature = "std")]
556-
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
557-
impl ::std::error::Error for EcdsaSigError {}
558-
559-
impl From<secp256k1::Error> for EcdsaSigError {
560-
fn from(e: secp256k1::Error) -> EcdsaSigError {
561-
EcdsaSigError::Secp256k1(e)
562-
}
563-
}
564-
565-
impl From<NonStandardSigHashType> for EcdsaSigError {
566-
fn from(err: NonStandardSigHashType) -> Self {
567-
EcdsaSigError::NonStandardSigHashType(err.0)
568-
}
569-
}
570-
571-
impl From<hex::Error> for EcdsaSigError {
572-
fn from(err: hex::Error) -> Self {
573-
EcdsaSigError::HexEncoding(err)
574-
}
575-
}
576-
577465
#[cfg(test)]
578466
mod tests {
579467
use io;

src/util/mod.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//!
1919
2020
pub mod key;
21+
pub mod ecdsa;
2122
pub mod schnorr;
2223
pub mod address;
2324
pub mod amount;
@@ -36,14 +37,6 @@ pub mod sighash;
3637

3738
pub(crate) mod endian;
3839

39-
pub mod ecdsa {
40-
//! ECDSA Bitcoin signatures.
41-
//!
42-
//! This module provides ECDSA signatures used Bitcoin that can be roundtrip (de)serialized.
43-
44-
pub use super::key::{EcdsaSig, EcdsaSigError};
45-
}
46-
4740
use prelude::*;
4841
use io;
4942
use core::fmt;

0 commit comments

Comments
 (0)