diff --git a/chain/src/types.rs b/chain/src/types.rs index e5e3acd1e..3b017b3fe 100644 --- a/chain/src/types.rs +++ b/chain/src/types.rs @@ -60,7 +60,7 @@ impl Tip { /// Serialization of a tip, required to save to datastore. impl ser::Writeable for Tip { - fn write(&self, writer: &mut ser::Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { try!(writer.write_u64(self.height)); try!(writer.write_fixed_bytes(&self.last_block_h)); try!(writer.write_fixed_bytes(&self.prev_block_h)); diff --git a/core/src/core/block.rs b/core/src/core/block.rs index 2912f2d19..9b8631ab5 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -80,7 +80,7 @@ impl Default for BlockHeader { /// Serialization of a block header impl Writeable for BlockHeader { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u64, self.height], [write_fixed_bytes, &self.previous], @@ -148,7 +148,7 @@ pub struct Block { /// binary writer. Differentiates between writing the block for the purpose of /// full serialization and the one of just extracting a hash. impl Writeable for Block { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { try!(self.header.write(writer)); if writer.serialization_mode() != ser::SerializationMode::Hash { diff --git a/core/src/core/hash.rs b/core/src/core/hash.rs index 410ddbf76..7bff30a54 100644 --- a/core/src/core/hash.rs +++ b/core/src/core/hash.rs @@ -20,8 +20,9 @@ use byteorder::{ByteOrder, BigEndian}; use std::fmt; use tiny_keccak::Keccak; +use std::convert::AsRef; -use ser::{self, AsFixedBytes, Reader, Readable, Writer, Writeable, Error}; +use ser::{self, Reader, Readable, Writer, Writeable, Error, AsFixedBytes}; pub const ZERO_HASH: Hash = Hash([0; 32]); @@ -50,6 +51,12 @@ impl Hash { } } +impl AsRef<[u8]> for Hash { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + impl Readable for Hash { fn read(reader: &mut Reader) -> Result { let v = try!(reader.read_fixed_bytes(32)); @@ -62,7 +69,7 @@ impl Readable for Hash { } impl Writeable for Hash { - fn write(&self, writer: &mut Writer) -> Result<(), Error> { + fn write(&self, writer: &mut W) -> Result<(), Error> { writer.write_fixed_bytes(&self.0) } } @@ -89,8 +96,8 @@ impl ser::Writer for HashWriter { ser::SerializationMode::Hash } - fn write_fixed_bytes(&mut self, b32: &AsFixedBytes) -> Result<(), ser::Error> { - self.state.update(b32.as_fixed_bytes()); + fn write_fixed_bytes(&mut self, b32: &T) -> Result<(), ser::Error> { + self.state.update(b32.as_ref()); Ok(()) } } diff --git a/core/src/core/mod.rs b/core/src/core/mod.rs index b1f0fcccc..8c861011b 100644 --- a/core/src/core/mod.rs +++ b/core/src/core/mod.rs @@ -149,7 +149,7 @@ impl Readable for Proof { } impl Writeable for Proof { - fn write(&self, writer: &mut Writer) -> Result<(), Error> { + fn write(&self, writer: &mut W) -> Result<(), Error> { for n in 0..PROOFSIZE { try!(writer.write_u32(self.0[n])); } @@ -162,9 +162,9 @@ impl Writeable for Proof { struct HPair(Hash, Hash); impl Writeable for HPair { - fn write(&self, writer: &mut Writer) -> Result<(), Error> { - try!(writer.write_bytes(&self.0.to_slice())); - try!(writer.write_bytes(&self.1.to_slice())); + fn write(&self, writer: &mut W) -> Result<(), Error> { + try!(writer.write_bytes(&self.0)); + try!(writer.write_bytes(&self.1)); Ok(()) } } diff --git a/core/src/core/target.rs b/core/src/core/target.rs index c1d5f2ba5..d697f38f5 100644 --- a/core/src/core/target.rs +++ b/core/src/core/target.rs @@ -67,7 +67,7 @@ impl Add for Difficulty { } impl Writeable for Difficulty { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { let data = self.num.to_bytes_be(); try!(writer.write_u8(data.len() as u8)); writer.write_fixed_bytes(&data) diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 90b184b6b..f3e9809e0 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -52,7 +52,7 @@ pub struct TxKernel { } impl Writeable for TxKernel { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u8, self.features.bits()], [write_fixed_bytes, &self.excess], @@ -103,7 +103,7 @@ pub struct Transaction { /// Implementation of Writeable for a fully blinded transaction, defines how to /// write the transaction as binary. impl Writeable for Transaction { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u64, self.fee], [write_bytes, &self.excess_sig], @@ -251,7 +251,7 @@ pub struct Input(pub Commitment); /// Implementation of Writeable for a transaction Input, defines how to write /// an Input as binary. impl Writeable for Input { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { writer.write_fixed_bytes(&self.0) } } @@ -295,11 +295,11 @@ pub struct Output { /// Implementation of Writeable for a transaction Output, defines how to write /// an Output as binary. impl Writeable for Output { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u8, self.features.bits()], [write_fixed_bytes, &self.commit]); // The hash of an output doesn't include the range proof if writer.serialization_mode() == ser::SerializationMode::Full { - writer.write_bytes(&self.proof.bytes())? + writer.write_bytes(&self.proof)? } Ok(()) } diff --git a/core/src/ser.rs b/core/src/ser.rs index f3ad6a0b6..f50e6776f 100644 --- a/core/src/ser.rs +++ b/core/src/ser.rs @@ -80,14 +80,6 @@ impl error::Error for Error { } } -/// Useful trait to implement on types that can be translated to byte slices -/// directly. Allows the use of `write_fixed_bytes` on them. -pub trait AsFixedBytes { - /// The slice representation of self - fn as_fixed_bytes(&self) -> &[u8]; -} - - /// Signal to a serializable object how much of its data should be serialized #[derive(Copy, Clone, PartialEq, Eq)] pub enum SerializationMode { @@ -140,14 +132,14 @@ pub trait Writer { /// Writes a variable number of bytes. The length is encoded as a 64-bit /// prefix. - fn write_bytes(&mut self, bytes: &AsFixedBytes) -> Result<(), Error> { - try!(self.write_u64(bytes.as_fixed_bytes().len() as u64)); + fn write_bytes(&mut self, bytes: &T) -> Result<(), Error> { + try!(self.write_u64(bytes.as_ref().len() as u64)); self.write_fixed_bytes(bytes) } /// Writes a fixed number of bytes from something that can turn itself into /// a `&[u8]`. The reader is expected to know the actual length on read. - fn write_fixed_bytes(&mut self, fixed: &AsFixedBytes) -> Result<(), Error>; + fn write_fixed_bytes(&mut self, fixed: &T) -> Result<(), Error>; } /// Implementations defined how different numbers and binary structures are @@ -179,7 +171,7 @@ pub trait Reader { /// underlying Write implementation. pub trait Writeable { /// Write the data held by this Writeable to the provided writer - fn write(&self, writer: &mut Writer) -> Result<(), Error>; + fn write(&self, writer: &mut W) -> Result<(), Error>; } /// Trait that every type that can be deserialized from binary must implement. @@ -197,14 +189,14 @@ pub fn deserialize>(mut source: &mut Read) -> Result { } /// Serializes a Writeable into any std::io::Write implementation. -pub fn serialize(mut sink: &mut Write, thing: &Writeable) -> Result<(), Error> { +pub fn serialize(mut sink: &mut Write, thing: &W) -> Result<(), Error> { let mut writer = BinWriter { sink: sink }; thing.write(&mut writer) } /// Utility function to serialize a writeable directly in memory using a /// Vec. -pub fn ser_vec(thing: &Writeable) -> Result, Error> { +pub fn ser_vec(thing: &W) -> Result, Error> { let mut vec = Vec::new(); try!(serialize(&mut vec, thing)); Ok(vec) @@ -302,53 +294,25 @@ impl<'a> Writer for BinWriter<'a> { SerializationMode::Full } - fn write_fixed_bytes(&mut self, fixed: &AsFixedBytes) -> Result<(), Error> { - let bs = fixed.as_fixed_bytes(); + fn write_fixed_bytes(&mut self, fixed: &T) -> Result<(), Error> { + let bs = fixed.as_ref(); try!(self.sink.write_all(bs)); Ok(()) } } -macro_rules! impl_slice_bytes { - ($byteable: ty) => { - impl AsFixedBytes for $byteable { - fn as_fixed_bytes(&self) -> &[u8] { - &self[..] - } - } - } -} +/// Useful marker trait on types that can be sized byte slices +pub trait AsFixedBytes: Sized + AsRef<[u8]> {} -impl_slice_bytes!(::secp::key::SecretKey); -impl_slice_bytes!(::secp::Signature); -impl_slice_bytes!(::secp::pedersen::Commitment); -impl_slice_bytes!(Vec); -impl_slice_bytes!([u8; 1]); -impl_slice_bytes!([u8; 2]); -impl_slice_bytes!([u8; 4]); -impl_slice_bytes!([u8; 8]); -impl_slice_bytes!([u8; 32]); - -impl<'a> AsFixedBytes for &'a [u8] { - fn as_fixed_bytes(&self) -> &[u8] { - *self - } -} - -impl<'a> AsFixedBytes for String { - fn as_fixed_bytes(&self) -> &[u8] { - self.as_bytes() - } -} - -impl AsFixedBytes for ::core::hash::Hash { - fn as_fixed_bytes(&self) -> &[u8] { - self.to_slice() - } -} - -impl AsFixedBytes for ::secp::pedersen::RangeProof { - fn as_fixed_bytes(&self) -> &[u8] { - &self.bytes() - } -} +impl AsFixedBytes for Vec {} +impl AsFixedBytes for [u8; 1] {} +impl AsFixedBytes for [u8; 2] {} +impl AsFixedBytes for [u8; 4] {} +impl AsFixedBytes for [u8; 8] {} +impl AsFixedBytes for [u8; 32] {} +impl AsFixedBytes for String {} +impl AsFixedBytes for ::core::hash::Hash {} +impl AsFixedBytes for ::secp::pedersen::RangeProof {} +impl AsFixedBytes for ::secp::key::SecretKey {} +impl AsFixedBytes for ::secp::Signature {} +impl AsFixedBytes for ::secp::pedersen::Commitment {} \ No newline at end of file diff --git a/p2p/src/conn.rs b/p2p/src/conn.rs index 119aca7c7..81737f9c0 100644 --- a/p2p/src/conn.rs +++ b/p2p/src/conn.rs @@ -202,7 +202,7 @@ impl Connection { /// Utility function to send any Writeable. Handles adding the header and /// serialization. - pub fn send_msg(&self, t: Type, body: &ser::Writeable) -> Result<(), Error> { + pub fn send_msg (&self, t: Type, body: &W) -> Result<(), Error> { let mut body_data = vec![]; try!(ser::serialize(&mut body_data, body)); @@ -282,10 +282,10 @@ impl TimeoutConnection { /// Sends a request and registers a timer on the provided message type and /// optionally the hash of the sent data. - pub fn send_request(&self, + pub fn send_request(&self, t: Type, rt: Type, - body: &ser::Writeable, + body: &W, expect_h: Option<(Hash)>) -> Result<(), Error> { let sent = try!(self.underlying.send_msg(t, body)); @@ -296,7 +296,7 @@ impl TimeoutConnection { } /// Same as Connection - pub fn send_msg(&self, t: Type, body: &ser::Writeable) -> Result<(), Error> { + pub fn send_msg(&self, t: Type, body: &W) -> Result<(), Error> { self.underlying.send_msg(t, body) } diff --git a/p2p/src/msg.rs b/p2p/src/msg.rs index d9859a075..4ed7956b4 100644 --- a/p2p/src/msg.rs +++ b/p2p/src/msg.rs @@ -147,7 +147,7 @@ impl MsgHeader { } impl Writeable for MsgHeader { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u8, self.magic[0]], [write_u8, self.magic[1]], @@ -197,7 +197,7 @@ pub struct Hand { } impl Writeable for Hand { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u32, self.version], [write_u32, self.capabilities.bits()], @@ -246,7 +246,7 @@ pub struct Shake { } impl Writeable for Shake { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u32, self.version], [write_u32, self.capabilities.bits()]); @@ -279,7 +279,7 @@ pub struct GetPeerAddrs { } impl Writeable for GetPeerAddrs { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { writer.write_u32(self.capabilities.bits()) } } @@ -299,7 +299,7 @@ pub struct PeerAddrs { } impl Writeable for PeerAddrs { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { try!(writer.write_u32(self.peers.len() as u32)); for p in &self.peers { p.write(writer); @@ -335,7 +335,7 @@ pub struct PeerError { } impl Writeable for PeerError { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { ser_multiwrite!(writer, [write_u32, self.code], [write_bytes, &self.message]); Ok(()) } @@ -358,7 +358,7 @@ impl Readable for PeerError { pub struct SockAddr(pub SocketAddr); impl Writeable for SockAddr { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { match self.0 { SocketAddr::V4(sav4) => { ser_multiwrite!(writer, @@ -413,7 +413,7 @@ pub struct Locator { } impl Writeable for Locator { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { writer.write_u8(self.hashes.len() as u8)?; for h in &self.hashes { h.write(writer)? @@ -439,7 +439,7 @@ pub struct Headers { } impl Writeable for Headers { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { writer.write_u16(self.headers.len() as u16)?; for h in &self.headers { h.write(writer)? @@ -464,7 +464,7 @@ impl Readable for Headers { pub struct Empty {} impl Writeable for Empty { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { Ok(()) } } diff --git a/p2p/src/protocol.rs b/p2p/src/protocol.rs index c6e9cc72d..1323cd6bb 100644 --- a/p2p/src/protocol.rs +++ b/p2p/src/protocol.rs @@ -106,14 +106,14 @@ impl Protocol for ProtocolV1 { } impl ProtocolV1 { - fn send_msg(&self, t: Type, body: &ser::Writeable) -> Result<(), Error> { + fn send_msg(&self, t: Type, body: &W) -> Result<(), Error> { self.conn.borrow().send_msg(t, body) } - fn send_request(&self, + fn send_request(&self, t: Type, rt: Type, - body: &ser::Writeable, + body: &W, expect_resp: Option) -> Result<(), Error> { self.conn.borrow().send_request(t, rt, body, expect_resp) diff --git a/p2p/src/store.rs b/p2p/src/store.rs index a87300825..eb443a694 100644 --- a/p2p/src/store.rs +++ b/p2p/src/store.rs @@ -50,7 +50,7 @@ pub struct PeerData { } impl Writeable for PeerData { - fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> { + fn write(&self, writer: &mut W) -> Result<(), ser::Error> { SockAddr(self.addr).write(writer)?; ser_multiwrite!(writer, [write_u32, self.capabilities.bits()], diff --git a/secp256k1zkp/src/key.rs b/secp256k1zkp/src/key.rs index 719219bb5..51d49121e 100644 --- a/secp256k1zkp/src/key.rs +++ b/secp256k1zkp/src/key.rs @@ -32,6 +32,7 @@ pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]); impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE); impl_pretty_debug!(SecretKey); + /// The number 1 encoded as a secret key /// Deprecated; `static` is not what I want; use `ONE_KEY` instead pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/secp256k1zkp/src/lib.rs b/secp256k1zkp/src/lib.rs index 031bd2274..29878fa29 100644 --- a/secp256k1zkp/src/lib.rs +++ b/secp256k1zkp/src/lib.rs @@ -69,6 +69,12 @@ pub struct RecoveryId(i32); #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct Signature(ffi::Signature); +impl std::convert::AsRef<[u8]> for Signature { + fn as_ref(&self) -> &[u8] { + &self.0.as_ref() + } +} + /// An ECDSA signature with a recovery ID for pubkey recovery #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct RecoverableSignature(ffi::RecoverableSignature); diff --git a/secp256k1zkp/src/macros.rs b/secp256k1zkp/src/macros.rs index c47451631..75295e54b 100644 --- a/secp256k1zkp/src/macros.rs +++ b/secp256k1zkp/src/macros.rs @@ -42,6 +42,12 @@ macro_rules! impl_array_newtype { pub fn is_empty(&self) -> bool { false } } + impl AsRef<[u8]> for $thing { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } + } + impl PartialEq for $thing { #[inline] fn eq(&self, other: &$thing) -> bool { diff --git a/secp256k1zkp/src/pedersen.rs b/secp256k1zkp/src/pedersen.rs index 9c84d31fd..bd0075d24 100644 --- a/secp256k1zkp/src/pedersen.rs +++ b/secp256k1zkp/src/pedersen.rs @@ -16,6 +16,7 @@ //! # Pedersen commitments and related range proofs use std::mem; +use std::convert; use ContextFlag; use Error; @@ -32,6 +33,7 @@ pub struct Commitment(pub [u8; constants::PEDERSEN_COMMITMENT_SIZE]); impl_array_newtype!(Commitment, u8, constants::PEDERSEN_COMMITMENT_SIZE); impl_pretty_debug!(Commitment); + impl Commitment { /// Uninitialized commitment, use with caution unsafe fn blank() -> Commitment { @@ -74,6 +76,12 @@ impl Clone for RangeProof { } } +impl AsRef<[u8]> for RangeProof { + fn as_ref(&self) -> &[u8] { + &self.proof[..self.plen as usize] + } +} + impl RangeProof { pub fn bytes(&self) -> &[u8] { &self.proof[..self.plen as usize] diff --git a/store/src/lib.rs b/store/src/lib.rs index 47c406bce..e69be1329 100644 --- a/store/src/lib.rs +++ b/store/src/lib.rs @@ -92,7 +92,7 @@ impl Store { /// Writes a single key and its `Writeable` value to the db. Encapsulates /// serialization. - pub fn put_ser(&self, key: &[u8], value: &ser::Writeable) -> Result<(), Error> { + pub fn put_ser(&self, key: &[u8], value: &W) -> Result<(), Error> { let ser_value = ser::ser_vec(value); match ser_value { Ok(data) => self.put(key, data), @@ -176,7 +176,7 @@ pub struct Batch<'a> { impl<'a> Batch<'a> { /// Writes a single key and its `Writeable` value to the batch. The write /// function must be called to "commit" the batch to storage. - pub fn put_ser(mut self, key: &[u8], value: &ser::Writeable) -> Result, Error> { + pub fn put_ser(mut self, key: &[u8], value: &W) -> Result, Error> { let ser_value = ser::ser_vec(value); match ser_value { Ok(data) => {