diff --git a/core/src/core/block.rs b/core/src/core/block.rs index df38d906d..9413246f9 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -61,12 +61,13 @@ impl Default for BlockHeader { // core. Readable is in the ser package. impl Writeable for BlockHeader { fn write(&self, writer: &mut Writer) -> Option { - try_m!(writer.write_u64(self.height)); - try_m!(writer.write_fixed_bytes(&self.previous)); - try_m!(writer.write_i64(self.timestamp.to_timespec().sec)); - try_m!(writer.write_fixed_bytes(&self.utxo_merkle)); - try_m!(writer.write_fixed_bytes(&self.tx_merkle)); - try_m!(writer.write_u64(self.total_fees)); + ser_multiwrite!(writer, + [write_u64, self.height], + [write_fixed_bytes, &self.previous], + [write_i64, self.timestamp.to_timespec().sec], + [write_fixed_bytes, &self.utxo_merkle], + [write_fixed_bytes, &self.tx_merkle], + [write_u64, self.total_fees]); // make sure to not introduce any variable length data before the nonce to // avoid complicating PoW try_m!(writer.write_u64(self.nonce)); @@ -103,9 +104,10 @@ impl Writeable for Block { fn write(&self, writer: &mut Writer) -> Option { try_m!(self.header.write(writer)); - try_m!(writer.write_u64(self.inputs.len() as u64)); - try_m!(writer.write_u64(self.outputs.len() as u64)); - try_m!(writer.write_u64(self.proofs.len() as u64)); + ser_multiwrite!(writer, + [write_u64, self.inputs.len() as u64], + [write_u64, self.outputs.len() as u64], + [write_u64, self.proofs.len() as u64]); for inp in &self.inputs { try_m!(inp.write(writer)); } @@ -123,8 +125,15 @@ impl Writeable for Block { /// from a binary stream. impl Readable for Block { fn read(reader: &mut Reader) -> Result { - let (height, previous, timestamp, utxo_merkle, tx_merkle, total_fees, nonce) = - ser_multiread!(reader, read_u64, read_32_bytes, read_i64, read_32_bytes, read_32_bytes, read_u64, read_u64); + let (height, previous, timestamp, utxo_merkle, tx_merkle, total_fees, nonce) = + ser_multiread!(reader, + read_u64, + read_32_bytes, + read_i64, + read_32_bytes, + read_32_bytes, + read_u64, + read_u64); // cuckoo cycle of 42 nodes let mut pow = [0; PROOFSIZE]; @@ -132,11 +141,12 @@ impl Readable for Block { pow[n] = try!(reader.read_u32()); } - let (td, input_len, output_len, proof_len) = - ser_multiread!(reader, read_u64, read_u64, read_u64, read_u64); + let (td, input_len, output_len, proof_len) = + ser_multiread!(reader, read_u64, read_u64, read_u64, read_u64); if input_len > MAX_IN_OUT_LEN || output_len > MAX_IN_OUT_LEN || proof_len > MAX_IN_OUT_LEN { - return Err(ser::Error::TooLargeReadErr("Too many inputs, outputs or proofs.".to_string())); + return Err(ser::Error::TooLargeReadErr("Too many inputs, outputs or proofs." + .to_string())); } let inputs = try!((0..input_len).map(|_| Input::read(reader)).collect()); @@ -373,7 +383,7 @@ impl Block { #[cfg(test)] mod test { use super::*; - use core::{Input, Output, Transaction}; + use core::{Input, Output, Transaction}; use core::hash::{Hash, Hashed}; use core::test::{tx1i1o, tx2i1o}; @@ -463,4 +473,3 @@ mod test { assert_eq!(b3.outputs.len(), 4); } } - diff --git a/core/src/core/hash.rs b/core/src/core/hash.rs index 0ed193809..ad3328ec6 100644 --- a/core/src/core/hash.rs +++ b/core/src/core/hash.rs @@ -80,4 +80,3 @@ impl Hashed for [u8] { self.to_owned() } } - diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index ff202559f..0e287613c 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -47,7 +47,7 @@ impl Writeable for TxProof { impl Readable for TxProof { fn read(reader: &mut Reader) -> Result { - let (remainder, sig) = ser_multiread!(reader, read_33_bytes, read_vec); + let (remainder, sig) = ser_multiread!(reader, read_33_bytes, read_vec); Ok(TxProof { remainder: Commitment::from_vec(remainder), sig: sig, @@ -69,10 +69,11 @@ pub struct Transaction { /// write the transaction as binary. impl Writeable for Transaction { fn write(&self, writer: &mut Writer) -> Option { - try_m!(writer.write_u64(self.fee)); - try_m!(writer.write_vec(&mut self.zerosig.clone())); - try_m!(writer.write_u64(self.inputs.len() as u64)); - try_m!(writer.write_u64(self.outputs.len() as u64)); + ser_multiwrite!(writer, + [write_u64, self.fee], + [write_vec, &mut self.zerosig.clone()], + [write_u64, self.inputs.len() as u64], + [write_u64, self.outputs.len() as u64]); for inp in &self.inputs { try_m!(inp.write(writer)); } @@ -87,8 +88,8 @@ impl Writeable for Transaction { /// transaction from a binary stream. impl Readable for Transaction { fn read(reader: &mut Reader) -> Result { - let (fee, zerosig, input_len, output_len) = - ser_multiread!(reader, read_u64, read_vec, read_u64, read_u64); + let (fee, zerosig, input_len, output_len) = + ser_multiread!(reader, read_u64, read_vec, read_u64, read_u64); // in case a facetious miner sends us more than what we can allocate if input_len > MAX_IN_OUT_LEN || output_len > MAX_IN_OUT_LEN { @@ -311,7 +312,7 @@ impl Writeable for Output { /// an Output from a binary stream. impl Readable for Output { fn read(reader: &mut Reader) -> Result { - let (commit, proof) = ser_multiread!(reader, read_33_bytes, read_vec); + let (commit, proof) = ser_multiread!(reader, read_33_bytes, read_vec); Ok(Output::BlindOutput { commit: Commitment::from_vec(commit), proof: RangeProof::from_vec(proof), @@ -545,5 +546,3 @@ mod test { } } } - - diff --git a/core/src/macros.rs b/core/src/macros.rs index de8988623..aa0db0f83 100644 --- a/core/src/macros.rs +++ b/core/src/macros.rs @@ -72,7 +72,8 @@ macro_rules! try_m { } } -/// Eliminate some of the boilerplate of deserialization (package ser) by passing just the list of reader function. +/// Eliminate some of the boilerplate of deserialization (package ser) by +/// passing just the list of reader function. /// Example before: /// let foo = try!(reader.read_u64()); /// let bar = try!(reader.read_u32()); @@ -85,3 +86,9 @@ macro_rules! ser_multiread { } } +#[macro_export] +macro_rules! ser_multiwrite { + ($wrtr:ident, $([ $write_call:ident, $val:expr ]),* ) => { + $( try_m!($wrtr.$write_call($val)) );* + } +} diff --git a/core/src/ser.rs b/core/src/ser.rs index 6ae913773..41049dac9 100644 --- a/core/src/ser.rs +++ b/core/src/ser.rs @@ -28,11 +28,11 @@ use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian}; pub enum Error { /// Wraps an io error produced when reading or writing IOErr(io::Error), - /// Expected a given value that wasn't found - UnexpectedData{ - expected: Vec, - received: Vec, - }, + /// Expected a given value that wasn't found + UnexpectedData { + expected: Vec, + received: Vec, + }, /// When asked to read too much data TooLargeReadErr(String), } @@ -48,7 +48,7 @@ pub trait AsFixedBytes { /// written to an underlying stream or container (depending on implementation). pub trait Writer { /// Writes a u8 as bytes - fn write_u8(&mut self, n: u8) -> Option; + fn write_u8(&mut self, n: u8) -> Option; /// Writes a u32 as bytes fn write_u32(&mut self, n: u32) -> Option; /// Writes a u64 as bytes @@ -78,12 +78,13 @@ pub trait Reader { fn read_vec(&mut self) -> Result, Error>; /// Read a fixed number of bytes from the underlying reader. fn read_fixed_bytes(&mut self, length: usize) -> Result, Error>; - /// Convenience function to read 32 fixed bytes - fn read_32_bytes(&mut self) -> Result, Error>; - /// Convenience function to read 33 fixed bytes - fn read_33_bytes(&mut self) -> Result, Error>; - /// Consumes a byte from the reader, producing an error if it doesn't have the expected value - fn expect_u8(&mut self, val: u8) -> Result; + /// Convenience function to read 32 fixed bytes + fn read_32_bytes(&mut self) -> Result, Error>; + /// Convenience function to read 33 fixed bytes + fn read_33_bytes(&mut self) -> Result, Error>; + /// Consumes a byte from the reader, producing an error if it doesn't have + /// the expected value + fn expect_u8(&mut self, val: u8) -> Result; } /// Trait that every type that can be serialized as binary must implement. @@ -157,15 +158,22 @@ impl<'a> Reader for BinReader<'a> { self.source.read_exact(&mut buf).map(move |_| buf).map_err(Error::IOErr) } fn read_32_bytes(&mut self) -> Result, Error> { - self.read_fixed_bytes(32) - } + self.read_fixed_bytes(32) + } fn read_33_bytes(&mut self) -> Result, Error> { - self.read_fixed_bytes(33) - } - fn expect_u8(&mut self, val: u8) -> Result { - let b = try!(self.read_u8()); - if b == val { Ok(b) } else { Err(Error::UnexpectedData{expected: vec![val], received: vec![b]}) } - } + self.read_fixed_bytes(33) + } + fn expect_u8(&mut self, val: u8) -> Result { + let b = try!(self.read_u8()); + if b == val { + Ok(b) + } else { + Err(Error::UnexpectedData { + expected: vec![val], + received: vec![b], + }) + } + } } /// Utility wrapper for an underlying byte Writer. Defines higher level methods @@ -228,4 +236,3 @@ impl AsFixedBytes for ::secp::pedersen::RangeProof { &self.bytes() } } -