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"
libc = "0.1"
rustc-serialize = "0.3"
serde = "0.6"
serde_json = "0.6"
serde = "~1.0.8"
serde_json = "~1.0.2"

View file

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

View file

@ -106,8 +106,7 @@ impl Signature {
if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx,
&mut ret,
data.as_ptr(),
data.len() as libc::size_t) ==
1 {
data.len() as libc::size_t) == 1 {
Ok(Signature(ret))
} else {
Err(Error::InvalidSignature)
@ -115,8 +114,10 @@ impl Signature {
}
}
/// Converts a "lax DER"-encoded byte slice to a signature. This is basically
/// only useful for validating signatures in the Bitcoin blockchain from before
/// Converts a "lax DER"-encoded byte slice to a signature. This is
/// 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
/// support serializing to this "format"
pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result<Signature, Error> {
@ -244,7 +245,8 @@ impl RecoverableSignature {
(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
#[inline]
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 {
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
/// batch key generation. Requires a signing-capable context.
#[inline]
@ -505,7 +509,8 @@ impl Secp256k1 {
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.
pub fn sign(&self, msg: &Message, sk: &key::SecretKey) -> Result<Signature, Error> {
if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None {
@ -527,7 +532,8 @@ impl Secp256k1 {
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.
pub fn sign_recoverable(&self,
msg: &Message,
@ -569,9 +575,11 @@ impl Secp256k1 {
}
/// 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
/// 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.
#[inline]
pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> {

View file

@ -20,25 +20,25 @@ macro_rules! impl_array_newtype {
impl $thing {
#[inline]
/// Converts the object to a raw pointer for FFI interfacing
/// Converts the object to a raw pointer for FFI interfacing
pub fn as_ptr(&self) -> *const $ty {
let &$thing(ref dat) = self;
dat.as_ptr()
}
#[inline]
/// Converts the object to a mutable raw pointer for FFI interfacing
/// Converts the object to a mutable raw pointer for FFI interfacing
pub fn as_mut_ptr(&mut self) -> *mut $ty {
let &mut $thing(ref mut dat) = self;
dat.as_mut_ptr()
}
#[inline]
/// Returns the length of the object as an array
/// Returns the length of the object as an array
pub fn len(&self) -> usize { $len }
#[inline]
/// Returns whether the object as an array is empty
/// Returns whether the object as an array is empty
pub fn is_empty(&self) -> bool { false }
}
@ -125,9 +125,9 @@ macro_rules! impl_array_newtype {
impl ::std::hash::Hash for $thing {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
state.write(&self.0)
// for n in 0..self.len() {
// state.write_u8(self.0[n]);
// }
// for n in 0..self.len() {
// state.write_u8(self.0[n]);
// }
}
}
@ -159,45 +159,48 @@ macro_rules! impl_array_newtype {
}
}
impl ::serde::Deserialize for $thing {
fn deserialize<D>(d: &mut D) -> Result<$thing, D::Error>
where D: ::serde::Deserializer
impl<'de> ::serde::Deserialize<'de> for $thing {
fn deserialize<D>(d: D) -> Result<$thing, D::Error>
where D: ::serde::Deserializer<'de>
{
// We have to define the Visitor struct inside the function
// to make it local ... all we really need is that it's
// local to the macro, but this works too :)
struct Visitor {
marker: ::std::marker::PhantomData<$thing>,
}
impl ::serde::de::Visitor for Visitor {
struct Visitor;
impl<'di> ::serde::de::Visitor<'di> for Visitor {
type Value = $thing;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
formatter.write_str("an array of bytes")
}
#[inline]
fn visit_seq<V>(&mut self, mut v: V) -> Result<$thing, V::Error>
where V: ::serde::de::SeqVisitor
fn visit_seq<V>(self, mut v: V) -> Result<$thing, V::Error>
where V: ::serde::de::SeqAccess<'di>
{
unsafe {
use std::mem;
let mut ret: [$ty; $len] = mem::uninitialized();
for i in 0..$len {
ret[i] = match try!(v.visit()) {
ret[i] = match try!(v.next_element()) {
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))
}
}
}
// 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 {
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
{
(&self.0[..]).serialize(s)

View file

@ -15,6 +15,8 @@
//! # Pedersen commitments and related range proofs
use std::cmp::min;
use std::fmt;
use std::mem;
use ContextFlag;
@ -26,6 +28,7 @@ use ffi;
use key;
use key::SecretKey;
use rand::{Rng, OsRng};
use serde::{ser, de};
/// A Pedersen commitment
pub struct Commitment(pub [u8; constants::PEDERSEN_COMMITMENT_SIZE]);
@ -34,6 +37,15 @@ impl_pretty_debug!(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
unsafe fn blank() -> Commitment {
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 {
fn as_ref(&self) -> &[u8] {
&self.proof[..self.plen as usize]
@ -84,6 +143,12 @@ impl AsRef<[u8]> for RangeProof {
}
impl RangeProof {
pub fn zero() -> RangeProof {
RangeProof {
proof: [0; constants::MAX_PROOF_SIZE],
plen: 0,
}
}
/// The range proof as a byte slice.
pub fn bytes(&self) -> &[u8] {
&self.proof[..self.plen as usize]
@ -146,7 +211,8 @@ impl Secp256k1 {
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> {
if self.caps != ContextFlag::Commit {
@ -223,7 +289,8 @@ impl Secp256k1 {
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.
pub fn range_proof(&self,
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,
commit: Commitment,
proof: RangeProof,