add `fmt::Display` and `str::FromStr` impls for `Signature`

This commit is contained in:
Andrew Poelstra 2018-08-26 18:52:17 +00:00
parent 572adb2873
commit 30aa3a0c28
1 changed files with 67 additions and 1 deletions

View File

@ -142,7 +142,7 @@
extern crate libc;
use libc::size_t;
use std::{error, fmt, ops, ptr};
use std::{error, fmt, ops, ptr, str};
#[cfg(any(test, feature = "rand"))] use rand::Rng;
#[macro_use]
@ -164,6 +164,35 @@ pub struct RecoveryId(i32);
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Signature(ffi::Signature);
impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut v = [0; 72];
let mut len = v.len() as size_t;
let secp = Secp256k1::without_caps();
unsafe {
let err = ffi::secp256k1_ecdsa_signature_serialize_der(secp.ctx, v.as_mut_ptr(),
&mut len, self.as_ptr());
debug_assert!(err == 1);
}
for ch in &v[..] {
write!(f, "{:02x}", *ch)?;
}
Ok(())
}
}
impl str::FromStr for Signature {
type Err = Error;
fn from_str(s: &str) -> Result<Signature, Error> {
let secp = Secp256k1::without_caps();
let mut res = [0; 72];
match from_hex(s, &mut res) {
Ok(x) => Signature::from_der(&secp, &res[0..x]),
_ => Err(Error::InvalidSignature),
}
}
}
/// An ECDSA signature with a recovery ID for pubkey recovery
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct RecoverableSignature(ffi::RecoverableSignature);
@ -739,6 +768,7 @@ fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
#[cfg(test)]
mod tests {
use rand::{Rng, thread_rng};
use std::str::FromStr;
use key::{SecretKey, PublicKey};
use super::from_hex;
@ -850,6 +880,42 @@ mod tests {
}
}
#[test]
fn signature_display() {
let secp = Secp256k1::without_caps();
let hex_str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45";
let byte_str = hex!(hex_str);
assert_eq!(
Signature::from_der(&secp, &byte_str).expect("byte str decode"),
Signature::from_str(&hex_str).expect("byte str decode")
);
let sig = Signature::from_str(&hex_str).expect("byte str decode");
assert_eq!(&sig.to_string(), hex_str);
assert!(Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4"
).is_err());
assert!(Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab"
).is_err());
assert!(Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx"
).is_err());
assert!(Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"
).is_err());
}
#[test]
fn signature_lax_der() {
macro_rules! check_lax_sig(