diff --git a/Cargo.toml b/Cargo.toml index e5dfa4378..e82d0b710 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,6 @@ features = [ "rand", "serde" ] all-features = true -[dependencies] -arrayvec = { version = "0.4.10", default-features = false } - [build-dependencies] cc = "=1.0.26" diff --git a/src/lib.rs b/src/lib.rs index 442d66919..a824baa95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -143,9 +143,6 @@ #[cfg(any(test, feature = "rand"))] use rand::Rng; #[cfg(any(test, feature = "std"))] extern crate core; -extern crate arrayvec; - -use arrayvec::ArrayVec; use core::{fmt, ptr, str}; #[macro_use] @@ -338,10 +335,11 @@ impl Signature { &mut self.0 as *mut _ } + #[cfg(feature = "std")] #[inline] /// Serializes the signature in DER format - pub fn serialize_der(&self) -> ArrayVec<[u8; 72]> { - let mut ret = ArrayVec::<[_; 72]>::new(); + pub fn serialize_der(&self) -> Vec{ + let mut ret = Vec::with_capacity(72); let mut len: usize = ret.capacity() as usize; unsafe { let err = ffi::secp256k1_ecdsa_signature_serialize_der( @@ -351,12 +349,30 @@ impl Signature { self.as_ptr(), ); debug_assert!(err == 1); - // ret.set_len(len as usize); ret.set_len(len as usize); } ret } + #[inline] + /// Serializes the signature in DER format without allocating memory + /// The signature can be anywhere from 8 bytes to 72 bytes + /// So the function needs a buffer that is equal or larger than 72 bytes + /// It will write into that buffer and return a slice containing only the signature + pub fn serialize_der_no_alloc<'a>(&self, buf: &'a mut [u8]) -> &'a [u8] { + let mut len: usize = buf.len(); + unsafe { + let err = ffi::secp256k1_ecdsa_signature_serialize_der( + ffi::secp256k1_context_no_precomp, + buf.as_mut_ptr(), + &mut len, + self.as_ptr(), + ); + debug_assert!(err == 1); + } + &buf[..len] + } + #[inline] /// Serializes the signature in compact format pub fn serialize_compact(&self) -> [u8; 64] { @@ -458,7 +474,8 @@ impl From for RecoverableSignature { #[cfg(feature = "serde")] impl ::serde::Serialize for Signature { fn serialize(&self, s: S) -> Result { - s.serialize_bytes(&self.serialize_der()) + let mut buf = [0u8; 72]; + s.serialize_bytes(&self.serialize_der_no_alloc(&mut buf)) } } @@ -915,6 +932,34 @@ mod tests { } } + #[test] + fn signature_serialize_no_alloc_roundtrip() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); + + let mut msg = [0; 32]; + for _ in 0..100 { + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + + let (sk, _) = s.generate_keypair(&mut thread_rng()); + let sig1 = s.sign(&msg, &sk); + let mut buf = vec![0u8; 172]; + let der = sig1.serialize_der_no_alloc(&mut buf); + let sig2 = Signature::from_der(&der[..]).unwrap(); + assert_eq!(sig1, sig2); + + let compact = sig1.serialize_compact(); + let sig2 = Signature::from_compact(&compact[..]).unwrap(); + assert_eq!(sig1, sig2); + + assert!(Signature::from_compact(&der[..]).is_err()); + assert!(Signature::from_compact(&compact[0..4]).is_err()); + assert!(Signature::from_der(&compact[..]).is_err()); + assert!(Signature::from_der(&der[0..4]).is_err()); + } + } + #[test] fn signature_display() { let hex_str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45";