Merge pull request #38 from rust-bitcoin/2018-08-serde
add feature-gated serde 1.0 support for Signature, SecretKey, PublicKey
This commit is contained in:
commit
ad080da1d8
|
@ -10,6 +10,7 @@ script:
|
||||||
- cargo build --verbose --features=fuzztarget
|
- cargo build --verbose --features=fuzztarget
|
||||||
- cargo build --verbose --features=rand
|
- cargo build --verbose --features=rand
|
||||||
- cargo test --verbose --features=rand
|
- cargo test --verbose --features=rand
|
||||||
|
- cargo test --verbose --features="rand serde"
|
||||||
- cargo build --verbose
|
- cargo build --verbose
|
||||||
- cargo test --verbose
|
- cargo test --verbose
|
||||||
- cargo build --release
|
- cargo build --release
|
||||||
|
|
|
@ -27,6 +27,7 @@ fuzztarget = []
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.3"
|
rand = "0.3"
|
||||||
|
serde_test = "1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
@ -34,3 +35,7 @@ libc = "0.2"
|
||||||
[dependencies.rand]
|
[dependencies.rand]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.serde]
|
||||||
|
version = "1.0"
|
||||||
|
optional = true
|
||||||
|
|
70
src/key.rs
70
src/key.rs
|
@ -121,6 +121,31 @@ impl SecretKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl ::serde::Serialize for SecretKey {
|
||||||
|
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
|
s.serialize_bytes(&self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de> ::serde::Deserialize<'de> for SecretKey {
|
||||||
|
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<SecretKey, D::Error> {
|
||||||
|
use ::serde::de::Error;
|
||||||
|
|
||||||
|
// serde can actually deserialize a 32-byte array directly rather than deserializing
|
||||||
|
// a byte slice and copying, but it has special code for byte-slices and no special
|
||||||
|
// code for byte-arrays, meaning this is actually simpler and more efficient
|
||||||
|
let mut arr = [0; 32];
|
||||||
|
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
|
||||||
|
if sl.len() != constants::SECRET_KEY_SIZE {
|
||||||
|
return Err(D::Error::invalid_length(sl.len(), &"32"));
|
||||||
|
}
|
||||||
|
arr.copy_from_slice(sl);
|
||||||
|
Ok(SecretKey(arr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PublicKey {
|
impl PublicKey {
|
||||||
/// Obtains a raw pointer suitable for use with FFI functions
|
/// Obtains a raw pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -254,6 +279,24 @@ impl From<ffi::PublicKey> for PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl ::serde::Serialize for PublicKey {
|
||||||
|
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
|
s.serialize_bytes(&self.serialize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de> ::serde::Deserialize<'de> for PublicKey {
|
||||||
|
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
|
||||||
|
use ::serde::de::Error;
|
||||||
|
|
||||||
|
let secp = Secp256k1::without_caps();
|
||||||
|
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
|
||||||
|
PublicKey::from_slice(&secp, sl).map_err(D::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::super::{Secp256k1};
|
use super::super::{Secp256k1};
|
||||||
|
@ -529,6 +572,33 @@ mod test {
|
||||||
assert!(pk3 <= pk1);
|
assert!(pk3 <= pk1);
|
||||||
assert!(pk1 >= pk3);
|
assert!(pk1 >= pk3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
#[test]
|
||||||
|
fn test_signature_serde() {
|
||||||
|
use serde_test::{Token, assert_tokens};
|
||||||
|
static SK_BYTES: [u8; 32] = [
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
0xff, 0xff, 0, 0, 0xff, 0xff, 0, 0,
|
||||||
|
99, 99, 99, 99, 99, 99, 99, 99
|
||||||
|
];
|
||||||
|
static PK_BYTES: [u8; 33] = [
|
||||||
|
0x02,
|
||||||
|
0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f,
|
||||||
|
0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d,
|
||||||
|
0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54,
|
||||||
|
0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66,
|
||||||
|
];
|
||||||
|
|
||||||
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
|
let sk = SecretKey::from_slice(&s, &SK_BYTES).unwrap();
|
||||||
|
let pk = PublicKey::from_secret_key(&s, &sk);
|
||||||
|
|
||||||
|
assert_tokens(&sk, &[Token::BorrowedBytes(&SK_BYTES[..])]);
|
||||||
|
assert_tokens(&pk, &[Token::BorrowedBytes(&PK_BYTES[..])]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
42
src/lib.rs
42
src/lib.rs
|
@ -39,6 +39,8 @@
|
||||||
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
|
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
|
||||||
#[cfg(all(test, feature = "unstable"))] extern crate test;
|
#[cfg(all(test, feature = "unstable"))] extern crate test;
|
||||||
#[cfg(any(test, feature = "rand"))] extern crate rand;
|
#[cfg(any(test, feature = "rand"))] extern crate rand;
|
||||||
|
#[cfg(feature = "serde")] extern crate serde;
|
||||||
|
#[cfg(all(test, feature = "serde"))] extern crate serde_test;
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
|
@ -305,6 +307,25 @@ impl ops::Index<ops::RangeFull> for Signature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl ::serde::Serialize for Signature {
|
||||||
|
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
|
let secp = Secp256k1::without_caps();
|
||||||
|
s.serialize_bytes(&self.serialize_der(&secp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de> ::serde::Deserialize<'de> for Signature {
|
||||||
|
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Signature, D::Error> {
|
||||||
|
use ::serde::de::Error;
|
||||||
|
|
||||||
|
let secp = Secp256k1::without_caps();
|
||||||
|
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
|
||||||
|
Signature::from_der(&secp, sl).map_err(D::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A (hashed) message input to an ECDSA signature
|
/// A (hashed) message input to an ECDSA signature
|
||||||
pub struct Message([u8; constants::MESSAGE_SIZE]);
|
pub struct Message([u8; constants::MESSAGE_SIZE]);
|
||||||
impl_array_newtype!(Message, u8, constants::MESSAGE_SIZE);
|
impl_array_newtype!(Message, u8, constants::MESSAGE_SIZE);
|
||||||
|
@ -903,6 +924,27 @@ mod tests {
|
||||||
sig.normalize_s(&secp);
|
sig.normalize_s(&secp);
|
||||||
assert_eq!(secp.verify(&msg, &sig, &pk), Ok(()));
|
assert_eq!(secp.verify(&msg, &sig, &pk), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
#[test]
|
||||||
|
fn test_signature_serde() {
|
||||||
|
use serde_test::{Token, assert_tokens};
|
||||||
|
|
||||||
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
|
let msg = Message::from_slice(&[1; 32]).unwrap();
|
||||||
|
let sk = SecretKey::from_slice(&s, &[2; 32]).unwrap();
|
||||||
|
let sig = s.sign(&msg, &sk);
|
||||||
|
static SIG_BYTES: [u8; 71] = [
|
||||||
|
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237,
|
||||||
|
179, 76, 119, 72, 102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148,
|
||||||
|
8, 230, 206, 119, 75, 2, 32, 40, 118, 231, 16, 47, 32, 79, 107, 254,
|
||||||
|
226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125, 75, 1, 0, 98, 225,
|
||||||
|
147, 247, 99, 25, 15, 103, 118
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_tokens(&sig, &[Token::BorrowedBytes(&SIG_BYTES[..])]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(test, feature = "unstable"))]
|
#[cfg(all(test, feature = "unstable"))]
|
||||||
|
|
Loading…
Reference in New Issue