From 40314614f7063c94dd73eb41c0d3d698362a5f83 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 27 Jan 2016 12:14:57 +0100 Subject: [PATCH] RLP encoder refactoring --- util/Cargo.toml | 1 + util/src/bytes.rs | 96 ++++++++++++++--------- util/src/journaldb.rs | 4 +- util/src/lib.rs | 1 + util/src/network/host.rs | 9 +-- util/src/network/session.rs | 8 +- util/src/network/tests.rs | 1 + util/src/overlaydb.rs | 1 - util/src/rlp/mod.rs | 30 ++++++-- util/src/rlp/rlpstream.rs | 150 +++++++++++++++--------------------- util/src/rlp/rlptraits.rs | 55 ++++++++++--- util/src/rlp/tests.rs | 36 +++++---- util/src/trie/node.rs | 6 +- util/src/trie/triedbmut.rs | 6 +- util/src/triehash.rs | 8 +- 15 files changed, 234 insertions(+), 178 deletions(-) diff --git a/util/Cargo.toml b/util/Cargo.toml index a91bff962..00f64948a 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -23,6 +23,7 @@ elastic-array = "0.4" heapsize = "0.2" itertools = "0.4" crossbeam = "0.2" +smallvec = "0.1" slab = { git = "https://github.com/arkpar/slab.git" } sha3 = { path = "sha3" } clippy = "*" # Always newest, since we use nightly diff --git a/util/src/bytes.rs b/util/src/bytes.rs index a30581a1f..3f637abaf 100644 --- a/util/src/bytes.rs +++ b/util/src/bytes.rs @@ -42,8 +42,37 @@ use std::error::Error as StdError; use std::ops::{Deref, DerefMut}; use uint::{Uint, U128, U256}; use hash::FixedHash; +use elastic_array::*; -/// TODO [Gav Wood] Please document me +/// Vector like object +pub trait VecLike { + /// Add an element to the collection + fn push(&mut self, value: T); + + /// Add a slice to the collection + fn extend(&mut self, slice: &[T]); +} + + +macro_rules! impl_veclike_for_elastic_array { + ($from: ident) => { + impl VecLike for $from where T: Copy { + fn push(&mut self, value: T) { + $from::::push(self, value) + } + fn extend(&mut self, slice: &[T]) { + $from::::append_slice(self, slice) + + } + } + } +} + +impl_veclike_for_elastic_array!(ElasticArray16); +impl_veclike_for_elastic_array!(ElasticArray32); +impl_veclike_for_elastic_array!(ElasticArray1024); + +/// Slie pretty print helper pub struct PrettySlice<'a> (&'a [u8]); impl<'a> fmt::Debug for PrettySlice<'a> { @@ -170,49 +199,47 @@ fn bytes_convertable() { /// /// TODO: optimise some conversations pub trait ToBytes { - /// TODO [Gav Wood] Please document me - fn to_bytes(&self) -> Vec; - /// TODO [Gav Wood] Please document me - fn to_bytes_len(&self) -> usize { self.to_bytes().len() } - /// TODO [debris] Please document me - fn first_byte(&self) -> Option { self.to_bytes().first().map(|&x| { x })} + /// Serialize self to byte array + fn to_bytes>(&self, out: &mut V); + /// Get length of serialized data in bytes + fn to_bytes_len(&self) -> usize; } impl <'a> ToBytes for &'a str { - fn to_bytes(&self) -> Vec { - From::from(*self) + fn to_bytes>(&self, out: &mut V) { + out.extend(self.as_bytes()); } - fn to_bytes_len(&self) -> usize { self.len() } + fn to_bytes_len(&self) -> usize { + self.as_bytes().len() + } } impl ToBytes for String { - fn to_bytes(&self) -> Vec { - let s: &str = self.as_ref(); - From::from(s) + fn to_bytes>(&self, out: &mut V) { + out.extend(self.as_bytes()); } - fn to_bytes_len(&self) -> usize { self.len() } + fn to_bytes_len(&self) -> usize { + self.len() + } } impl ToBytes for u64 { - fn to_bytes(&self) -> Vec { - let mut res= vec![]; + fn to_bytes>(&self, out: &mut V) { let count = self.to_bytes_len(); - res.reserve(count); for i in 0..count { let j = count - 1 - i; - res.push((*self >> (j * 8)) as u8); + out.push((*self >> (j * 8)) as u8); } - res } fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 } } impl ToBytes for bool { - fn to_bytes(&self) -> Vec { - vec![ if *self { 1u8 } else { 0u8 } ] + fn to_bytes>(&self, out: &mut V) { + out.push(if *self { 1u8 } else { 0u8 }) } fn to_bytes_len(&self) -> usize { 1 } @@ -221,28 +248,29 @@ impl ToBytes for bool { macro_rules! impl_map_to_bytes { ($from: ident, $to: ty) => { impl ToBytes for $from { - fn to_bytes(&self) -> Vec { (*self as $to).to_bytes() } + fn to_bytes>(&self, out: &mut V) { + (*self as $to).to_bytes(out) + } + fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() } } } } impl_map_to_bytes!(usize, u64); +impl_map_to_bytes!(u8, u64); impl_map_to_bytes!(u16, u64); impl_map_to_bytes!(u32, u64); macro_rules! impl_uint_to_bytes { ($name: ident) => { impl ToBytes for $name { - fn to_bytes(&self) -> Vec { - let mut res= vec![]; + fn to_bytes>(&self, out: &mut V) { let count = self.to_bytes_len(); - res.reserve(count); for i in 0..count { let j = count - 1 - i; - res.push(self.byte(j)); + out.push(self.byte(j)); } - res } fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 } } @@ -253,18 +281,10 @@ impl_uint_to_bytes!(U256); impl_uint_to_bytes!(U128); impl ToBytes for T where T: FixedHash { - fn to_bytes(&self) -> Vec { - let mut res: Vec = vec![]; - res.reserve(T::size()); - - unsafe { - use std::ptr; - ptr::copy(self.bytes().as_ptr(), res.as_mut_ptr(), T::size()); - res.set_len(T::size()); - } - - res + fn to_bytes>(&self, out: &mut V) { + out.extend(self.bytes()); } + fn to_bytes_len(&self) -> usize { self.bytes().len() } } /// Error returned when FromBytes conversation goes wrong diff --git a/util/src/journaldb.rs b/util/src/journaldb.rs index ba31efafb..6c904ca5f 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(&self.inserts); - r.append(&self.removes); + r.append_list(&self.inserts); + r.append_list(&self.removes); try!(self.backing.put(&last, r.as_raw())); self.inserts.clear(); self.removes.clear(); diff --git a/util/src/lib.rs b/util/src/lib.rs index 970c0713c..09f92429a 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -55,6 +55,7 @@ extern crate secp256k1; extern crate arrayvec; extern crate elastic_array; extern crate crossbeam; +extern crate smallvec; /// TODO [Gav Wood] Please document me pub mod standard; diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 6f306ecb0..95b1e3668 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -124,11 +124,10 @@ pub struct CapabilityInfo { } impl Encodable for CapabilityInfo { - fn encode(&self, encoder: &mut E) -> () where E: Encoder { - encoder.emit_list(|e| { - self.protocol.encode(e); - (self.version as u32).encode(e); - }); + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(2); + s.append(&self.protocol); + s.append(&self.version); } } diff --git a/util/src/network/session.rs b/util/src/network/session.rs index 2817f008d..380da3e9b 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -199,10 +199,10 @@ impl Session { fn write_hello(&mut self, host: &HostInfo) -> Result<(), UtilError> { let mut rlp = RlpStream::new(); rlp.append_raw(&[PACKET_HELLO as u8], 0); - rlp.append_list(5) + rlp.begin_list(5) .append(&host.protocol_version) .append(&host.client_version) - .append(&host.capabilities) + .append_list(&host.capabilities) .append(&host.listen_port) .append(host.id()); self.connection.send_packet(&rlp.out()) @@ -267,7 +267,7 @@ impl Session { fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError { let mut rlp = RlpStream::new(); rlp.append(&(PACKET_DISCONNECT as u32)); - rlp.append_list(1); + rlp.begin_list(1); rlp.append(&(reason.clone() as u32)); self.connection.send_packet(&rlp.out()).ok(); NetworkError::Disconnect(reason) @@ -276,7 +276,7 @@ impl Session { fn prepare(packet_id: u8) -> Result { let mut rlp = RlpStream::new(); rlp.append(&(packet_id as u32)); - rlp.append_list(0); + rlp.begin_list(0); Ok(rlp) } diff --git a/util/src/network/tests.rs b/util/src/network/tests.rs index 06966abb5..0dd1aed12 100644 --- a/util/src/network/tests.rs +++ b/util/src/network/tests.rs @@ -75,6 +75,7 @@ fn test_net_service() { #[test] fn test_net_connect() { + ::env_logger::init().ok(); let key1 = KeyPair::create().unwrap(); let mut config1 = NetworkConfiguration::new_with_port(30344); config1.use_secret = Some(key1.secret().clone()); diff --git a/util/src/overlaydb.rs b/util/src/overlaydb.rs index d2f56a520..7ef0c3309 100644 --- a/util/src/overlaydb.rs +++ b/util/src/overlaydb.rs @@ -143,7 +143,6 @@ impl OverlayDB { self.backing.delete(&key.bytes()).expect("Low-level database error. Some issue with your hard disk?"); true } - } } diff --git a/util/src/rlp/mod.rs b/util/src/rlp/mod.rs index f6acdf180..8b7814e5a 100644 --- a/util/src/rlp/mod.rs +++ b/util/src/rlp/mod.rs @@ -30,6 +30,7 @@ //! * 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 @@ -48,7 +49,8 @@ pub use self::rlperrors::DecoderError; pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder}; pub use self::untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype}; pub use self::rlpin::{Rlp, RlpIterator}; -pub use self::rlpstream::{RlpStream,RlpStandard}; +pub use self::rlpstream::{RlpStream}; +pub use elastic_array::ElasticArray1024; use super::hash::H256; /// TODO [arkpar] Please document me @@ -84,13 +86,31 @@ pub fn decode(bytes: &[u8]) -> T where T: Decodable { /// use util::rlp::*; /// /// fn main () { +/// let animal = "cat"; +/// let out = encode(&animal); +/// assert_eq!(out, vec![0x83, b'c', b'a', b't']); +/// } +/// ``` +pub fn encode(object: &E) -> ElasticArray1024 where E: Encodable { + 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(&animals); +/// let out = encode_list(&animals); /// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); /// } /// ``` -pub fn encode(object: &E) -> Vec where E: Encodable { +pub fn encode_list(list: &I) -> ElasticArray1024 where I: Deref, E: Encodable { let mut stream = RlpStream::new(); - stream.append(object); - stream.out() + stream.append_list(list); + stream.drain() } diff --git a/util/src/rlp/rlpstream.rs b/util/src/rlp/rlpstream.rs index ac22736fc..b5e9d2152 100644 --- a/util/src/rlp/rlpstream.rs +++ b/util/src/rlp/rlpstream.rs @@ -1,8 +1,8 @@ +use std::ops::Deref; use elastic_array::*; -use bytes::{Bytes, ToBytes}; +use bytes::{ToBytes, VecLike}; use rlp::{Stream, Encoder, Encodable}; -use hash::H256; -use sha3::*; +use rlp::rlptraits::ByteEncodable; #[derive(Debug, Copy, Clone)] struct ListInfo { @@ -37,22 +37,18 @@ impl Stream for RlpStream { fn new_list(len: usize) -> Self { let mut stream = RlpStream::new(); - stream.append_list(len); + stream.begin_list(len); stream } - fn append(&mut self, object: &E) -> &mut RlpStream where E: Encodable { - // encode given value and add it at the end of the stream - object.encode(&mut self.encoder); - + fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable { + value.rlp_append(self); // if list is finished, prepend the length self.note_appended(1); - - // return chainable self self } - fn append_list(&mut self, len: usize) -> &mut RlpStream { + fn begin_list(&mut self, len: usize) -> &mut RlpStream { match len { 0 => { // we may finish, if the appended list len is equal 0 @@ -69,6 +65,15 @@ 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() { + self.append(el); + } + self + } + fn append_empty_data(&mut self) -> &mut RlpStream { // self push raw item self.encoder.bytes.push(0x80); @@ -117,6 +122,12 @@ impl Stream for RlpStream { impl RlpStream { + /// Appends primitive value to the end of stream + fn append_value(&mut self, object: &E) where E: ByteEncodable { + // encode given value and add it at the end of the stream + self.encoder.emit_value(object); + } + /// Try to finish lists fn note_appended(&mut self, inserted_items: usize) -> () { if self.unfinished_lists.len() == 0 { @@ -164,12 +175,12 @@ impl BasicEncoder { /// inserts list prefix at given position /// TODO: optimise it further? fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> () { - let mut res = vec![]; + let mut res = ElasticArray16::new(); match len { 0...55 => res.push(0xc0u8 + len as u8), _ => { res.push(0xf7u8 + len.to_bytes_len() as u8); - res.extend(len.to_bytes()); + ToBytes::to_bytes(&len, &mut res); } }; @@ -183,22 +194,30 @@ impl BasicEncoder { } impl Encoder for BasicEncoder { - fn emit_value(&mut self, bytes: &[u8]) -> () { - match bytes.len() { + fn emit_value(&mut self, value: &E) { + match value.bytes_len() { // just 0 0 => self.bytes.push(0x80u8), - // byte is its own encoding - 1 if bytes[0] < 0x80 => self.bytes.append_slice(bytes), + // byte is its own encoding if < 0x80 + 1 => { + value.to_bytes(&mut self.bytes); + let len = self.bytes.len(); + let last_byte = self.bytes[len - 1]; + if last_byte >= 0x80 { + self.bytes.push(last_byte); + self.bytes[len - 1] = 0x81; + } + } // (prefix + length), followed by the string - len @ 1 ... 55 => { + len @ 2 ... 55 => { self.bytes.push(0x80u8 + len as u8); - self.bytes.append_slice(bytes); + value.to_bytes(&mut self.bytes); } // (prefix + length of length), followed by the length, followd by the string len => { self.bytes.push(0xb7 + len.to_bytes_len() as u8); - self.bytes.append_slice(&len.to_bytes()); - self.bytes.append_slice(bytes); + ToBytes::to_bytes(&len, &mut self.bytes); + value.to_bytes(&mut self.bytes); } } } @@ -206,86 +225,41 @@ impl Encoder for BasicEncoder { fn emit_raw(&mut self, bytes: &[u8]) -> () { self.bytes.append_slice(bytes); } +} - fn emit_list(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> () { - // get len before inserting a list - let before_len = self.bytes.len(); - // insert all list elements - f(self); +impl ByteEncodable for T where T: ToBytes { + fn to_bytes>(&self, out: &mut V) { + ToBytes::to_bytes(self, out) + } - // get len after inserting a list - let after_len = self.bytes.len(); - - // diff is list len - let list_len = after_len - before_len; - self.insert_list_len_at_pos(list_len, before_len); + fn bytes_len(&self) -> usize { + ToBytes::to_bytes_len(self) } } -/// TODO [Gav Wood] Please document me -pub trait RlpStandard { - /// TODO [Gav Wood] Please document me - fn rlp_append(&self, s: &mut RlpStream); - - /// TODO [Gav Wood] Please document me - fn rlp_bytes(&self) -> Bytes { - let mut s = RlpStream::new(); - self.rlp_append(&mut s); - s.out() +impl<'a> ByteEncodable for &'a[u8] { + fn to_bytes>(&self, out: &mut V) { + out.extend(self) } - /// TODO [Gav Wood] Please document me - fn rlp_sha3(&self) -> H256 { self.rlp_bytes().sha3() } -} - -// @debris TODO: implement Encoder for RlpStandard. - -impl Encodable for T where T: ToBytes { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_value(&self.to_bytes()) + fn bytes_len(&self) -> usize { + self.len() } } -impl<'a, T> Encodable for &'a [T] where T: Encodable + 'a { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_list(|e| { - // insert all list elements - for el in self.iter() { - el.encode(e); - } - }) +impl ByteEncodable for Vec { + fn to_bytes>(&self, out: &mut V) { + out.extend(self.deref()) + } + + fn bytes_len(&self) -> usize { + self.len() } } -impl Encodable for Vec where T: Encodable { - fn encode(&self, encoder: &mut E) where E: Encoder { - let r: &[T] = self.as_ref(); - r.encode(encoder) - } -} - -/// lets treat bytes differently than other lists -/// they are a single value -impl<'a> Encodable for &'a [u8] { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_value(self) - } -} - -/// lets treat bytes differently than other lists -/// they are a single value -impl Encodable for Vec { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_value(self) - } -} - -impl Encodable for Option where T: Encodable { - fn encode(&self, encoder: &mut E) where E: Encoder { - match *self { - Some(ref x) => x.encode(encoder), - None => encoder.emit_value(&[]) - } +impl Encodable for T where T: ByteEncodable { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(self) } } diff --git a/util/src/rlp/rlptraits.rs b/util/src/rlp/rlptraits.rs index d6ef16932..aa964c26c 100644 --- a/util/src/rlp/rlptraits.rs +++ b/util/src/rlp/rlptraits.rs @@ -1,4 +1,10 @@ +use std::ops::Deref; +use bytes::VecLike; use rlp::{DecoderError, UntrustedRlp}; +use rlpstream::RlpStream; +use elastic_array::ElasticArray1024; +use hash::H256; +use sha3::*; /// TODO [debris] Please document me pub trait Decoder: Sized { @@ -204,17 +210,33 @@ pub trait View<'a, 'view>: Sized { /// TODO [debris] Please document me pub trait Encoder { /// TODO [debris] Please document me - fn emit_value(&mut self, bytes: &[u8]) -> (); - /// TODO [Gav Wood] Please document me - fn emit_list(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> (); + fn emit_value(&mut self, value: &E); /// TODO [debris] Please document me fn emit_raw(&mut self, bytes: &[u8]) -> (); } -/// TODO [debris] Please document me +/// Primitive data type encodable to RLP +pub trait ByteEncodable { + /// Serialize this object to given byte container + fn to_bytes>(&self, out: &mut V); + /// Get size of serialised data in bytes + fn bytes_len(&self) -> usize; +} + +/// Structure encodable to RLP pub trait Encodable { - /// TODO [debris] Please document me - fn encode(&self, encoder: &mut E) -> () where E: Encoder; + /// Append a value to the stream + fn rlp_append(&self, s: &mut RlpStream); + + /// Get rlp-encoded bytes for this instance + fn rlp_bytes(&self) -> ElasticArray1024 { + let mut s = RlpStream::new(); + self.rlp_append(&mut s); + s.drain() + } + + /// Get the hash or RLP encoded representation + fn rlp_sha3(&self) -> H256 { self.rlp_bytes().deref().sha3() } } /// TODO [debris] Please document me @@ -239,7 +261,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, object: &E) -> &'a mut Self where E: Encodable; + fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable; /// Declare appending the list of given size, chainable. /// @@ -249,13 +271,28 @@ pub trait Stream: Sized { /// /// fn main () { /// let mut stream = RlpStream::new_list(2); - /// stream.append_list(2).append(&"cat").append(&"dog"); + /// stream.begin_list(2).append(&"cat").append(&"dog"); /// stream.append(&""); /// let out = stream.out(); /// assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]); /// } /// ``` - fn append_list(&mut self, len: usize) -> &mut Self; + 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(2); + /// stream.begin_list([&"cat", &"dog"]); + /// let out = stream.out(); + /// assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]); + /// } + /// ``` + fn append_list(&mut self, list: &I) -> &mut Self where I: Deref, E: Encodable; /// Apends null to the end of stream, chainable. /// diff --git a/util/src/rlp/tests.rs b/util/src/rlp/tests.rs index f33cec177..df61ad127 100644 --- a/util/src/rlp/tests.rs +++ b/util/src/rlp/tests.rs @@ -77,13 +77,23 @@ 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 { for t in &tests { let res = rlp::encode(&t.0); - assert_eq!(res, &t.1[..]); + assert_eq!(&res[..], &t.1[..]); + } +} + +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[..]); } } @@ -178,25 +188,19 @@ fn encode_vector_u8() { #[test] fn encode_vector_u64() { let tests = vec![ - 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]), + 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]), ]; - run_encode_tests(tests); + run_encode_list_tests(tests); } #[test] fn encode_vector_str() { - let tests = vec![ETestPair(vec!["cat", "dog"], + let tests = vec![ETestVecPair(vec!["cat", "dog"], vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; - run_encode_tests(tests); -} - -#[test] -fn encode_vector_of_vectors_str() { - let tests = vec![ETestPair(vec![vec!["cat"]], vec![0xc5, 0xc4, 0x83, b'c', b'a', b't'])]; - run_encode_tests(tests); + run_encode_list_tests(tests); } struct DTestPair(T, Vec) where T: rlp::Decodable + fmt::Debug + cmp::Eq; @@ -333,7 +337,7 @@ fn test_rlp_json() { for operation in input.into_iter() { match operation { rlptest::Operation::Append(ref v) => stream.append(v), - rlptest::Operation::AppendList(len) => stream.append_list(len), + rlptest::Operation::AppendList(len) => stream.begin_list(len), rlptest::Operation::AppendRaw(ref raw, len) => stream.append_raw(raw, len), rlptest::Operation::AppendEmpty => stream.append_empty_data() }; @@ -346,7 +350,7 @@ fn test_rlp_json() { #[test] fn test_decoding_array() { let v = vec![5u16, 2u16]; - let res = rlp::encode(&v); + let res = rlp::encode_list(&v); let arr: [u16; 2] = rlp::decode(&res); assert_eq!(arr[0], 5); assert_eq!(arr[1], 2); diff --git a/util/src/trie/node.rs b/util/src/trie/node.rs index dad5830b2..c47a0d25f 100644 --- a/util/src/trie/node.rs +++ b/util/src/trie/node.rs @@ -89,17 +89,17 @@ impl<'a> Node<'a> { let mut stream = RlpStream::new(); match *self { Node::Leaf(ref slice, ref value) => { - stream.append_list(2); + stream.begin_list(2); stream.append(&slice.encoded(true)); stream.append(value); }, Node::Extension(ref slice, ref raw_rlp) => { - stream.append_list(2); + stream.begin_list(2); stream.append(&slice.encoded(false)); stream.append_raw(raw_rlp, 1); }, Node::Branch(ref nodes, ref value) => { - stream.append_list(17); + stream.begin_list(17); for i in 0..16 { stream.append_raw(nodes[i], 1); } diff --git a/util/src/trie/triedbmut.rs b/util/src/trie/triedbmut.rs index 48749bf0d..5baffee8e 100644 --- a/util/src/trie/triedbmut.rs +++ b/util/src/trie/triedbmut.rs @@ -684,11 +684,11 @@ mod tests { fn random_value_indexed(j: usize) -> Bytes { match random::() % 2 { - 0 => encode(&j), + 0 => encode(&j).to_vec(), _ => { let mut h = H256::new(); h.as_slice_mut()[31] = j as u8; - encode(&h) + encode(&h).to_vec() }, } } @@ -1035,7 +1035,7 @@ mod tests { let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; for j in 0..4u32 { let key = random_key(alphabet, 5, 1); - x.push((key, encode(&j))); + x.push((key, encode(&j).to_vec())); } let real = trie_root(x.clone()); let mut memdb = MemoryDB::new(); diff --git a/util/src/triehash.rs b/util/src/triehash.rs index 66f9072b8..6ff6b790d 100644 --- a/util/src/triehash.rs +++ b/util/src/triehash.rs @@ -30,7 +30,7 @@ pub fn ordered_trie_root(input: Vec>) -> H256 { // optimize it later .into_iter() .enumerate() - .fold(BTreeMap::new(), | mut acc, (i, vec) | { acc.insert(rlp::encode(&i), vec); acc }) + .fold(BTreeMap::new(), | mut acc, (i, vec) | { acc.insert(rlp::encode(&i).to_vec(), vec); acc }) // then move them to a vector .into_iter() .map(|(k, v)| (as_nibbles(&k), v) ) @@ -189,7 +189,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // if the slice contains just one item, append the suffix of the key // and then append value if inlen == 1 { - stream.append_list(2); + stream.begin_list(2); stream.append(&hex_prefix_encode(&key[pre_len..], true)); stream.append(&value); return; @@ -208,7 +208,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // new part of the key to the stream // then recursively append suffixes of all items who had this key if shared_prefix > pre_len { - stream.append_list(2); + stream.begin_list(2); stream.append(&hex_prefix_encode(&key[pre_len..shared_prefix], false)); hash256aux(input, shared_prefix, stream); return; @@ -216,7 +216,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // an item for every possible nibble/suffix // + 1 for data - stream.append_list(17); + stream.begin_list(17); // if first key len is equal to prefix_len, move to next element let mut begin = match pre_len == key.len() {