Update secp256k1zlp to serde 1.0

This commit is contained in:
Ignotus Peverell 2017-05-28 20:20:56 -07:00
parent 1ae2e905d8
commit da41120293
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211
8 changed files with 2067 additions and 1999 deletions

View file

@ -29,6 +29,5 @@ clippy = {version = "0.0", optional = true}
rand = "0.3" rand = "0.3"
libc = "0.1" libc = "0.1"
rustc-serialize = "0.3" rustc-serialize = "0.3"
serde = "0.6" serde = "~1.0.8"
serde_json = "0.6" serde_json = "~1.0.2"

View file

@ -15,6 +15,7 @@
//! # Public and secret keys //! # Public and secret keys
use std::fmt;
use std::intrinsics::copy_nonoverlapping; use std::intrinsics::copy_nonoverlapping;
use std::marker; use std::marker;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
@ -278,20 +279,24 @@ impl Encodable for PublicKey {
} }
} }
impl Deserialize for PublicKey { impl<'de> Deserialize<'de> for PublicKey {
fn deserialize<D>(d: &mut D) -> Result<PublicKey, D::Error> fn deserialize<D>(d: D) -> Result<PublicKey, D::Error>
where D: Deserializer where D: Deserializer<'de>
{ {
use serde::de; use serde::de;
struct Visitor { struct Visitor {
marker: marker::PhantomData<PublicKey>, marker: marker::PhantomData<PublicKey>,
} }
impl de::Visitor for Visitor { impl<'di> de::Visitor<'di> for Visitor {
type Value = PublicKey; type Value = PublicKey;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an array of bytes")
}
#[inline] #[inline]
fn visit_seq<V>(&mut self, mut v: V) -> Result<PublicKey, V::Error> fn visit_seq<V>(self, mut v: V) -> Result<PublicKey, V::Error>
where V: de::SeqVisitor where V: ::serde::de::SeqAccess<'di>
{ {
debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >= debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >=
constants::COMPRESSED_PUBLIC_KEY_SIZE); constants::COMPRESSED_PUBLIC_KEY_SIZE);
@ -304,28 +309,27 @@ impl Deserialize for PublicKey {
let mut read_len = 0; let mut read_len = 0;
while read_len < constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { while read_len < constants::UNCOMPRESSED_PUBLIC_KEY_SIZE {
let read_ch = match try!(v.visit()) { let read_ch = match try!(v.next_element()) {
Some(c) => c, Some(c) => c,
None => break, None => break,
}; };
ret[read_len] = read_ch; ret[read_len] = read_ch;
read_len += 1; read_len += 1;
} }
try!(v.end());
PublicKey::from_slice(&s, &ret[..read_len]) PublicKey::from_slice(&s, &ret[..read_len])
.map_err(|e| de::Error::syntax(&e.to_string())) .map_err(|e| de::Error::custom(&e.to_string()))
} }
} }
} }
// Begin actual function // Begin actual function
d.visit(Visitor { marker: ::std::marker::PhantomData }) d.deserialize_seq(Visitor { marker: ::std::marker::PhantomData })
} }
} }
impl Serialize for PublicKey { impl Serialize for PublicKey {
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error> fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where S: Serializer where S: Serializer
{ {
let secp = Secp256k1::with_caps(::ContextFlag::None); let secp = Secp256k1::with_caps(::ContextFlag::None);
@ -339,6 +343,7 @@ mod test {
use super::super::Error::{InvalidPublicKey, InvalidSecretKey, IncapableContext}; use super::super::Error::{InvalidPublicKey, InvalidSecretKey, IncapableContext};
use super::{PublicKey, SecretKey}; use super::{PublicKey, SecretKey};
use super::super::constants; use super::super::constants;
extern crate serde_json;
use rand::{Rng, thread_rng}; use rand::{Rng, thread_rng};
@ -515,33 +520,24 @@ mod test {
use json; use json;
// Invalid length // Invalid length
let zero31 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]".as_bytes(); let zero31 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]";
let mut json = json::de::Deserializer::new(zero31.iter().map(|c| Ok(*c))); assert!(serde_json::from_str::<PublicKey>(zero31).is_err());
assert!(<PublicKey as Deserialize>::deserialize(&mut json).is_err()); assert!(serde_json::from_str::<SecretKey>(zero31).is_err());
let mut json = json::de::Deserializer::new(zero31.iter().map(|c| Ok(*c)));
assert!(<SecretKey as Deserialize>::deserialize(&mut json).is_err());
let zero32 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]".as_bytes(); let zero32 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]";
let mut json = json::de::Deserializer::new(zero32.iter().map(|c| Ok(*c))); assert!(serde_json::from_str::<PublicKey>(zero32).is_err());
assert!(<PublicKey as Deserialize>::deserialize(&mut json).is_err()); assert!(serde_json::from_str::<SecretKey>(zero32).is_ok());
let mut json = json::de::Deserializer::new(zero32.iter().map(|c| Ok(*c)));
assert!(<SecretKey as Deserialize>::deserialize(&mut json).is_ok());
// All zeroes pk is invalid // All zeroes pk is invalid
let zero65 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\ let zero65 = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]" 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]";
.as_bytes(); assert!(serde_json::from_str::<PublicKey>(zero31).is_err());
let mut json = json::de::Deserializer::new(zero65.iter().map(|c| Ok(*c))); assert!(serde_json::from_str::<SecretKey>(zero31).is_err());
assert!(<PublicKey as Deserialize>::deserialize(&mut json).is_err());
let mut json = json::de::Deserializer::new(zero65.iter().map(|c| Ok(*c)));
assert!(<SecretKey as Deserialize>::deserialize(&mut json).is_err());
// Syntax error // Syntax error
let string = "\"my key\"".as_bytes(); let string = "\"my key\"";
let mut json = json::de::Deserializer::new(string.iter().map(|c| Ok(*c))); assert!(serde_json::from_str::<PublicKey>(zero31).is_err());
assert!(<PublicKey as Deserialize>::deserialize(&mut json).is_err()); assert!(serde_json::from_str::<SecretKey>(zero31).is_err());
let mut json = json::de::Deserializer::new(string.iter().map(|c| Ok(*c)));
assert!(<SecretKey as Deserialize>::deserialize(&mut json).is_err());
} }
@ -551,24 +547,18 @@ mod test {
use json; use json;
macro_rules! round_trip ( macro_rules! round_trip (
($var:ident) => ({ ($e:ident, $d:ty) => {
let start = $var; let json = serde_json::to_string(&$e).unwrap();
let mut encoded = Vec::new(); assert!(json.len() > 0);
{ assert!(serde_json::from_str::<$d>(json.as_str()).is_ok());
let mut serializer = json::ser::Serializer::new(&mut encoded);
start.serialize(&mut serializer).unwrap();
} }
let mut deserializer = json::de::Deserializer::new(encoded.iter().map(|c| Ok(*c)));
let decoded = Deserialize::deserialize(&mut deserializer);
assert_eq!(Some(start), decoded.ok());
})
); );
let s = Secp256k1::new(); let s = Secp256k1::new();
for _ in 0..500 { for _ in 0..500 {
let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap();
round_trip!(sk); // round_trip!(sk, SecretKey);
round_trip!(pk); round_trip!(pk, PublicKey);
} }
} }

View file

@ -106,8 +106,7 @@ impl Signature {
if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx, if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx,
&mut ret, &mut ret,
data.as_ptr(), data.as_ptr(),
data.len() as libc::size_t) == data.len() as libc::size_t) == 1 {
1 {
Ok(Signature(ret)) Ok(Signature(ret))
} else { } else {
Err(Error::InvalidSignature) Err(Error::InvalidSignature)
@ -115,8 +114,10 @@ impl Signature {
} }
} }
/// Converts a "lax DER"-encoded byte slice to a signature. This is basically /// Converts a "lax DER"-encoded byte slice to a signature. This is
/// only useful for validating signatures in the Bitcoin blockchain from before /// basically
/// only useful for validating signatures in the Bitcoin blockchain from
/// before
/// 2016. It should never be used in new applications. This library does not /// 2016. It should never be used in new applications. This library does not
/// support serializing to this "format" /// support serializing to this "format"
pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result<Signature, Error> { pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result<Signature, Error> {
@ -244,7 +245,8 @@ impl RecoverableSignature {
(RecoveryId(recid), ret) (RecoveryId(recid), ret)
} }
/// Converts a recoverable signature to a non-recoverable one (this is needed /// Converts a recoverable signature to a non-recoverable one (this is
/// needed
/// for verification /// for verification
#[inline] #[inline]
pub fn to_standard(&self, secp: &Secp256k1) -> Signature { pub fn to_standard(&self, secp: &Secp256k1) -> Signature {
@ -469,7 +471,8 @@ impl Secp256k1 {
} }
} }
/// Creates a new Secp256k1 context with no capabilities (just de/serialization) /// Creates a new Secp256k1 context with no capabilities (just
/// de/serialization)
pub fn without_caps() -> Secp256k1 { pub fn without_caps() -> Secp256k1 {
Secp256k1::with_caps(ContextFlag::None) Secp256k1::with_caps(ContextFlag::None)
} }
@ -493,7 +496,8 @@ impl Secp256k1 {
} }
} }
/// Generates a random keypair. Convenience function for `key::SecretKey::new` /// Generates a random keypair. Convenience function for
/// `key::SecretKey::new`
/// and `key::PublicKey::from_secret_key`; call those functions directly for /// and `key::PublicKey::from_secret_key`; call those functions directly for
/// batch key generation. Requires a signing-capable context. /// batch key generation. Requires a signing-capable context.
#[inline] #[inline]
@ -505,7 +509,8 @@ impl Secp256k1 {
Ok((sk, pk)) Ok((sk, pk))
} }
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce /// Constructs a signature for `msg` using the secret key `sk` and RFC6979
/// nonce
/// Requires a signing-capable context. /// Requires a signing-capable context.
pub fn sign(&self, msg: &Message, sk: &key::SecretKey) -> Result<Signature, Error> { pub fn sign(&self, msg: &Message, sk: &key::SecretKey) -> Result<Signature, Error> {
if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None {
@ -527,7 +532,8 @@ impl Secp256k1 {
Ok(Signature::from(ret)) Ok(Signature::from(ret))
} }
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce /// Constructs a signature for `msg` using the secret key `sk` and RFC6979
/// nonce
/// Requires a signing-capable context. /// Requires a signing-capable context.
pub fn sign_recoverable(&self, pub fn sign_recoverable(&self,
msg: &Message, msg: &Message,
@ -569,9 +575,11 @@ impl Secp256k1 {
} }
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public /// Checks that `sig` is a valid ECDSA signature for `msg` using the public
/// key `pubkey`. Returns `Ok(true)` on success. Note that this function cannot /// key `pubkey`. Returns `Ok(true)` on success. Note that this function
/// cannot
/// be used for Bitcoin consensus checking since there may exist signatures /// be used for Bitcoin consensus checking since there may exist signatures
/// which OpenSSL would verify but not libsecp256k1, or vice-versa. Requires a /// which OpenSSL would verify but not libsecp256k1, or vice-versa.
/// Requires a
/// verify-capable context. /// verify-capable context.
#[inline] #[inline]
pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> { pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> {

View file

@ -159,45 +159,48 @@ macro_rules! impl_array_newtype {
} }
} }
impl ::serde::Deserialize for $thing { impl<'de> ::serde::Deserialize<'de> for $thing {
fn deserialize<D>(d: &mut D) -> Result<$thing, D::Error> fn deserialize<D>(d: D) -> Result<$thing, D::Error>
where D: ::serde::Deserializer where D: ::serde::Deserializer<'de>
{ {
// We have to define the Visitor struct inside the function // We have to define the Visitor struct inside the function
// to make it local ... all we really need is that it's // to make it local ... all we really need is that it's
// local to the macro, but this works too :) // local to the macro, but this works too :)
struct Visitor { struct Visitor;
marker: ::std::marker::PhantomData<$thing>,
} impl<'di> ::serde::de::Visitor<'di> for Visitor {
impl ::serde::de::Visitor for Visitor {
type Value = $thing; type Value = $thing;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
formatter.write_str("an array of bytes")
}
#[inline] #[inline]
fn visit_seq<V>(&mut self, mut v: V) -> Result<$thing, V::Error> fn visit_seq<V>(self, mut v: V) -> Result<$thing, V::Error>
where V: ::serde::de::SeqVisitor where V: ::serde::de::SeqAccess<'di>
{ {
unsafe { unsafe {
use std::mem; use std::mem;
let mut ret: [$ty; $len] = mem::uninitialized(); let mut ret: [$ty; $len] = mem::uninitialized();
for i in 0..$len { for i in 0..$len {
ret[i] = match try!(v.visit()) { ret[i] = match try!(v.next_element()) {
Some(c) => c, Some(c) => c,
None => return Err(::serde::de::Error::end_of_stream()) None => return Err(::serde::de::Error::invalid_length(i, &self))
}; };
} }
try!(v.end());
Ok($thing(ret)) Ok($thing(ret))
} }
} }
} }
// Begin actual function // Begin actual function
d.visit(Visitor { marker: ::std::marker::PhantomData }) // d.visit(Visitor { marker: ::std::marker::PhantomData })
d.deserialize_seq(Visitor)
} }
} }
impl ::serde::Serialize for $thing { impl ::serde::Serialize for $thing {
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error> fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where S: ::serde::Serializer where S: ::serde::Serializer
{ {
(&self.0[..]).serialize(s) (&self.0[..]).serialize(s)

View file

@ -15,6 +15,8 @@
//! # Pedersen commitments and related range proofs //! # Pedersen commitments and related range proofs
use std::cmp::min;
use std::fmt;
use std::mem; use std::mem;
use ContextFlag; use ContextFlag;
@ -26,6 +28,7 @@ use ffi;
use key; use key;
use key::SecretKey; use key::SecretKey;
use rand::{Rng, OsRng}; use rand::{Rng, OsRng};
use serde::{ser, de};
/// A Pedersen commitment /// A Pedersen commitment
pub struct Commitment(pub [u8; constants::PEDERSEN_COMMITMENT_SIZE]); pub struct Commitment(pub [u8; constants::PEDERSEN_COMMITMENT_SIZE]);
@ -34,6 +37,15 @@ impl_pretty_debug!(Commitment);
impl Commitment { impl Commitment {
/// Builds a Hash from a byte vector. If the vector is too short, it will be
/// completed by zeroes. If it's too long, it will be truncated.
pub fn from_vec(v: Vec<u8>) -> Commitment {
let mut h = [0; constants::PEDERSEN_COMMITMENT_SIZE];
for i in 0..min(v.len(), constants::PEDERSEN_COMMITMENT_SIZE) {
h[i] = v[i];
}
Commitment(h)
}
/// Uninitialized commitment, use with caution /// Uninitialized commitment, use with caution
unsafe fn blank() -> Commitment { unsafe fn blank() -> Commitment {
mem::uninitialized() mem::uninitialized()
@ -77,6 +89,53 @@ impl Clone for RangeProof {
} }
} }
impl ser::Serialize for RangeProof {
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
(&self.proof[..self.plen]).serialize(s)
}
}
struct Visitor;
impl<'di> de::Visitor<'di> for Visitor {
type Value = RangeProof;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an array of bytes")
}
#[inline]
fn visit_seq<V>(self, mut v: V) -> Result<RangeProof, V::Error>
where V: de::SeqAccess<'di>
{
unsafe {
use std::mem;
let mut ret: [u8; constants::MAX_PROOF_SIZE] = mem::uninitialized();
let mut i = 0;
while let Some(val) = v.next_element()? {
ret[i] = val;
i += 1;
}
Ok(RangeProof {
proof: ret,
plen: i,
})
}
}
}
impl<'de> de::Deserialize<'de> for RangeProof {
fn deserialize<D>(d: D) -> Result<RangeProof, D::Error>
where D: de::Deserializer<'de>
{
// Begin actual function
d.deserialize_seq(Visitor)
}
}
impl AsRef<[u8]> for RangeProof { impl AsRef<[u8]> for RangeProof {
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] {
&self.proof[..self.plen as usize] &self.proof[..self.plen as usize]
@ -84,6 +143,12 @@ impl AsRef<[u8]> for RangeProof {
} }
impl RangeProof { impl RangeProof {
pub fn zero() -> RangeProof {
RangeProof {
proof: [0; constants::MAX_PROOF_SIZE],
plen: 0,
}
}
/// The range proof as a byte slice. /// The range proof as a byte slice.
pub fn bytes(&self) -> &[u8] { pub fn bytes(&self) -> &[u8] {
&self.proof[..self.plen as usize] &self.proof[..self.plen as usize]
@ -146,7 +211,8 @@ impl Secp256k1 {
Ok(Commitment(commit)) Ok(Commitment(commit))
} }
/// Convenience method to Create a pedersen commitment only from a value, with a zero blinding factor /// Convenience method to Create a pedersen commitment only from a value,
/// with a zero blinding factor
pub fn commit_value(&self, value: u64) -> Result<Commitment, Error> { pub fn commit_value(&self, value: u64) -> Result<Commitment, Error> {
if self.caps != ContextFlag::Commit { if self.caps != ContextFlag::Commit {
@ -223,7 +289,8 @@ impl Secp256k1 {
SecretKey::from_slice(self, &ret) SecretKey::from_slice(self, &ret)
} }
/// Produces a range proof for the provided value, using min and max bounds, relying /// Produces a range proof for the provided value, using min and max
/// bounds, relying
/// on the blinding factor and commitment. /// on the blinding factor and commitment.
pub fn range_proof(&self, pub fn range_proof(&self,
min: u64, min: u64,
@ -293,7 +360,8 @@ impl Secp256k1 {
} }
} }
/// Verify a range proof proof and rewind the proof to recover information sent by its author. /// Verify a range proof proof and rewind the proof to recover information
/// sent by its author.
pub fn rewind_range_proof(&self, pub fn rewind_range_proof(&self,
commit: Commitment, commit: Commitment,
proof: RangeProof, proof: RangeProof,