From 626fcdfffc239a2e973a1024e75624444af7fdb0 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 28 Jan 2016 20:13:05 +0100 Subject: [PATCH] append Now accepts lists again --- src/block.rs | 3 +- src/extras.rs | 6 +-- src/log_entry.rs | 2 +- src/receipt.rs | 2 +- src/verification.rs | 4 +- util/src/bytes.rs | 1 - util/src/journaldb.rs | 4 +- util/src/network/session.rs | 2 +- util/src/rlp/mod.rs | 23 +---------- util/src/rlp/rlpstream.rs | 82 +++++++++++++++++++++++++++---------- util/src/rlp/rlptraits.rs | 25 ++++------- util/src/rlp/tests.rs | 41 +++++++------------ 12 files changed, 96 insertions(+), 99 deletions(-) diff --git a/src/block.rs b/src/block.rs index ca99063d8..b1db20fd7 100644 --- a/src/block.rs +++ b/src/block.rs @@ -301,8 +301,7 @@ impl SealedBlock { pub fn rlp_bytes(&self) -> Bytes { let mut block_rlp = RlpStream::new_list(3); self.block.base.header.stream_rlp(&mut block_rlp, Seal::With); - block_rlp.begin_list(self.block.receipts.len()); - for t in &self.block.base.transactions { t.rlp_append(&mut block_rlp); } + block_rlp.append(&self.block.base.transactions); block_rlp.append_raw(&self.uncle_bytes, 1); block_rlp.out() } diff --git a/src/extras.rs b/src/extras.rs index 54ab23b58..d571e7c36 100644 --- a/src/extras.rs +++ b/src/extras.rs @@ -150,7 +150,7 @@ impl Encodable for BlockDetails { s.append(&self.number); s.append(&self.total_difficulty); s.append(&self.parent); - s.append_list(&self.children); + s.append(&self.children); } } @@ -185,7 +185,7 @@ impl Decodable for BlockLogBlooms { impl Encodable for BlockLogBlooms { fn rlp_append(&self, s: &mut RlpStream) { - s.append_list(&self.blooms); + s.append(&self.blooms); } } @@ -232,7 +232,7 @@ impl Decodable for BlocksBlooms { impl Encodable for BlocksBlooms { fn rlp_append(&self, s: &mut RlpStream) { let blooms_ref: &[H2048] = &self.blooms; - s.append_list(&blooms_ref); + s.append(&blooms_ref); } } diff --git a/src/log_entry.rs b/src/log_entry.rs index cb2b20e6c..8141549a3 100644 --- a/src/log_entry.rs +++ b/src/log_entry.rs @@ -16,7 +16,7 @@ impl Encodable for LogEntry { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(3); s.append(&self.address); - s.append_list(&self.topics); + s.append(&self.topics); s.append(&self.data); } } diff --git a/src/receipt.rs b/src/receipt.rs index 3ca9a76ee..d320373d6 100644 --- a/src/receipt.rs +++ b/src/receipt.rs @@ -33,6 +33,6 @@ impl Encodable for Receipt { s.append(&self.state_root); s.append(&self.gas_used); s.append(&self.log_bloom); - s.append_list(&self.logs); + s.append(&self.logs); } } diff --git a/src/verification.rs b/src/verification.rs index 0316ec7e7..567540c66 100644 --- a/src/verification.rs +++ b/src/verification.rs @@ -237,7 +237,7 @@ mod tests { for t in transactions { rlp.append_raw(&t.rlp_bytes_opt(Seal::With), 1); } - rlp.append_list(&uncles); + rlp.append(&uncles); rlp.out().to_vec() } @@ -362,7 +362,7 @@ mod tests { let good_uncles = vec![ good_uncle1.clone(), good_uncle2.clone() ]; let mut uncles_rlp = RlpStream::new(); - uncles_rlp.append_list(&good_uncles); + uncles_rlp.append(&good_uncles); let good_uncles_hash = uncles_rlp.as_raw().sha3(); let good_transactions_root = ordered_trie_root(good_transactions.iter().map(|t| t.rlp_bytes_opt(Seal::With)).collect()); diff --git a/util/src/bytes.rs b/util/src/bytes.rs index f40771438..102206f6c 100644 --- a/util/src/bytes.rs +++ b/util/src/bytes.rs @@ -268,7 +268,6 @@ macro_rules! impl_map_to_bytes { } impl_map_to_bytes!(usize, u64); -impl_map_to_bytes!(u8, u64); impl_map_to_bytes!(u16, u64); impl_map_to_bytes!(u32, u64); diff --git a/util/src/journaldb.rs b/util/src/journaldb.rs index 6c904ca5f..ba31efafb 100644 --- a/util/src/journaldb.rs +++ b/util/src/journaldb.rs @@ -86,8 +86,8 @@ impl JournalDB { let mut r = RlpStream::new_list(3); r.append(id); - r.append_list(&self.inserts); - r.append_list(&self.removes); + r.append(&self.inserts); + r.append(&self.removes); try!(self.backing.put(&last, r.as_raw())); self.inserts.clear(); self.removes.clear(); diff --git a/util/src/network/session.rs b/util/src/network/session.rs index 380da3e9b..09b7af5d3 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -202,7 +202,7 @@ impl Session { rlp.begin_list(5) .append(&host.protocol_version) .append(&host.client_version) - .append_list(&host.capabilities) + .append(&host.capabilities) .append(&host.listen_port) .append(host.id()); self.connection.send_packet(&rlp.out()) diff --git a/util/src/rlp/mod.rs b/util/src/rlp/mod.rs index 8dddf3acc..88872c2d1 100644 --- a/util/src/rlp/mod.rs +++ b/util/src/rlp/mod.rs @@ -30,7 +30,6 @@ //! * You want to get view onto rlp-slice. //! * You don't want to decode whole rlp at once. -use std::ops::Deref; /// TODO [Gav Wood] Please document me pub mod rlptraits; /// TODO [Gav Wood] Please document me @@ -46,7 +45,7 @@ pub mod rlpstream; mod tests; pub use self::rlperrors::DecoderError; -pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder}; +pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder, RlpEncodable}; pub use self::untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype}; pub use self::rlpin::{Rlp, RlpIterator}; pub use self::rlpstream::{RlpStream}; @@ -91,26 +90,8 @@ pub fn decode(bytes: &[u8]) -> T where T: Decodable { /// assert_eq!(out, vec![0x83, b'c', b'a', b't']); /// } /// ``` -pub fn encode(object: &E) -> ElasticArray1024 where E: Encodable { +pub fn encode(object: &E) -> ElasticArray1024 where E: RlpEncodable { let mut stream = RlpStream::new(); stream.append(object); stream.drain() } - -/// Shortcut function to encode a list to rlp. -/// -/// ```rust -/// extern crate ethcore_util as util; -/// use util::rlp::*; -/// -/// fn main () { -/// let animals = vec!["cat", "dog"]; -/// let out = encode_list(&animals).to_vec(); -/// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); -/// } -/// ``` -pub fn encode_list(list: &I) -> ElasticArray1024 where I: Deref, E: Encodable { - let mut stream = RlpStream::new(); - stream.append_list(list); - stream.drain() -} diff --git a/util/src/rlp/rlpstream.rs b/util/src/rlp/rlpstream.rs index 0b600b567..5eb071389 100644 --- a/util/src/rlp/rlpstream.rs +++ b/util/src/rlp/rlpstream.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use elastic_array::*; use bytes::{ToBytes, VecLike}; use rlp::{Stream, Encoder, Encodable}; -use rlp::rlptraits::ByteEncodable; +use rlp::rlptraits::{ByteEncodable, RlpEncodable}; #[derive(Debug, Copy, Clone)] struct ListInfo { @@ -43,7 +43,7 @@ impl Stream for RlpStream { stream } - fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable { + fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: RlpEncodable { self.finished_list = false; value.rlp_append(self); if !self.finished_list { @@ -70,16 +70,6 @@ impl Stream for RlpStream { self } - fn append_list(&mut self, list: &I) -> &mut Self where I: Deref, E: Encodable { - let items = list.deref(); - self.begin_list(items.len()); - for el in items.iter() { - el.rlp_append(self); - } - self.note_appended(items.len()); - self - } - fn append_empty_data(&mut self) -> &mut RlpStream { // self push raw item self.encoder.bytes.push(0x80); @@ -134,6 +124,15 @@ impl RlpStream { self.encoder.emit_value(object); } + fn append_internal<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable { + self.finished_list = false; + value.rlp_append(self); + if !self.finished_list { + self.note_appended(1); + } + self + } + /// Try to finish lists fn note_appended(&mut self, inserted_items: usize) -> () { if self.unfinished_lists.len() == 0 { @@ -234,7 +233,6 @@ impl Encoder for BasicEncoder { } } - impl ByteEncodable for T where T: ToBytes { fn to_bytes>(&self, out: &mut V) { ToBytes::to_bytes(self, out) @@ -245,23 +243,27 @@ impl ByteEncodable for T where T: ToBytes { } } -impl<'a> ByteEncodable for &'a[u8] { +struct U8Slice<'a>(&'a [u8]); + +impl<'a> ByteEncodable for U8Slice<'a> { fn to_bytes>(&self, out: &mut V) { - out.vec_extend(self) + out.vec_extend(self.0) } fn bytes_len(&self) -> usize { - self.len() + self.0.len() } } -impl ByteEncodable for Vec { - fn to_bytes>(&self, out: &mut V) { - out.vec_extend(self.deref()) +impl<'a> Encodable for &'a[u8] { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(&U8Slice(self)) } +} - fn bytes_len(&self) -> usize { - self.len() +impl Encodable for Vec { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(&U8Slice(self.deref())) } } @@ -270,3 +272,41 @@ impl Encodable for T where T: ByteEncodable { s.append_value(self) } } + +struct EncodableU8 (u8); + +impl ByteEncodable for EncodableU8 { + fn to_bytes>(&self, out: &mut V) { + out.vec_push(self.0) + } + + fn bytes_len(&self) -> usize { 1 } +} + +impl RlpEncodable for u8 { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(&EncodableU8(*self)) + } +} + +impl<'a, T> Encodable for &'a[T] where T: Encodable { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(self.len()); + for el in self.iter() { + s.append_internal(el); + } + } +} + +impl Encodable for Vec where T: Encodable { + fn rlp_append(&self, s: &mut RlpStream) { + Encodable::rlp_append(&self.deref(), s); + } +} + +impl RlpEncodable for T where T: Encodable { + fn rlp_append(&self, s: &mut RlpStream) { + Encodable::rlp_append(self, s) + } +} + diff --git a/util/src/rlp/rlptraits.rs b/util/src/rlp/rlptraits.rs index 437d86dc6..f79c7848c 100644 --- a/util/src/rlp/rlptraits.rs +++ b/util/src/rlp/rlptraits.rs @@ -223,7 +223,7 @@ pub trait ByteEncodable { fn bytes_len(&self) -> usize; } -/// Structure encodable to RLP +/// Structure encodable to RLP. Implement this trait for pub trait Encodable { /// Append a value to the stream fn rlp_append(&self, s: &mut RlpStream); @@ -239,6 +239,12 @@ pub trait Encodable { fn rlp_sha3(&self) -> H256 { self.rlp_bytes().deref().sha3() } } +/// Encodable wrapper trait required to handle special case of encoding a &[u8] as string and not as list +pub trait RlpEncodable { + /// Append a value to the stream + fn rlp_append(&self, s: &mut RlpStream); +} + /// TODO [debris] Please document me pub trait Stream: Sized { @@ -261,7 +267,7 @@ pub trait Stream: Sized { /// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); /// } /// ``` - fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable; + fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: RlpEncodable; /// Declare appending the list of given size, chainable. /// @@ -279,21 +285,6 @@ pub trait Stream: Sized { /// ``` fn begin_list(&mut self, len: usize) -> &mut Self; - /// Append the given list, chainable. - /// - /// ```rust - /// extern crate ethcore_util as util; - /// use util::rlp::*; - /// - /// fn main () { - /// let mut stream = RlpStream::new_list(1); - /// stream.append_list(&vec!["cat", "dog"]); - /// let out = stream.out().to_vec(); - /// assert_eq!(out, vec![0xc9, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); - /// } - /// ``` - fn append_list(&mut self, list: &I) -> &mut Self where I: Deref, E: Encodable; - /// Apends null to the end of stream, chainable. /// /// ```rust diff --git a/util/src/rlp/tests.rs b/util/src/rlp/tests.rs index b83e851cc..912709b5e 100644 --- a/util/src/rlp/tests.rs +++ b/util/src/rlp/tests.rs @@ -77,7 +77,6 @@ fn rlp_iter() { } struct ETestPair(T, Vec) where T: rlp::Encodable; -struct ETestVecPair(Vec, Vec) where T: rlp::Encodable; fn run_encode_tests(tests: Vec>) where T: rlp::Encodable @@ -88,15 +87,6 @@ fn run_encode_tests(tests: Vec>) } } -fn run_encode_list_tests(tests: Vec>) - where T: rlp::Encodable -{ - for t in &tests { - let res = rlp::encode_list(&t.0); - assert_eq!(&res[..], &t.1[..]); - } -} - #[test] fn encode_u16() { let tests = vec![ @@ -188,19 +178,19 @@ fn encode_vector_u8() { #[test] fn encode_vector_u64() { let tests = vec![ - ETestVecPair(vec![], vec![0xc0]), - ETestVecPair(vec![15u64], vec![0xc1, 0x0f]), - ETestVecPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), - ETestVecPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), + ETestPair(vec![], vec![0xc0]), + ETestPair(vec![15u64], vec![0xc1, 0x0f]), + ETestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), + ETestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), ]; - run_encode_list_tests(tests); + run_encode_tests(tests); } #[test] fn encode_vector_str() { - let tests = vec![ETestVecPair(vec!["cat", "dog"], + let tests = vec![ETestPair(vec!["cat", "dog"], vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; - run_encode_list_tests(tests); + run_encode_tests(tests); } struct DTestPair(T, Vec) where T: rlp::Decodable + fmt::Debug + cmp::Eq; @@ -227,9 +217,8 @@ fn decode_vector_u8() { #[test] fn decode_untrusted_u16() { let tests = vec![ - DTestPair(0u16, vec![0u8]), - DTestPair(0x100, vec![0x82, 0x01, 0x00]), - DTestPair(0xffff, vec![0x82, 0xff, 0xff]), + DTestPair(0x100u16, vec![0x82, 0x01, 0x00]), + DTestPair(0xffffu16, vec![0x82, 0xff, 0xff]), ]; run_decode_tests(tests); } @@ -237,9 +226,8 @@ fn decode_untrusted_u16() { #[test] fn decode_untrusted_u32() { let tests = vec![ - DTestPair(0u32, vec![0u8]), - DTestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), - DTestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), + DTestPair(0x10000u32, vec![0x83, 0x01, 0x00, 0x00]), + DTestPair(0xffffffu32, vec![0x83, 0xff, 0xff, 0xff]), ]; run_decode_tests(tests); } @@ -247,9 +235,8 @@ fn decode_untrusted_u32() { #[test] fn decode_untrusted_u64() { let tests = vec![ - DTestPair(0u64, vec![0u8]), - DTestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), - DTestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), + DTestPair(0x1000000u64, vec![0x84, 0x01, 0x00, 0x00, 0x00]), + DTestPair(0xFFFFFFFFu64, vec![0x84, 0xff, 0xff, 0xff, 0xff]), ]; run_decode_tests(tests); } @@ -350,7 +337,7 @@ fn test_rlp_json() { #[test] fn test_decoding_array() { let v = vec![5u16, 2u16]; - let res = rlp::encode_list(&v); + let res = rlp::encode(&v); let arr: [u16; 2] = rlp::decode(&res); assert_eq!(arr[0], 5); assert_eq!(arr[1], 2);