diff --git a/Cargo.toml b/Cargo.toml index bcd5fceb0ca..778df551d01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ bytes = "" crypto-mac = "^0.6.2" clap = "2.32.0" dirs = "1.0.3" -ethereum-types = "" +ethereum-types = "0.4.0" futures = "0.1.23" network-libp2p = { path = "network-libp2p" } rand = "0.3" diff --git a/ssz/Cargo.toml b/ssz/Cargo.toml index 0500ab3c5c3..aa4dc5d72cc 100644 --- a/ssz/Cargo.toml +++ b/ssz/Cargo.toml @@ -5,4 +5,4 @@ authors = ["Paul Hauner "] [dependencies] bytes = "0.4.9" -ethereum-types = "" +ethereum-types = "0.4.0" diff --git a/ssz/src/decode.rs b/ssz/src/decode.rs index d726a58320e..9d4132be8d2 100644 --- a/ssz/src/decode.rs +++ b/ssz/src/decode.rs @@ -10,59 +10,76 @@ pub enum DecodeError { } pub trait Decodable: Sized { - fn ssz_decode(bytes: &[u8]) -> Result; + fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError>; } -/// Decode the nth element of some ssz list. +/// Decode the given bytes for the given type /// -/// A single ssz encoded value can be considered a list of -/// one element, so this function will work on it too. -pub fn decode_ssz_list_element(ssz_bytes: &[u8], n: usize) - -> Result +/// The single ssz encoded value will be decoded as the given type at the +/// given index. +pub fn decode_ssz(ssz_bytes: &[u8], index: usize) + -> Result<(T, usize), DecodeError> where T: Decodable { - T::ssz_decode(nth_value(ssz_bytes, n)?) + if index >= ssz_bytes.len() { + return Err(DecodeError::OutOfBounds) + } + T::ssz_decode(ssz_bytes, index) } -/// Return the nth value in some ssz encoded list. -/// -/// The four-byte length prefix is not included in the return. +/// Decode a vector (list) of encoded bytes. /// -/// A single ssz encoded value can be considered a list of -/// one element, so this function will work on it too. -fn nth_value(ssz_bytes: &[u8], n: usize) - -> Result<&[u8], DecodeError> +/// Each element in the list will be decoded and placed into the vector. +pub fn decode_ssz_list(ssz_bytes: &[u8], index: usize) + -> Result<(Vec, usize), DecodeError> + where T: Decodable { - let mut c: usize = 0; - for i in 0..(n + 1) { - let length = decode_length(&ssz_bytes[c..], LENGTH_BYTES)?; - let next = c + LENGTH_BYTES + length; - - if i == n { - return Ok(&ssz_bytes[c + LENGTH_BYTES..next]); - } else { - if next >= ssz_bytes.len() { - return Err(DecodeError::OutOfBounds); - } else { - c = next; - } - } - } - Err(DecodeError::OutOfBounds) + + if index + LENGTH_BYTES > ssz_bytes.len() { + return Err(DecodeError::TooShort); + }; + + // get the length + let serialized_length = match decode_length(ssz_bytes, index, LENGTH_BYTES) { + Err(v) => return Err(v), + Ok(v) => v, + }; + + let final_len: usize = index + LENGTH_BYTES + serialized_length; + + if final_len > ssz_bytes.len() { + return Err(DecodeError::TooShort); + }; + + let mut tmp_index = index + LENGTH_BYTES; + let mut res_vec: Vec = Vec::new(); + + while tmp_index < final_len { + match T::ssz_decode(ssz_bytes, tmp_index) { + Err(v) => return Err(v), + Ok(v) => { + tmp_index = v.1; + res_vec.push(v.0); + }, + }; + + }; + + Ok((res_vec, final_len)) } /// Given some number of bytes, interpret the first four /// bytes as a 32-bit big-endian integer and return the /// result. -fn decode_length(bytes: &[u8], length_bytes: usize) +pub fn decode_length(bytes: &[u8], index: usize, length_bytes: usize) -> Result { if bytes.len() < length_bytes { return Err(DecodeError::TooShort); }; let mut len: usize = 0; - for i in 0..length_bytes { - let offset = (length_bytes - i - 1) * 8; + for i in index..index+length_bytes { + let offset = (index+length_bytes - i - 1) * 8; len = ((bytes[i] as usize) << offset) | len; }; Ok(len) @@ -76,24 +93,28 @@ mod tests { #[test] fn test_ssz_decode_length() { let decoded = decode_length( - &vec![0, 0, 1], + &vec![0, 0, 0, 1], + 0, LENGTH_BYTES); assert_eq!(decoded.unwrap(), 1); let decoded = decode_length( - &vec![0, 1, 0], + &vec![0, 0, 1, 0], + 0, LENGTH_BYTES); assert_eq!(decoded.unwrap(), 256); let decoded = decode_length( - &vec![0, 1, 255], + &vec![0, 0, 1, 255], + 0, LENGTH_BYTES); assert_eq!(decoded.unwrap(), 511); let decoded = decode_length( - &vec![255, 255, 255], + &vec![255, 255, 255, 255], + 0, LENGTH_BYTES); - assert_eq!(decoded.unwrap(), 16777215); + assert_eq!(decoded.unwrap(), 4294967295); } #[test] @@ -108,28 +129,82 @@ mod tests { for i in params { let decoded = decode_length( &encode_length(i, LENGTH_BYTES), + 0, LENGTH_BYTES).unwrap(); assert_eq!(i, decoded); } } #[test] - fn test_ssz_nth_value() { - let ssz = vec![0, 0, 1, 0]; - let result = nth_value(&ssz, 0).unwrap(); - assert_eq!(result, vec![0].as_slice()); - - let ssz = vec![0, 0, 4, 1, 2, 3, 4]; - let result = nth_value(&ssz, 0).unwrap(); - assert_eq!(result, vec![1, 2, 3, 4].as_slice()); - - let ssz = vec![0, 0, 1, 0, 0, 0, 1, 1]; - let result = nth_value(&ssz, 1).unwrap(); - assert_eq!(result, vec![1].as_slice()); - - let mut ssz = vec![0, 1, 255]; - ssz.append(&mut vec![42; 511]); - let result = nth_value(&ssz, 0).unwrap(); - assert_eq!(result, vec![42; 511].as_slice()); + fn test_decode_ssz_list() { + // u16 + let v: Vec = vec![10, 10, 10, 10]; + let decoded: (Vec, usize) = decode_ssz_list( + &vec![0, 0, 0, 8, 0, 10, 0, 10, 0, 10, 0, 10], + 0 + ).unwrap(); + + assert_eq!(decoded.0, v); + assert_eq!(decoded.1, 12); + + // u32 + let v: Vec = vec![10, 10, 10, 10]; + let decoded: (Vec, usize) = decode_ssz_list( + &vec![ + 0, 0, 0, 16, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10 + ], + 0 + ).unwrap(); + assert_eq!(decoded.0, v); + assert_eq!(decoded.1, 20); + + + // u64 + let v: Vec = vec![10,10,10,10]; + let decoded: (Vec, usize) = decode_ssz_list( + &vec![0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 10, + ], + 0 + ).unwrap(); + assert_eq!(decoded.0, v); + assert_eq!(decoded.1, 36); + + // Check that it can accept index + let v: Vec = vec![15,15,15,15]; + let decoded: (Vec, usize) = decode_ssz_list( + &vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 15, + 0, 0, 0, 0, 0, 0, 0, 15, + 0, 0, 0, 0, 0, 0, 0, 15, + 0, 0, 0, 0, 0, 0, 0, 15, + ], + 10 + ).unwrap(); + assert_eq!(decoded.0, v); + assert_eq!(decoded.1, 46); + + // Check that length > bytes throws error + let decoded: Result<(Vec, usize), DecodeError> = decode_ssz_list( + &vec![0, 0, 0, 32, + 0, 0, 0, 0, 0, 0, 0, 15, + ], + 0 + ); + assert_eq!(decoded, Err(DecodeError::TooShort)); + + // Check that incorrect index throws error + let decoded: Result<(Vec, usize), DecodeError> = decode_ssz_list( + &vec![ + 0, 0, 0, 0, 0, 0, 0, 15, + ], + 16 + ); + assert_eq!(decoded, Err(DecodeError::TooShort)); } } diff --git a/ssz/src/encode.rs b/ssz/src/encode.rs index 80d07a328c0..5080924ccf0 100644 --- a/ssz/src/encode.rs +++ b/ssz/src/encode.rs @@ -1,4 +1,12 @@ -use super::LENGTH_BYTES; +use super::{ + LENGTH_BYTES, + MAX_LIST_SIZE, +}; + +#[derive(Debug)] +pub enum EncodeError { + ListTooLong, +} pub trait Encodable { fn ssz_append(&self, s: &mut SszStream); @@ -40,6 +48,13 @@ impl SszStream { self.buffer.extend_from_slice(&vec); } + /// Append some ssz encoded bytes to the stream without calculating length + /// + /// The raw bytes will be concatenated to the stream. + pub fn append_encoded_raw(&mut self, vec: &Vec) { + self.buffer.extend_from_slice(&vec); + } + /// Append some vector (list) of encodable values to the stream. /// /// The length of the list will be concatenated to the stream, then @@ -47,10 +62,11 @@ impl SszStream { pub fn append_vec(&mut self, vec: &Vec) where E: Encodable { - self.buffer.extend_from_slice(&encode_length(vec.len(), LENGTH_BYTES)); - for v in vec { - v.ssz_append(self); + let mut list_stream = SszStream::new(); + for item in vec { + item.ssz_append(&mut list_stream); } + self.append_encoded_val(&list_stream.drain()); } /// Consume the stream and return the underlying bytes. @@ -89,29 +105,41 @@ mod tests { fn test_encode_length_4_bytes() { assert_eq!( encode_length(0, LENGTH_BYTES), - vec![0; 3] + vec![0; 4] ); assert_eq!( encode_length(1, LENGTH_BYTES), - vec![0, 0, 1] + vec![0, 0, 0, 1] ); assert_eq!( encode_length(255, LENGTH_BYTES), - vec![0, 0, 255] + vec![0, 0, 0, 255] ); assert_eq!( encode_length(256, LENGTH_BYTES), - vec![0, 1, 0] + vec![0, 0, 1, 0] ); assert_eq!( - encode_length(16777215, LENGTH_BYTES), // 2^(3*8) - 1 - vec![255, 255, 255] + encode_length(4294967295, LENGTH_BYTES), // 2^(3*8) - 1 + vec![255, 255, 255, 255] ); } #[test] #[should_panic] fn test_encode_length_4_bytes_panic() { - encode_length(16777216, LENGTH_BYTES); // 2^(3*8) + encode_length(4294967296, LENGTH_BYTES); // 2^(3*8) + } + + #[test] + fn test_encode_list() { + let test_vec: Vec = vec![256; 12]; + let mut stream = SszStream::new(); + stream.append_vec(&test_vec); + let ssz = stream.drain(); + + assert_eq!(ssz.len(), 4 + (12 * 2)); + assert_eq!(ssz[0..4], *vec![0, 0, 0, 24]); + assert_eq!(ssz[4..6], *vec![1, 0]); } } diff --git a/ssz/src/impl_decode.rs b/ssz/src/impl_decode.rs index 55fdf31e2e8..bbcb9d863fa 100644 --- a/ssz/src/impl_decode.rs +++ b/ssz/src/impl_decode.rs @@ -1,26 +1,30 @@ +use super::ethereum_types::H256; use super::{ DecodeError, Decodable, }; + + macro_rules! impl_decodable_for_uint { ($type: ident, $bit_size: expr) => { impl Decodable for $type { - fn ssz_decode(bytes: &[u8]) - -> Result + fn ssz_decode(bytes: &[u8], index: usize) + -> Result<(Self, usize), DecodeError> { assert!((0 < $bit_size) & ($bit_size <= 64) & ($bit_size % 8 == 0)); let max_bytes = $bit_size / 8; - if bytes.len() <= max_bytes { + if bytes.len() >= (index + max_bytes) { + let end_bytes = index + max_bytes; let mut result: $type = 0; - for i in 0..bytes.len() { - let offset = (bytes.len() - i - 1) * 8; + for i in index..end_bytes { + let offset = ((index + max_bytes) - i - 1) * 8; result = ((bytes[i] as $type) << offset) | result; }; - Ok(result) + Ok((result, end_bytes)) } else { - Err(DecodeError::TooLong) + Err(DecodeError::TooShort) } } } @@ -32,83 +36,184 @@ impl_decodable_for_uint!(u32, 32); impl_decodable_for_uint!(u64, 64); impl_decodable_for_uint!(usize, 64); +impl Decodable for H256 { + fn ssz_decode(bytes: &[u8], index: usize) + -> Result<(Self, usize), DecodeError> + { + if bytes.len() < 32 { + return Err(DecodeError::TooShort) + } + else if bytes.len() - 32 < index { + return Err(DecodeError::TooShort) + } + else { + return Ok((H256::from(&bytes[index..(index + 32)]), + index + 32)); + } + } +} #[cfg(test)] mod tests { + use super::*; use super::super::{ DecodeError, - decode_ssz_list_element, + decode_ssz, }; + #[test] + fn test_ssz_decode_h256() { + /* + * Input is exact length + */ + let input = vec![42_u8; 32]; + let (decoded, i) = H256::ssz_decode(&input, 0).unwrap(); + assert_eq!(decoded.to_vec(), input); + assert_eq!(i, 32); + + /* + * Input is too long + */ + let mut input = vec![42_u8; 32]; + input.push(12); + let (decoded, i) = H256::ssz_decode(&input, 0).unwrap(); + assert_eq!(decoded.to_vec()[..], input[0..32]); + assert_eq!(i, 32); + + /* + * Input is too short + */ + let input = vec![42_u8; 31]; + let res = H256::ssz_decode(&input, 0); + assert_eq!(res, Err(DecodeError::TooShort)); + } + #[test] fn test_ssz_decode_u16() { - let ssz = vec![0, 0, 1, 0]; - let result: u16 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![0, 0]; + + let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap(); assert_eq!(result, 0); + assert_eq!(index, 2); - let ssz = vec![0, 0, 1, 16]; - let result: u16 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![0, 16]; + let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap(); assert_eq!(result, 16); + assert_eq!(index, 2); - let ssz = vec![0, 0, 2, 1, 0]; - let result: u16 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![1, 0]; + let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap(); assert_eq!(result, 256); + assert_eq!(index, 2); - let ssz = vec![0, 0, 2, 255, 255]; - let result: u16 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![255, 255]; + let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 2); assert_eq!(result, 65535); - let ssz = vec![0, 0, 3, 0, 0, 1]; - let result: Result = - decode_ssz_list_element(&ssz, 0); - assert_eq!(result, Err(DecodeError::TooLong)); + let ssz = vec![1]; + let result: Result<(u16, usize), DecodeError> = + decode_ssz(&ssz, 0); + assert_eq!(result, Err(DecodeError::TooShort)); } #[test] fn test_ssz_decode_u32() { - let ssz = vec![0, 0, 1, 0]; - let result: u32 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![0, 0, 0, 0]; + let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap(); assert_eq!(result, 0); + assert_eq!(index, 4); + + let ssz = vec![0, 0, 1, 0]; + let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 4); + assert_eq!(result, 256); + + let ssz = vec![255, 255, 255, 0, 0, 1, 0]; + let (result, index): (u32, usize) = decode_ssz(&ssz, 3).unwrap(); + assert_eq!(index, 7); + assert_eq!(result, 256); - let ssz = vec![0, 0, 4, 255, 255, 255, 255]; - let result: u32 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![0,200, 1, 0]; + let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 4); + assert_eq!(result, 13107456); + + let ssz = vec![255, 255, 255, 255]; + let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 4); assert_eq!(result, 4294967295); - let ssz = vec![0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 1]; - let result: Result = - decode_ssz_list_element(&ssz, 0); - assert_eq!(result, Err(DecodeError::TooLong)); + let ssz = vec![0, 0, 1]; + let result: Result<(u32, usize), DecodeError> = + decode_ssz(&ssz, 0); + assert_eq!(result, Err(DecodeError::TooShort)); } #[test] fn test_ssz_decode_u64() { - let ssz = vec![0, 0, 1, 0]; - let result: u64 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0]; + let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 8); assert_eq!(result, 0); - let ssz = vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255]; - let result: u64 = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255]; + let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 8); assert_eq!(result, 18446744073709551615); - let ssz = vec![0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 1]; - let result: Result = - decode_ssz_list_element(&ssz, 0); - assert_eq!(result, Err(DecodeError::TooLong)); + let ssz = vec![0, 0, 8, 255, 0, 0, 0, 0, 0, 0, 0]; + let (result, index): (u64, usize) = decode_ssz(&ssz, 3).unwrap(); + assert_eq!(index, 11); + assert_eq!(result, 18374686479671623680); + + let ssz = vec![0,0,0,0,0,0,0]; + let result: Result<(u64, usize), DecodeError> = + decode_ssz(&ssz, 0); + assert_eq!(result, Err(DecodeError::TooShort)); } #[test] fn test_ssz_decode_usize() { - let ssz = vec![0, 0, 1, 0]; - let result: usize = decode_ssz_list_element(&ssz, 0).unwrap(); + let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0]; + let (result, index): (usize, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 8); assert_eq!(result, 0); let ssz = vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255]; - let result: usize = decode_ssz_list_element(&ssz, 0).unwrap(); + let (result, index): (usize, usize) = decode_ssz(&ssz, 3).unwrap(); + assert_eq!(index, 11); + assert_eq!(result, 18446744073709551615); + + let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255, 255]; + let (result, index): (usize, usize) = decode_ssz(&ssz, 0).unwrap(); + assert_eq!(index, 8); assert_eq!(result, 18446744073709551615); - let ssz = vec![0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 1]; - let result: Result = - decode_ssz_list_element(&ssz, 0); - assert_eq!(result, Err(DecodeError::TooLong)); + let ssz = vec![0, 0, 0, 0, 0, 0, 1]; + let result: Result<(usize, usize), DecodeError> = + decode_ssz(&ssz, 0); + assert_eq!(result, Err(DecodeError::TooShort)); + } + + #[test] + fn test_decode_ssz_bounds() { + let err: Result<(u16, usize), DecodeError> = decode_ssz( + &vec![1], + 2 + ); + assert_eq!(err, Err(DecodeError::OutOfBounds)); + + let err: Result<(u16,usize), DecodeError> = decode_ssz( + &vec![0, 0, 0, 0], + 3 + ); + assert_eq!(err, Err(DecodeError::TooShort)); + + let result: u16 = decode_ssz( + &vec![0,0,0,0,1], + 3 + ).unwrap().0; + assert_eq!(result, 1); } } diff --git a/ssz/src/impl_encode.rs b/ssz/src/impl_encode.rs index 88b4c1edc81..392f8667e02 100644 --- a/ssz/src/impl_encode.rs +++ b/ssz/src/impl_encode.rs @@ -1,8 +1,11 @@ +extern crate bytes; + use super::{ Encodable, SszStream }; -use super::ethereum_types::{ H256, U256 }; +use super::ethereum_types::H256; +use self::bytes::{ BytesMut, BufMut }; /* * Note: there is a "to_bytes" function for integers @@ -10,52 +13,43 @@ use super::ethereum_types::{ H256, U256 }; * use it instead. */ macro_rules! impl_encodable_for_uint { - ($type: ident) => { + ($type: ident, $bit_size: expr) => { impl Encodable for $type { fn ssz_append(&self, s: &mut SszStream) { - // Number of bits required to represent this integer. - // This could be optimised at the expense of complexity. - let num_bits = { - let mut n = *self; - let mut r: usize = 0; - while n > 0 { - n >>= 1; - r += 1; - } - if r == 0 { 1 } else { r } - }; - // Number of bytes required to represent this bit - let num_bytes = (num_bits + 8 - 1) / 8; - let mut ssz_val: Vec = Vec::with_capacity(num_bytes); - ssz_val.resize(num_bytes, 0); - for i in (0..num_bytes).rev() { - let offset = (num_bytes - i - 1) * 8; - ssz_val[i] = 0_u8 | (self >> offset) as u8 + // Ensure bit size is valid + assert!((0 < $bit_size) && + ($bit_size % 8 == 0) && + (2_u128.pow($bit_size) > *self as u128)); + + // Serialize to bytes + let mut buf = BytesMut::with_capacity($bit_size/8); + + // Match bit size with encoding + match $bit_size { + 8 => buf.put_u8(*self as u8), + 16 => buf.put_u16_be(*self as u16), + 32 => buf.put_u32_be(*self as u32), + 64 => buf.put_u64_be(*self as u64), + _ => { ; } } - s.append_encoded_val(&ssz_val); + + // Append bytes to the SszStream + s.append_encoded_raw(&mut buf.to_vec()); } } } } -impl_encodable_for_uint!(u8); -impl_encodable_for_uint!(u16); -impl_encodable_for_uint!(u32); -impl_encodable_for_uint!(u64); -impl_encodable_for_uint!(usize); +impl_encodable_for_uint!(u8, 8); +impl_encodable_for_uint!(u16, 16); +impl_encodable_for_uint!(u32, 32); +impl_encodable_for_uint!(u64, 64); +impl_encodable_for_uint!(usize, 64); impl Encodable for H256 { fn ssz_append(&self, s: &mut SszStream) { - s.append_encoded_val(&self.to_vec()); - } -} - -impl Encodable for U256 { - fn ssz_append(&self, s: &mut SszStream) { - let mut a = [0; 32]; - self.to_big_endian(&mut a); - s.append_encoded_val(&a.to_vec()); + s.append_encoded_raw(&self.to_vec()); } } @@ -64,27 +58,35 @@ impl Encodable for U256 { mod tests { use super::*; + #[test] + fn test_ssz_encode_h256() { + let h = H256::zero(); + let mut ssz = SszStream::new(); + ssz.append(&h); + assert_eq!(ssz.drain(), vec![0; 32]); + } + #[test] fn test_ssz_encode_u8() { - let x: u16 = 0; + let x: u8 = 0; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 0]); + assert_eq!(ssz.drain(), vec![0]); - let x: u16 = 1; + let x: u8 = 1; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 1]); + assert_eq!(ssz.drain(), vec![1]); - let x: u16 = 100; + let x: u8 = 100; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 100]); + assert_eq!(ssz.drain(), vec![100]); - let x: u16 = 255; + let x: u8 = 255; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 255]); + assert_eq!(ssz.drain(), vec![255]); } #[test] @@ -92,22 +94,22 @@ mod tests { let x: u16 = 1; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 1]); + assert_eq!(ssz.drain(), vec![0, 1]); let x: u16 = 100; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 100]); + assert_eq!(ssz.drain(), vec![0, 100]); let x: u16 = 1 << 8; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 2, 1, 0]); + assert_eq!(ssz.drain(), vec![1, 0]); let x: u16 = 65535; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 2, 255, 255]); + assert_eq!(ssz.drain(), vec![255, 255]); } #[test] @@ -115,27 +117,27 @@ mod tests { let x: u32 = 1; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 1]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 1]); let x: u32 = 100; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 100]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 100]); let x: u32 = 1 << 16; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 3, 1, 0, 0]); + assert_eq!(ssz.drain(), vec![0, 1, 0, 0]); let x: u32 = 1 << 24; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 4, 1, 0, 0, 0]); + assert_eq!(ssz.drain(), vec![1, 0, 0, 0]); let x: u32 = !0; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 4, 255, 255, 255, 255]); + assert_eq!(ssz.drain(), vec![255, 255, 255, 255]); } #[test] @@ -143,22 +145,22 @@ mod tests { let x: u64 = 1; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 1]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]); let x: u64 = 100; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 100]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]); let x: u64 = 1 << 32; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 5, 1, 0, 0, 0, 0]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]); let x: u64 = !0; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255]); + assert_eq!(ssz.drain(), vec![255, 255, 255, 255, 255, 255, 255, 255]); } #[test] @@ -166,21 +168,21 @@ mod tests { let x: usize = 1; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 1]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]); let x: usize = 100; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 1, 100]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]); let x: usize = 1 << 32; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 5, 1, 0, 0, 0, 0]); + assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]); let x: usize = !0; let mut ssz = SszStream::new(); ssz.append(&x); - assert_eq!(ssz.drain(), vec![0, 0, 8, 255, 255, 255, 255, 255, 255, 255, 255]); + assert_eq!(ssz.drain(), vec![255, 255, 255, 255, 255, 255, 255, 255]); } } diff --git a/ssz/src/lib.rs b/ssz/src/lib.rs index b5091c1fb34..bf0de9262ac 100644 --- a/ssz/src/lib.rs +++ b/ssz/src/lib.rs @@ -10,19 +10,22 @@ extern crate bytes; extern crate ethereum_types; +pub mod decode; + mod encode; -mod decode; mod impl_encode; mod impl_decode; pub use decode::{ Decodable, DecodeError, - decode_ssz_list_element, + decode_ssz, + decode_ssz_list, }; pub use encode::{ Encodable, SszStream, }; -pub const LENGTH_BYTES: usize = 3; +pub const LENGTH_BYTES: usize = 4; +pub const MAX_LIST_SIZE : usize = 1 << (4 * 8);