Merge ssz little endian branch
This commit is contained in:
commit
864ef137ef
@ -1,6 +1,6 @@
|
||||
use super::BLOCKS_DB_COLUMN as DB_COLUMN;
|
||||
use super::{ClientDB, DBError};
|
||||
use ssz::Decodable;
|
||||
use ssz::decode;
|
||||
use std::sync::Arc;
|
||||
use types::{BeaconBlock, Hash256, Slot};
|
||||
|
||||
@ -30,7 +30,7 @@ impl<T: ClientDB> BeaconBlockStore<T> {
|
||||
match self.get(&hash)? {
|
||||
None => Ok(None),
|
||||
Some(ssz) => {
|
||||
let (block, _) = BeaconBlock::ssz_decode(&ssz, 0).map_err(|_| DBError {
|
||||
let block = decode::<BeaconBlock>(&ssz).map_err(|_| DBError {
|
||||
message: "Bad BeaconBlock SSZ.".to_string(),
|
||||
})?;
|
||||
Ok(Some(block))
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::STATES_DB_COLUMN as DB_COLUMN;
|
||||
use super::{ClientDB, DBError};
|
||||
use ssz::Decodable;
|
||||
use ssz::decode;
|
||||
use std::sync::Arc;
|
||||
use types::{BeaconState, Hash256};
|
||||
|
||||
@ -23,7 +23,7 @@ impl<T: ClientDB> BeaconStateStore<T> {
|
||||
match self.get(&hash)? {
|
||||
None => Ok(None),
|
||||
Some(ssz) => {
|
||||
let (state, _) = BeaconState::ssz_decode(&ssz, 0).map_err(|_| DBError {
|
||||
let state = decode::<BeaconState>(&ssz).map_err(|_| DBError {
|
||||
message: "Bad State SSZ.".to_string(),
|
||||
})?;
|
||||
Ok(Some(state))
|
||||
|
@ -4,7 +4,7 @@ use self::bytes::{BufMut, BytesMut};
|
||||
use super::VALIDATOR_DB_COLUMN as DB_COLUMN;
|
||||
use super::{ClientDB, DBError};
|
||||
use bls::PublicKey;
|
||||
use ssz::{ssz_encode, Decodable};
|
||||
use ssz::{decode, ssz_encode};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -69,8 +69,8 @@ impl<T: ClientDB> ValidatorStore<T> {
|
||||
let val = self.db.get(DB_COLUMN, &key[..])?;
|
||||
match val {
|
||||
None => Ok(None),
|
||||
Some(val) => match PublicKey::ssz_decode(&val, 0) {
|
||||
Ok((key, _)) => Ok(Some(key)),
|
||||
Some(val) => match decode::<PublicKey>(&val) {
|
||||
Ok(key) => Ok(Some(key)),
|
||||
Err(_) => Err(ValidatorStoreError::DecodeError),
|
||||
},
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use protos::services::{
|
||||
};
|
||||
use protos::services_grpc::ValidatorService;
|
||||
use slog::{debug, Logger};
|
||||
use ssz::Decodable;
|
||||
use ssz::decode;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ValidatorServiceInstance {
|
||||
@ -20,7 +20,7 @@ impl ValidatorService for ValidatorServiceInstance {
|
||||
req: PublicKeyRequest,
|
||||
sink: UnarySink<IndexResponse>,
|
||||
) {
|
||||
if let Ok((public_key, _)) = PublicKey::ssz_decode(req.get_public_key(), 0) {
|
||||
if let Ok(public_key) = decode::<PublicKey>(req.get_public_key()) {
|
||||
debug!(self.log, "RPC request"; "endpoint" => "ValidatorIndex", "public_key" => public_key.concatenated_hex_id());
|
||||
|
||||
let mut resp = IndexResponse::new();
|
||||
|
@ -130,4 +130,15 @@ mod epoch_tests {
|
||||
assert_eq!(Slot::from(i), slots[i as usize])
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_epoch_ssz() {
|
||||
let max_epoch = Epoch::max_value();
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&max_epoch);
|
||||
let encoded = ssz.drain();
|
||||
assert_eq!(&encoded, &[255, 255, 255, 255, 255, 255, 255, 255]);
|
||||
let (decoded, _i): (Epoch, usize) = <_>::ssz_decode(&encoded, 0).unwrap();
|
||||
assert_eq!(max_epoch, decoded);
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,13 @@ macro_rules! ssz_tests {
|
||||
#[test]
|
||||
pub fn test_ssz_round_trip() {
|
||||
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
|
||||
use ssz::{ssz_encode, Decodable};
|
||||
use ssz::{decode, ssz_encode};
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||
let original = $type::random_for_test(&mut rng);
|
||||
|
||||
let bytes = ssz_encode(&original);
|
||||
let (decoded, _) = $type::ssz_decode(&bytes, 0).unwrap();
|
||||
let decoded: $type = decode(&bytes).unwrap();
|
||||
|
||||
assert_eq!(original, decoded);
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ impl TreeHash for AggregateSignature {
|
||||
mod tests {
|
||||
use super::super::{Keypair, Signature};
|
||||
use super::*;
|
||||
use ssz::ssz_encode;
|
||||
use ssz::{decode, ssz_encode};
|
||||
|
||||
#[test]
|
||||
pub fn test_ssz_round_trip() {
|
||||
@ -183,7 +183,7 @@ mod tests {
|
||||
original.add(&Signature::new(&[42, 42], 0, &keypair.sk));
|
||||
|
||||
let bytes = ssz_encode(&original);
|
||||
let (decoded, _) = AggregateSignature::ssz_decode(&bytes, 0).unwrap();
|
||||
let decoded = decode::<AggregateSignature>(&bytes).unwrap();
|
||||
|
||||
assert_eq!(original, decoded);
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ mod aggregate_signature;
|
||||
mod keypair;
|
||||
mod public_key;
|
||||
mod secret_key;
|
||||
mod serde_vistors;
|
||||
mod signature;
|
||||
|
||||
pub use crate::aggregate_public_key::AggregatePublicKey;
|
||||
|
@ -4,7 +4,8 @@ use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use serde_hex::{encode as hex_encode, PrefixedHexVisitor};
|
||||
use ssz::{
|
||||
decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
|
||||
decode, decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream,
|
||||
TreeHash,
|
||||
};
|
||||
use std::default;
|
||||
use std::hash::{Hash, Hasher};
|
||||
@ -90,9 +91,9 @@ impl<'de> Deserialize<'de> for PublicKey {
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
|
||||
let obj = PublicKey::from_bytes(&bytes[..])
|
||||
let pubkey = PublicKey::from_bytes(&bytes[..])
|
||||
.map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e)))?;
|
||||
Ok(obj)
|
||||
Ok(pubkey)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
use super::serde_vistors::HexVisitor;
|
||||
use bls_aggregates::{DecodeError as BlsDecodeError, SecretKey as RawSecretKey};
|
||||
use hex::encode as hex_encode;
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use ssz::{decode_ssz_list, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
||||
use serde_hex::HexVisitor;
|
||||
use ssz::{
|
||||
decode, decode_ssz_list, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
|
||||
};
|
||||
|
||||
/// A single BLS signature.
|
||||
///
|
||||
@ -59,9 +61,9 @@ impl<'de> Deserialize<'de> for SecretKey {
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes = deserializer.deserialize_str(HexVisitor)?;
|
||||
let (pubkey, _) = <_>::ssz_decode(&bytes[..], 0)
|
||||
let secret_key = decode::<SecretKey>(&bytes[..])
|
||||
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
|
||||
Ok(pubkey)
|
||||
Ok(secret_key)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
use hex;
|
||||
use serde::de::{self, Visitor};
|
||||
use std::fmt;
|
||||
|
||||
pub struct HexVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for HexVisitor {
|
||||
type Value = Vec<u8>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a hex string (irrelevant of prefix)")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(hex::decode(value.trim_start_matches("0x"))
|
||||
.map_err(|e| de::Error::custom(format!("invalid hex ({:?})", e)))?)
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
use super::serde_vistors::HexVisitor;
|
||||
use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE};
|
||||
use bls_aggregates::Signature as RawSignature;
|
||||
use hex::encode as hex_encode;
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use serde_hex::HexVisitor;
|
||||
use ssz::{
|
||||
decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
|
||||
decode, decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream,
|
||||
TreeHash,
|
||||
};
|
||||
|
||||
/// A single BLS signature.
|
||||
@ -136,7 +137,7 @@ impl<'de> Deserialize<'de> for Signature {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes: Vec<u8> = deserializer.deserialize_str(HexVisitor)?;
|
||||
let bytes = deserializer.deserialize_str(HexVisitor)?;
|
||||
let signature = Signature::from_bytes(&bytes[..])
|
||||
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
|
||||
Ok(signature)
|
||||
@ -156,7 +157,7 @@ mod tests {
|
||||
let original = Signature::new(&[42, 42], 0, &keypair.sk);
|
||||
|
||||
let bytes = ssz_encode(&original);
|
||||
let (decoded, _) = Signature::ssz_decode(&bytes, 0).unwrap();
|
||||
let decoded = decode::<Signature>(&bytes).unwrap();
|
||||
|
||||
assert_eq!(original, decoded);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use bit_vec::BitVec;
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
use serde_hex::{encode, PrefixedHexVisitor};
|
||||
use ssz::Decodable;
|
||||
use ssz::{Decodable, Encodable};
|
||||
use std::cmp;
|
||||
use std::default;
|
||||
|
||||
@ -144,14 +144,14 @@ impl std::ops::BitAnd for BooleanBitfield {
|
||||
}
|
||||
}
|
||||
|
||||
impl ssz::Encodable for BooleanBitfield {
|
||||
impl Encodable for BooleanBitfield {
|
||||
// ssz_append encodes Self according to the `ssz` spec.
|
||||
fn ssz_append(&self, s: &mut ssz::SszStream) {
|
||||
s.append_vec(&self.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl ssz::Decodable for BooleanBitfield {
|
||||
impl Decodable for BooleanBitfield {
|
||||
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
|
||||
let len = ssz::decode::decode_length(bytes, index, ssz::LENGTH_BYTES)?;
|
||||
if (ssz::LENGTH_BYTES + len) > bytes.len() {
|
||||
@ -210,7 +210,7 @@ impl ssz::TreeHash for BooleanBitfield {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ssz::{ssz_encode, Decodable, SszStream};
|
||||
use ssz::{decode, ssz_encode, SszStream};
|
||||
|
||||
#[test]
|
||||
fn test_new_bitfield() {
|
||||
@ -378,12 +378,12 @@ mod tests {
|
||||
|
||||
let mut stream = SszStream::new();
|
||||
stream.append(&field);
|
||||
assert_eq!(stream.drain(), vec![0, 0, 0, 2, 225, 192]);
|
||||
assert_eq!(stream.drain(), vec![2, 0, 0, 0, 225, 192]);
|
||||
|
||||
let field = BooleanBitfield::from_elem(18, true);
|
||||
let mut stream = SszStream::new();
|
||||
stream.append(&field);
|
||||
assert_eq!(stream.drain(), vec![0, 0, 0, 3, 255, 255, 192]);
|
||||
assert_eq!(stream.drain(), vec![3, 0, 0, 0, 255, 255, 192]);
|
||||
}
|
||||
|
||||
fn create_test_bitfield() -> BooleanBitfield {
|
||||
@ -399,13 +399,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_ssz_decode() {
|
||||
let encoded = vec![0, 0, 0, 2, 225, 192];
|
||||
let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
|
||||
let encoded = vec![2, 0, 0, 0, 225, 192];
|
||||
let field = decode::<BooleanBitfield>(&encoded).unwrap();
|
||||
let expected = create_test_bitfield();
|
||||
assert_eq!(field, expected);
|
||||
|
||||
let encoded = vec![0, 0, 0, 3, 255, 255, 3];
|
||||
let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
|
||||
let encoded = vec![3, 0, 0, 0, 255, 255, 3];
|
||||
let field = decode::<BooleanBitfield>(&encoded).unwrap();
|
||||
let expected = BooleanBitfield::from_bytes(&[255, 255, 3]);
|
||||
assert_eq!(field, expected);
|
||||
}
|
||||
@ -414,7 +414,7 @@ mod tests {
|
||||
fn test_ssz_round_trip() {
|
||||
let original = BooleanBitfield::from_bytes(&vec![18; 12][..]);
|
||||
let ssz = ssz_encode(&original);
|
||||
let (decoded, _) = BooleanBitfield::ssz_decode(&ssz, 0).unwrap();
|
||||
let decoded = decode::<BooleanBitfield>(&ssz).unwrap();
|
||||
assert_eq!(original, decoded);
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,24 @@ impl<'de> Visitor<'de> for PrefixedHexVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HexVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for HexVisitor {
|
||||
type Value = Vec<u8>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a hex string (irrelevant of prefix)")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(hex::decode(value.trim_start_matches("0x"))
|
||||
.map_err(|e| de::Error::custom(format!("invalid hex ({:?})", e)))?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -8,3 +8,5 @@ edition = "2018"
|
||||
bytes = "0.4.9"
|
||||
ethereum-types = "0.5"
|
||||
hashing = { path = "../hashing" }
|
||||
hex = "0.3"
|
||||
yaml-rust = "0.4"
|
||||
|
@ -69,7 +69,7 @@ Syntax:
|
||||
|
||||
| Shorthand | Meaning |
|
||||
|:-------------|:----------------------------------------------------|
|
||||
| `big` | ``big endian`` |
|
||||
| `little` | ``little endian`` |
|
||||
| `to_bytes` | convert to bytes. Params: ``(size, byte order)`` |
|
||||
| `from_bytes` | convert from bytes. Params: ``(bytes, byte order)`` |
|
||||
| `value` | the value to serialize |
|
||||
@ -82,7 +82,7 @@ Syntax:
|
||||
|
||||
Convert directly to bytes the size of the int. (e.g. ``int16 = 2 bytes``)
|
||||
|
||||
All integers are serialized as **big endian**.
|
||||
All integers are serialized as **little endian**.
|
||||
|
||||
| Check to perform | Code |
|
||||
|:-----------------------|:------------------------|
|
||||
@ -92,7 +92,7 @@ All integers are serialized as **big endian**.
|
||||
|
||||
```python
|
||||
buffer_size = int_size / 8
|
||||
return value.to_bytes(buffer_size, 'big')
|
||||
return value.to_bytes(buffer_size, 'little')
|
||||
```
|
||||
|
||||
#### Address
|
||||
@ -131,7 +131,7 @@ For general `byte` type:
|
||||
value_bytes ]``
|
||||
|
||||
```python
|
||||
byte_length = (len(value)).to_bytes(4, 'big')
|
||||
byte_length = (len(value)).to_bytes(4, 'little')
|
||||
return byte_length + value
|
||||
```
|
||||
|
||||
@ -175,12 +175,12 @@ At each step, the following checks should be made:
|
||||
Convert directly from bytes into integer utilising the number of bytes the same
|
||||
size as the integer length. (e.g. ``int16 == 2 bytes``)
|
||||
|
||||
All integers are interpreted as **big endian**.
|
||||
All integers are interpreted as **little endian**.
|
||||
|
||||
```python
|
||||
byte_length = int_size / 8
|
||||
new_index = current_index + int_size
|
||||
return int.from_bytes(rawbytes[current_index:current_index+int_size], 'big'), new_index
|
||||
return int.from_bytes(rawbytes[current_index:current_index+int_size], 'little'), new_index
|
||||
```
|
||||
|
||||
#### Address
|
||||
@ -206,7 +206,7 @@ return rawbytes[current_index:current_index+32], new_index
|
||||
Get the length of the bytes, return the bytes.
|
||||
|
||||
```python
|
||||
bytes_length = int.from_bytes(rawbytes[current_index:current_index+4], 'big')
|
||||
bytes_length = int.from_bytes(rawbytes[current_index:current_index+4], 'little')
|
||||
new_index = current_index + 4 + bytes_lenth
|
||||
return rawbytes[current_index+4:current_index+4+bytes_length], new_index
|
||||
```
|
||||
@ -224,7 +224,7 @@ entire length of the list.
|
||||
| rawbytes has enough left for length | ``len(rawbytes) > current_index + 4`` |
|
||||
|
||||
```python
|
||||
total_length = int.from_bytes(rawbytes[current_index:current_index+4], 'big')
|
||||
total_length = int.from_bytes(rawbytes[current_index:current_index+4], 'little')
|
||||
new_index = current_index + 4 + total_length
|
||||
item_index = current_index + 4
|
||||
deserialized_list = []
|
||||
|
@ -9,7 +9,7 @@ publish = false
|
||||
cargo-fuzz = true
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.4.0"
|
||||
ethereum-types = "0.5"
|
||||
|
||||
[dependencies.ssz]
|
||||
path = ".."
|
||||
@ -84,22 +84,22 @@ path = "fuzz_targets/fuzz_target_address_decode.rs"
|
||||
name = "fuzz_target_address_encode"
|
||||
path = "fuzz_targets/fuzz_target_address_encode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_target_vec_decode"
|
||||
path = "fuzz_targets/fuzz_target_vec_decode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_target_vec_address_decode"
|
||||
path = "fuzz_targets/fuzz_target_vec_address_decode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_target_vec_u64_decode"
|
||||
path = "fuzz_targets/fuzz_target_vec_u64_decode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_target_vec_bool_decode"
|
||||
path = "fuzz_targets/fuzz_target_vec_bool_decode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_target_vec_decode"
|
||||
path = "fuzz_targets/fuzz_target_vec_decode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_target_vec_encode"
|
||||
path = "fuzz_targets/fuzz_target_vec_encode.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_target_vec_u64_decode"
|
||||
path = "fuzz_targets/fuzz_target_vec_u64_decode.rs"
|
||||
|
@ -4,18 +4,17 @@ extern crate ethereum_types;
|
||||
extern crate ssz;
|
||||
|
||||
use ethereum_types::Address;
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let result: Result<(Address, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 20 {
|
||||
let result: Result<Address, DecodeError> = decode(data);
|
||||
if data.len() == 20 {
|
||||
// Should have valid result
|
||||
let (address, index) = result.unwrap();
|
||||
assert_eq!(index, 20);
|
||||
let address = result.unwrap();
|
||||
assert_eq!(address, Address::from_slice(&data[..20]));
|
||||
} else {
|
||||
// Length of less than 32 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -2,27 +2,23 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let result: Result<(bool, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 1 {
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
if data[0] == u8::pow(2,7) {
|
||||
let (val_bool, index) = result.unwrap();
|
||||
let result: Result<bool, DecodeError> = decode(data);
|
||||
if data.len() == 1 {
|
||||
if data[0] == 1 {
|
||||
let val_bool = result.unwrap();
|
||||
assert!(val_bool);
|
||||
assert_eq!(index, 1);
|
||||
} else if data[0] == 0 {
|
||||
let (val_bool, index) = result.unwrap();
|
||||
let val_bool = result.unwrap();
|
||||
assert!(!val_bool);
|
||||
assert_eq!(index, 1);
|
||||
} else {
|
||||
assert_eq!(result, Err(DecodeError::Invalid));
|
||||
}
|
||||
} else {
|
||||
// Length of 0 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -15,8 +15,6 @@ fuzz_target!(|data: &[u8]| {
|
||||
ssz.append(&val_bool);
|
||||
let ssz = ssz.drain();
|
||||
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
assert_eq!(val_bool, ssz[0] % u8::pow(2, 6));
|
||||
assert_eq!(val_bool, ssz[0]);
|
||||
assert_eq!(ssz.len(), 1);
|
||||
});
|
||||
|
@ -4,18 +4,17 @@ extern crate ethereum_types;
|
||||
extern crate ssz;
|
||||
|
||||
use ethereum_types::H256;
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let result: Result<(H256, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 32 {
|
||||
let result: Result<H256, DecodeError> = decode(data);
|
||||
if data.len() == 32 {
|
||||
// Should have valid result
|
||||
let (hash, index) = result.unwrap();
|
||||
assert_eq!(index, 32);
|
||||
let hash = result.unwrap();
|
||||
assert_eq!(hash, H256::from_slice(&data[..32]));
|
||||
} else {
|
||||
// Length of less than 32 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -2,21 +2,18 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let result: Result<(u16, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 2 {
|
||||
let result: Result<u16, DecodeError> = decode(data);
|
||||
if data.len() == 2 {
|
||||
// Valid result
|
||||
let (number_u16, index) = result.unwrap();
|
||||
assert_eq!(index, 2);
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
let val = u16::from_be_bytes([data[0], data[1]]);
|
||||
let number_u16 = result.unwrap();
|
||||
let val = u16::from_le_bytes([data[0], data[1]]);
|
||||
assert_eq!(number_u16, val);
|
||||
} else {
|
||||
// Length of 0 or 1 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -15,8 +15,6 @@ fuzz_target!(|data: &[u8]| {
|
||||
ssz.append(&number_u16);
|
||||
let ssz = ssz.drain();
|
||||
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
assert_eq!(ssz.len(), 2);
|
||||
assert_eq!(number_u16, u16::from_be_bytes([ssz[0], ssz[1]]));
|
||||
assert_eq!(number_u16, u16::from_le_bytes([ssz[0], ssz[1]]));
|
||||
});
|
||||
|
@ -2,21 +2,18 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let result: Result<(u32, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 4 {
|
||||
let result: Result<u32, DecodeError> = decode(data);
|
||||
if data.len() == 4 {
|
||||
// Valid result
|
||||
let (number_u32, index) = result.unwrap();
|
||||
assert_eq!(index, 4);
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
let val = u32::from_be_bytes([data[0], data[1], data[2], data[3]]);
|
||||
let number_u32 = result.unwrap();
|
||||
let val = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
|
||||
assert_eq!(number_u32, val);
|
||||
} else {
|
||||
// Length less then 4 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
// Length not 4 should return error
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -15,8 +15,6 @@ fuzz_target!(|data: &[u8]| {
|
||||
ssz.append(&number_u32);
|
||||
let ssz = ssz.drain();
|
||||
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
assert_eq!(ssz.len(), 4);
|
||||
assert_eq!(number_u32, u32::from_be_bytes([ssz[0], ssz[1], ssz[2], ssz[3]]));
|
||||
assert_eq!(number_u32, u32::from_le_bytes([ssz[0], ssz[1], ssz[2], ssz[3]]));
|
||||
});
|
||||
|
@ -2,18 +2,15 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let result: Result<(u64, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 8 {
|
||||
let result: Result<u64, DecodeError> = decode(data);
|
||||
if data.len() == 8 {
|
||||
// Valid result
|
||||
let (number_u64, index) = result.unwrap();
|
||||
assert_eq!(index, 8);
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
let val = u64::from_be_bytes([
|
||||
let number_u64 = result.unwrap();
|
||||
let val = u64::from_le_bytes([
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
@ -25,7 +22,7 @@ fuzz_target!(|data: &[u8]| {
|
||||
]);
|
||||
assert_eq!(number_u64, val);
|
||||
} else {
|
||||
// Length less then 8 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
// Length not 8 should return error
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -9,7 +9,7 @@ fuzz_target!(|data: &[u8]| {
|
||||
let mut ssz = SszStream::new();
|
||||
let mut number_u64 = 0;
|
||||
if data.len() >= 8 {
|
||||
number_u64 = u64::from_be_bytes([
|
||||
number_u64 = u64::from_le_bytes([
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
@ -24,10 +24,8 @@ fuzz_target!(|data: &[u8]| {
|
||||
ssz.append(&number_u64);
|
||||
let ssz = ssz.drain();
|
||||
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
assert_eq!(ssz.len(), 8);
|
||||
assert_eq!(number_u64, u64::from_be_bytes([
|
||||
assert_eq!(number_u64, u64::from_le_bytes([
|
||||
ssz[0],
|
||||
ssz[1],
|
||||
ssz[2],
|
||||
|
@ -2,20 +2,17 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let result: Result<(u8, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 1 {
|
||||
let result: Result<u8, DecodeError> = decode(data);
|
||||
if data.len() == 1 {
|
||||
// Should have valid result
|
||||
let (number_u8, index) = result.unwrap();
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
assert_eq!(index, 1);
|
||||
let number_u8 = result.unwrap();
|
||||
assert_eq!(number_u8, data[0]);
|
||||
} else {
|
||||
// Length of 0 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
// Length not 1 should return error
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -15,8 +15,6 @@ fuzz_target!(|data: &[u8]| {
|
||||
ssz.append(&number_u8);
|
||||
let ssz = ssz.drain();
|
||||
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
assert_eq!(number_u8, ssz[0]);
|
||||
assert_eq!(ssz.len(), 1);
|
||||
});
|
||||
|
@ -2,19 +2,16 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{DecodeError, decode};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
// Fuzz decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
// Note: we assume architecture is 64 bit -> usize == 64 bits
|
||||
let result: Result<(usize, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
if data.len() >= 8 {
|
||||
let result: Result<usize, DecodeError> = decode(data);
|
||||
if data.len() == 8 {
|
||||
// Valid result
|
||||
let (number_usize, index) = result.unwrap();
|
||||
assert_eq!(index, 8);
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
let val = u64::from_be_bytes([
|
||||
let number_usize = result.unwrap();
|
||||
let val = u64::from_le_bytes([
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
@ -27,6 +24,6 @@ fuzz_target!(|data: &[u8]| {
|
||||
assert_eq!(number_usize, val as usize);
|
||||
} else {
|
||||
// Length less then 8 should return error
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
assert!(result.is_err());
|
||||
}
|
||||
});
|
||||
|
@ -9,7 +9,7 @@ fuzz_target!(|data: &[u8]| {
|
||||
let mut ssz = SszStream::new();
|
||||
let mut number_usize = 0;
|
||||
if data.len() >= 8 {
|
||||
number_usize = u64::from_be_bytes([
|
||||
number_usize = u64::from_le_bytes([
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
@ -24,10 +24,8 @@ fuzz_target!(|data: &[u8]| {
|
||||
ssz.append(&number_usize);
|
||||
let ssz = ssz.drain();
|
||||
|
||||
// TODO: change to little endian bytes
|
||||
// https://github.com/sigp/lighthouse/issues/215
|
||||
assert_eq!(ssz.len(), 8);
|
||||
assert_eq!(number_usize, u64::from_be_bytes([
|
||||
assert_eq!(number_usize, u64::from_le_bytes([
|
||||
ssz[0],
|
||||
ssz[1],
|
||||
ssz[2],
|
||||
|
@ -4,9 +4,9 @@ extern crate ethereum_types;
|
||||
extern crate ssz;
|
||||
|
||||
use ethereum_types::{Address};
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{decode, DecodeError};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _result: Result<(Vec<Address>, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
let _result: Result<Vec<Address>, DecodeError> = decode(data);
|
||||
});
|
||||
|
@ -2,9 +2,9 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{decode, DecodeError};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _result: Result<(Vec<bool>, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
let _result: Result<Vec<bool>, DecodeError> = decode(data);
|
||||
});
|
||||
|
@ -3,10 +3,9 @@
|
||||
extern crate ethereum_types;
|
||||
extern crate ssz;
|
||||
|
||||
use ethereum_types::{Address, H256};
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{decode, DecodeError, Decodable};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _result: Result<(Vec<u8>, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
let _result: Result<Vec<u8>, DecodeError> = decode(data);
|
||||
});
|
||||
|
@ -3,7 +3,6 @@
|
||||
extern crate ethereum_types;
|
||||
extern crate ssz;
|
||||
|
||||
use ethereum_types::{Address, H256};
|
||||
use ssz::SszStream;
|
||||
|
||||
// Fuzz ssz_encode()
|
||||
|
@ -2,9 +2,9 @@
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate ssz;
|
||||
|
||||
use ssz::{DecodeError, Decodable};
|
||||
use ssz::{decode, DecodeError};
|
||||
|
||||
// Fuzz ssz_decode()
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _result: Result<(Vec<u64>, usize), DecodeError> = Decodable::ssz_decode(data, 0);
|
||||
let _result: Result<Vec<u64>, DecodeError> = decode(data);
|
||||
});
|
||||
|
@ -13,16 +13,22 @@ pub trait Decodable: Sized {
|
||||
|
||||
/// Decode the given bytes for the given type
|
||||
///
|
||||
/// The single ssz encoded value will be decoded as the given type at the
|
||||
/// given index.
|
||||
pub fn decode_ssz<T>(ssz_bytes: &[u8], index: usize) -> Result<(T, usize), DecodeError>
|
||||
/// The single ssz encoded value/container/list will be decoded as the given type,
|
||||
/// by recursively calling `ssz_decode`.
|
||||
pub fn decode<T>(ssz_bytes: &[u8]) -> Result<(T), DecodeError>
|
||||
where
|
||||
T: Decodable,
|
||||
{
|
||||
if index >= ssz_bytes.len() {
|
||||
return Err(DecodeError::TooShort);
|
||||
let (decoded, i): (T, usize) = match T::ssz_decode(ssz_bytes, 0) {
|
||||
Err(e) => return Err(e),
|
||||
Ok(v) => v,
|
||||
};
|
||||
|
||||
if i < ssz_bytes.len() {
|
||||
return Err(DecodeError::TooLong);
|
||||
}
|
||||
T::ssz_decode(ssz_bytes, index)
|
||||
|
||||
Ok(decoded)
|
||||
}
|
||||
|
||||
/// Decode a vector (list) of encoded bytes.
|
||||
@ -65,7 +71,7 @@ where
|
||||
}
|
||||
|
||||
/// Given some number of bytes, interpret the first four
|
||||
/// bytes as a 32-bit big-endian integer and return the
|
||||
/// bytes as a 32-bit little-endian integer and return the
|
||||
/// result.
|
||||
pub fn decode_length(
|
||||
bytes: &[u8],
|
||||
@ -82,7 +88,7 @@ pub fn decode_length(
|
||||
.take(index + length_bytes)
|
||||
.skip(index)
|
||||
{
|
||||
let offset = (index + length_bytes - i - 1) * 8;
|
||||
let offset = (i - index) * 8;
|
||||
len |= (*byte as usize) << offset;
|
||||
}
|
||||
Ok(len)
|
||||
@ -90,18 +96,18 @@ pub fn decode_length(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::encode::encode_length;
|
||||
use super::super::encode::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ssz_decode_length() {
|
||||
let decoded = decode_length(&vec![0, 0, 0, 1], 0, LENGTH_BYTES);
|
||||
let decoded = decode_length(&vec![1, 0, 0, 0], 0, LENGTH_BYTES);
|
||||
assert_eq!(decoded.unwrap(), 1);
|
||||
|
||||
let decoded = decode_length(&vec![0, 0, 1, 0], 0, LENGTH_BYTES);
|
||||
let decoded = decode_length(&vec![0, 1, 0, 0], 0, LENGTH_BYTES);
|
||||
assert_eq!(decoded.unwrap(), 256);
|
||||
|
||||
let decoded = decode_length(&vec![0, 0, 1, 255], 0, LENGTH_BYTES);
|
||||
let decoded = decode_length(&vec![255, 1, 0, 0], 0, LENGTH_BYTES);
|
||||
assert_eq!(decoded.unwrap(), 511);
|
||||
|
||||
let decoded = decode_length(&vec![255, 255, 255, 255], 0, LENGTH_BYTES);
|
||||
@ -132,21 +138,35 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_decode_ssz_list() {
|
||||
let test_vec: Vec<u16> = vec![256; 12];
|
||||
let mut stream = SszStream::new();
|
||||
stream.append_vec(&test_vec);
|
||||
let ssz = stream.drain();
|
||||
|
||||
// u16
|
||||
let decoded: (Vec<u16>, usize) = decode_ssz_list(&ssz, 0).unwrap();
|
||||
|
||||
assert_eq!(decoded.0, test_vec);
|
||||
assert_eq!(decoded.1, LENGTH_BYTES + (12 * 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_ssz_list() {
|
||||
// u16
|
||||
let v: Vec<u16> = vec![10, 10, 10, 10];
|
||||
let decoded: (Vec<u16>, usize) =
|
||||
decode_ssz_list(&vec![0, 0, 0, 8, 0, 10, 0, 10, 0, 10, 0, 10], 0).unwrap();
|
||||
decode_ssz_list(&vec![8, 0, 0, 0, 10, 0, 10, 0, 10, 0, 10, 0], 0).unwrap();
|
||||
|
||||
assert_eq!(decoded.0, v);
|
||||
assert_eq!(decoded.1, 12);
|
||||
assert_eq!(decoded.1, LENGTH_BYTES + (4 * 2));
|
||||
|
||||
// u32
|
||||
let v: Vec<u32> = vec![10, 10, 10, 10];
|
||||
let decoded: (Vec<u32>, 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,
|
||||
16, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 00,
|
||||
],
|
||||
0,
|
||||
)
|
||||
@ -158,36 +178,37 @@ mod tests {
|
||||
let v: Vec<u64> = vec![10, 10, 10, 10];
|
||||
let decoded: (Vec<u64>, 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,
|
||||
32, 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, 0, 0, 0, 0, 0, 0,
|
||||
],
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(decoded.0, v);
|
||||
assert_eq!(decoded.1, 36);
|
||||
assert_eq!(decoded.1, LENGTH_BYTES + (8 * 4));
|
||||
|
||||
// Check that it can accept index
|
||||
let v: Vec<usize> = vec![15, 15, 15, 15];
|
||||
let offset = 10;
|
||||
let decoded: (Vec<usize>, 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,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 32, 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, 0, 0, 0, 0, 0, 0, 0,
|
||||
],
|
||||
10,
|
||||
offset,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(decoded.0, v);
|
||||
assert_eq!(decoded.1, 46);
|
||||
assert_eq!(decoded.1, offset + LENGTH_BYTES + (8 * 4));
|
||||
|
||||
// Check that length > bytes throws error
|
||||
let decoded: Result<(Vec<usize>, usize), DecodeError> =
|
||||
decode_ssz_list(&vec![0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 15], 0);
|
||||
decode_ssz_list(&vec![32, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0], 0);
|
||||
assert_eq!(decoded, Err(DecodeError::TooShort));
|
||||
|
||||
// Check that incorrect index throws error
|
||||
let decoded: Result<(Vec<usize>, usize), DecodeError> =
|
||||
decode_ssz_list(&vec![0, 0, 0, 0, 0, 0, 0, 15], 16);
|
||||
decode_ssz_list(&vec![15, 0, 0, 0, 0, 0, 0, 0], 16);
|
||||
assert_eq!(decoded, Err(DecodeError::TooShort));
|
||||
}
|
||||
}
|
||||
|
@ -70,13 +70,13 @@ impl SszStream {
|
||||
/// Encode some length into a ssz size prefix.
|
||||
///
|
||||
/// The ssz size prefix is 4 bytes, which is treated as a continuious
|
||||
/// 32bit big-endian integer.
|
||||
/// 32bit little-endian integer.
|
||||
pub fn encode_length(len: usize, length_bytes: usize) -> Vec<u8> {
|
||||
assert!(length_bytes > 0); // For sanity
|
||||
assert!((len as usize) < 2usize.pow(length_bytes as u32 * 8));
|
||||
let mut header: Vec<u8> = vec![0; length_bytes];
|
||||
for (i, header_byte) in header.iter_mut().enumerate() {
|
||||
let offset = (length_bytes - i - 1) * 8;
|
||||
let offset = i * 8;
|
||||
*header_byte = ((len >> offset) & 0xff) as u8;
|
||||
}
|
||||
header
|
||||
@ -95,15 +95,27 @@ mod tests {
|
||||
#[test]
|
||||
fn test_encode_length_4_bytes() {
|
||||
assert_eq!(encode_length(0, LENGTH_BYTES), vec![0; 4]);
|
||||
assert_eq!(encode_length(1, LENGTH_BYTES), vec![0, 0, 0, 1]);
|
||||
assert_eq!(encode_length(255, LENGTH_BYTES), vec![0, 0, 0, 255]);
|
||||
assert_eq!(encode_length(256, LENGTH_BYTES), vec![0, 0, 1, 0]);
|
||||
assert_eq!(encode_length(1, LENGTH_BYTES), vec![1, 0, 0, 0]);
|
||||
assert_eq!(encode_length(255, LENGTH_BYTES), vec![255, 0, 0, 0]);
|
||||
assert_eq!(encode_length(256, LENGTH_BYTES), vec![0, 1, 0, 0]);
|
||||
assert_eq!(
|
||||
encode_length(4294967295, LENGTH_BYTES), // 2^(3*8) - 1
|
||||
vec![255, 255, 255, 255]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_lower_length() {
|
||||
assert_eq!(encode_length(0, LENGTH_BYTES - 2), vec![0; 2]);
|
||||
assert_eq!(encode_length(1, LENGTH_BYTES - 2), vec![1, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_higher_length() {
|
||||
assert_eq!(encode_length(0, LENGTH_BYTES + 2), vec![0; 6]);
|
||||
assert_eq!(encode_length(1, LENGTH_BYTES + 2), vec![1, 0, 0, 0, 0, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_encode_length_4_bytes_panic() {
|
||||
@ -117,8 +129,42 @@ mod tests {
|
||||
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]);
|
||||
assert_eq!(ssz.len(), LENGTH_BYTES + (12 * 2));
|
||||
assert_eq!(ssz[0..4], *vec![24, 0, 0, 0]);
|
||||
assert_eq!(ssz[4..6], *vec![0, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_mixed_prefixed() {
|
||||
let test_vec: Vec<u16> = vec![100, 200];
|
||||
let test_value: u8 = 5;
|
||||
|
||||
let mut stream = SszStream::new();
|
||||
stream.append_vec(&test_vec);
|
||||
stream.append(&test_value);
|
||||
let ssz = stream.drain();
|
||||
|
||||
assert_eq!(ssz.len(), LENGTH_BYTES + (2 * 2) + 1);
|
||||
assert_eq!(ssz[0..4], *vec![4, 0, 0, 0]);
|
||||
assert_eq!(ssz[4..6], *vec![100, 0]);
|
||||
assert_eq!(ssz[6..8], *vec![200, 0]);
|
||||
assert_eq!(ssz[8], 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_mixed_postfixed() {
|
||||
let test_value: u8 = 5;
|
||||
let test_vec: Vec<u16> = vec![100, 200];
|
||||
|
||||
let mut stream = SszStream::new();
|
||||
stream.append(&test_value);
|
||||
stream.append_vec(&test_vec);
|
||||
let ssz = stream.drain();
|
||||
|
||||
assert_eq!(ssz.len(), 1 + LENGTH_BYTES + (2 * 2));
|
||||
assert_eq!(ssz[0], 5);
|
||||
assert_eq!(ssz[1..5], *vec![4, 0, 0, 0]);
|
||||
assert_eq!(ssz[5..7], *vec![100, 0]);
|
||||
assert_eq!(ssz[7..9], *vec![200, 0]);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ macro_rules! impl_decodable_for_uint {
|
||||
let end_bytes = index + max_bytes;
|
||||
let mut result: $type = 0;
|
||||
for (i, byte) in bytes.iter().enumerate().take(end_bytes).skip(index) {
|
||||
let offset = (end_bytes - i - 1) * 8;
|
||||
let offset = (i - index) * 8;
|
||||
result |= ($type::from(*byte)) << offset;
|
||||
}
|
||||
Ok((result, end_bytes))
|
||||
@ -65,7 +65,7 @@ impl Decodable for bool {
|
||||
} else {
|
||||
let result = match bytes[index] {
|
||||
0b0000_0000 => false,
|
||||
0b1000_0000 => true,
|
||||
0b0000_0001 => true,
|
||||
_ => return Err(DecodeError::Invalid),
|
||||
};
|
||||
Ok((result, index + 1))
|
||||
@ -104,7 +104,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{decode_ssz, DecodeError};
|
||||
use super::super::{decode, DecodeError};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
@ -138,139 +138,169 @@ mod tests {
|
||||
fn test_ssz_decode_u16() {
|
||||
let ssz = vec![0, 0];
|
||||
|
||||
let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(result, 0);
|
||||
assert_eq!(index, 2);
|
||||
|
||||
let ssz = vec![0, 16];
|
||||
let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let ssz = vec![16, 0];
|
||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(result, 16);
|
||||
assert_eq!(index, 2);
|
||||
|
||||
let ssz = vec![1, 0];
|
||||
let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let ssz = vec![0, 1];
|
||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(result, 256);
|
||||
assert_eq!(index, 2);
|
||||
|
||||
let ssz = vec![255, 255];
|
||||
let (result, index): (u16, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let (result, index): (u16, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(index, 2);
|
||||
assert_eq!(result, 65535);
|
||||
|
||||
let ssz = vec![1];
|
||||
let result: Result<(u16, usize), DecodeError> = decode_ssz(&ssz, 0);
|
||||
let result: Result<(u16, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssz_decode_u32() {
|
||||
let ssz = vec![0, 0, 0, 0];
|
||||
let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let (result, index): (u32, usize) = <_>::ssz_decode(&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();
|
||||
let ssz = vec![0, 1, 0, 0];
|
||||
let (result, index): (u32, usize) = <_>::ssz_decode(&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();
|
||||
let ssz = vec![255, 255, 255, 0, 1, 0, 0];
|
||||
let (result, index): (u32, usize) = <_>::ssz_decode(&ssz, 3).unwrap();
|
||||
assert_eq!(index, 7);
|
||||
assert_eq!(result, 256);
|
||||
|
||||
let ssz = vec![0, 200, 1, 0];
|
||||
let (result, index): (u32, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let ssz = vec![0, 1, 200, 0];
|
||||
let (result, index): (u32, usize) = <_>::ssz_decode(&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();
|
||||
let (result, index): (u32, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(index, 4);
|
||||
assert_eq!(result, 4294967295);
|
||||
|
||||
let ssz = vec![0, 0, 1];
|
||||
let result: Result<(u32, usize), DecodeError> = decode_ssz(&ssz, 0);
|
||||
let ssz = vec![1, 0, 0];
|
||||
let result: Result<(u32, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssz_decode_u64() {
|
||||
let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
|
||||
let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let (result, index): (u64, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(index, 8);
|
||||
assert_eq!(result, 0);
|
||||
|
||||
let ssz = vec![255, 255, 255, 255, 255, 255, 255, 255];
|
||||
let (result, index): (u64, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let (result, index): (u64, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(index, 8);
|
||||
assert_eq!(result, 18446744073709551615);
|
||||
|
||||
let ssz = vec![0, 0, 8, 255, 0, 0, 0, 0, 0, 0, 0];
|
||||
let (result, index): (u64, usize) = decode_ssz(&ssz, 3).unwrap();
|
||||
let ssz = vec![0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 255];
|
||||
let (result, index): (u64, usize) = <_>::ssz_decode(&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);
|
||||
let result: Result<(u64, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssz_decode_usize() {
|
||||
let ssz = vec![0, 0, 0, 0, 0, 0, 0, 0];
|
||||
let (result, index): (usize, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let (result, index): (usize, usize) = <_>::ssz_decode(&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, index): (usize, usize) = decode_ssz(&ssz, 3).unwrap();
|
||||
let (result, index): (usize, usize) = <_>::ssz_decode(&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();
|
||||
let (result, index): (usize, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(index, 8);
|
||||
assert_eq!(result, 18446744073709551615);
|
||||
|
||||
let ssz = vec![0, 0, 0, 0, 0, 0, 1];
|
||||
let result: Result<(usize, usize), DecodeError> = decode_ssz(&ssz, 0);
|
||||
let result: Result<(usize, usize), DecodeError> = <_>::ssz_decode(&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);
|
||||
let err: Result<(u16, usize), DecodeError> = <_>::ssz_decode(&vec![1], 2);
|
||||
assert_eq!(err, Err(DecodeError::TooShort));
|
||||
|
||||
let err: Result<(u16, usize), DecodeError> = decode_ssz(&vec![0, 0, 0, 0], 3);
|
||||
let err: Result<(u16, usize), DecodeError> = <_>::ssz_decode(&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;
|
||||
let result: u16 = <_>::ssz_decode(&vec![0, 0, 0, 1, 0], 3).unwrap().0;
|
||||
assert_eq!(result, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_ssz_bool() {
|
||||
let ssz = vec![0b0000_0000, 0b1000_0000];
|
||||
let (result, index): (bool, usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
let ssz = vec![0b0000_0000, 0b0000_0001];
|
||||
let (result, index): (bool, usize) = <_>::ssz_decode(&ssz, 0).unwrap();
|
||||
assert_eq!(index, 1);
|
||||
assert_eq!(result, false);
|
||||
|
||||
let (result, index): (bool, usize) = decode_ssz(&ssz, 1).unwrap();
|
||||
let (result, index): (bool, usize) = <_>::ssz_decode(&ssz, 1).unwrap();
|
||||
assert_eq!(index, 2);
|
||||
assert_eq!(result, true);
|
||||
|
||||
let ssz = vec![0b0100_0000];
|
||||
let result: Result<(bool, usize), DecodeError> = decode_ssz(&ssz, 0);
|
||||
let result: Result<(bool, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
||||
assert_eq!(result, Err(DecodeError::Invalid));
|
||||
|
||||
let ssz = vec![];
|
||||
let result: Result<(bool, usize), DecodeError> = <_>::ssz_decode(&ssz, 0);
|
||||
assert_eq!(result, Err(DecodeError::TooShort));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_decode_ssz_list_underflow() {
|
||||
// SSZ encoded (u16::[1, 1, 1], u16::2)
|
||||
let mut encoded = vec![6, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2, 0];
|
||||
let (decoded_array, i): (Vec<u16>, usize) = <_>::ssz_decode(&encoded, 0).unwrap();
|
||||
let (decoded_u16, i): (u16, usize) = <_>::ssz_decode(&encoded, i).unwrap();
|
||||
assert_eq!(decoded_array, vec![1, 1, 1]);
|
||||
assert_eq!(decoded_u16, 2);
|
||||
assert_eq!(i, 12);
|
||||
|
||||
// Underflow
|
||||
encoded[0] = 4; // change length to 4 from 6
|
||||
let (decoded_array, i): (Vec<u16>, usize) = <_>::ssz_decode(&encoded, 0).unwrap();
|
||||
let (decoded_u16, _): (u16, usize) = <_>::ssz_decode(&encoded, i).unwrap();
|
||||
assert_eq!(decoded_array, vec![1, 1]);
|
||||
assert_eq!(decoded_u16, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_too_long() {
|
||||
let encoded = vec![6, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2];
|
||||
let decoded_array: Result<Vec<u16>, DecodeError> = decode(&encoded);
|
||||
assert_eq!(decoded_array, Err(DecodeError::TooLong));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_u8_array() {
|
||||
let ssz = vec![0, 1, 2, 3];
|
||||
let (result, index): ([u8; 4], usize) = decode_ssz(&ssz, 0).unwrap();
|
||||
assert_eq!(index, 4);
|
||||
let result: [u8; 4] = decode(&ssz).unwrap();
|
||||
assert_eq!(result.len(), 4);
|
||||
assert_eq!(result, [0, 1, 2, 3]);
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ macro_rules! impl_encodable_for_uint {
|
||||
// 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),
|
||||
16 => buf.put_u16_le(*self as u16),
|
||||
32 => buf.put_u32_le(*self as u32),
|
||||
64 => buf.put_u64_le(*self as u64),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ impl_encodable_for_u8_array!(4);
|
||||
|
||||
impl Encodable for bool {
|
||||
fn ssz_append(&self, s: &mut SszStream) {
|
||||
let byte = if *self { 0b1000_0000 } else { 0b0000_0000 };
|
||||
let byte = if *self { 0b0000_0001 } else { 0b0000_0000 };
|
||||
s.append_encoded_raw(&[byte]);
|
||||
}
|
||||
}
|
||||
@ -136,17 +136,17 @@ mod tests {
|
||||
let x: u16 = 1;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 1]);
|
||||
assert_eq!(ssz.drain(), vec![1, 0]);
|
||||
|
||||
let x: u16 = 100;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 100]);
|
||||
assert_eq!(ssz.drain(), vec![100, 0]);
|
||||
|
||||
let x: u16 = 1 << 8;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![1, 0]);
|
||||
assert_eq!(ssz.drain(), vec![0, 1]);
|
||||
|
||||
let x: u16 = 65535;
|
||||
let mut ssz = SszStream::new();
|
||||
@ -159,22 +159,22 @@ mod tests {
|
||||
let x: u32 = 1;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 1]);
|
||||
assert_eq!(ssz.drain(), vec![1, 0, 0, 0]);
|
||||
|
||||
let x: u32 = 100;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 100]);
|
||||
assert_eq!(ssz.drain(), vec![100, 0, 0, 0]);
|
||||
|
||||
let x: u32 = 1 << 16;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 1, 0, 0]);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 1, 0]);
|
||||
|
||||
let x: u32 = 1 << 24;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![1, 0, 0, 0]);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 1]);
|
||||
|
||||
let x: u32 = !0;
|
||||
let mut ssz = SszStream::new();
|
||||
@ -187,17 +187,17 @@ mod tests {
|
||||
let x: u64 = 1;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]);
|
||||
assert_eq!(ssz.drain(), vec![1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
let x: u64 = 100;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]);
|
||||
assert_eq!(ssz.drain(), vec![100, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
let x: u64 = 1 << 32;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 1, 0, 0, 0]);
|
||||
|
||||
let x: u64 = !0;
|
||||
let mut ssz = SszStream::new();
|
||||
@ -210,17 +210,17 @@ mod tests {
|
||||
let x: usize = 1;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 1]);
|
||||
assert_eq!(ssz.drain(), vec![1, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
let x: usize = 100;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 0, 0, 0, 100]);
|
||||
assert_eq!(ssz.drain(), vec![100, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
let x: usize = 1 << 32;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 1, 0, 0, 0, 0]);
|
||||
assert_eq!(ssz.drain(), vec![0, 0, 0, 0, 1, 0, 0, 0]);
|
||||
|
||||
let x: usize = !0;
|
||||
let mut ssz = SszStream::new();
|
||||
@ -228,6 +228,27 @@ mod tests {
|
||||
assert_eq!(ssz.drain(), vec![255, 255, 255, 255, 255, 255, 255, 255]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssz_mixed() {
|
||||
let mut stream = SszStream::new();
|
||||
|
||||
let h = Address::zero();
|
||||
let a: u8 = 100;
|
||||
let b: u16 = 65535;
|
||||
let c: u32 = 1 << 24;
|
||||
|
||||
stream.append(&h);
|
||||
stream.append(&a);
|
||||
stream.append(&b);
|
||||
stream.append(&c);
|
||||
|
||||
let ssz = stream.drain();
|
||||
assert_eq!(ssz[0..20], *vec![0; 20]);
|
||||
assert_eq!(ssz[20], 100);
|
||||
assert_eq!(ssz[21..23], *vec![255, 255]);
|
||||
assert_eq!(ssz[23..27], *vec![0, 0, 0, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssz_encode_bool() {
|
||||
let x: bool = false;
|
||||
@ -238,7 +259,7 @@ mod tests {
|
||||
let x: bool = true;
|
||||
let mut ssz = SszStream::new();
|
||||
ssz.append(&x);
|
||||
assert_eq!(ssz.drain(), vec![0b1000_0000]);
|
||||
assert_eq!(ssz.drain(), vec![0b0000_0001]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -19,7 +19,7 @@ mod impl_decode;
|
||||
mod impl_encode;
|
||||
mod impl_tree_hash;
|
||||
|
||||
pub use crate::decode::{decode_ssz, decode_ssz_list, Decodable, DecodeError};
|
||||
pub use crate::decode::{decode, decode_ssz_list, Decodable, DecodeError};
|
||||
pub use crate::encode::{Encodable, SszStream};
|
||||
pub use crate::signed_root::SignedRoot;
|
||||
pub use crate::tree_hash::{merkle_hash, TreeHash};
|
||||
@ -38,3 +38,193 @@ where
|
||||
ssz_stream.append(val);
|
||||
ssz_stream.drain()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate hex;
|
||||
extern crate yaml_rust;
|
||||
|
||||
use self::yaml_rust::yaml;
|
||||
use super::*;
|
||||
use std::{fs::File, io::prelude::*, path::PathBuf};
|
||||
|
||||
#[test]
|
||||
pub fn test_vector_uint_bounds() {
|
||||
let mut file = {
|
||||
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
file_path_buf.push("src/test_vectors/uint_bounds.yaml");
|
||||
|
||||
File::open(file_path_buf).unwrap()
|
||||
};
|
||||
let mut yaml_str = String::new();
|
||||
file.read_to_string(&mut yaml_str).unwrap();
|
||||
let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
|
||||
let doc = &docs[0];
|
||||
|
||||
// Load test cases
|
||||
let test_cases = doc["test_cases"].clone();
|
||||
|
||||
for test_case in test_cases {
|
||||
// Only the valid cases are checked as parse::<uX>() will fail for all invalid cases
|
||||
if test_case["valid"].as_bool().unwrap() {
|
||||
// Convert test vector 'ssz' encoded yaml to Vec<u8>
|
||||
let ssz = test_case["ssz"].as_str().unwrap().trim_start_matches("0x");
|
||||
let test_vector_bytes = hex::decode(ssz).unwrap();
|
||||
|
||||
// Convert test vector 'value' to ssz encoded bytes
|
||||
let mut bytes: Vec<u8>;
|
||||
match test_case["type"].as_str().unwrap() {
|
||||
"uint8" => {
|
||||
let value: u8 = test_case["value"].as_str().unwrap().parse::<u8>().unwrap();
|
||||
bytes = ssz_encode::<u8>(&value); // check encoding
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u8>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
"uint16" => {
|
||||
let value: u16 =
|
||||
test_case["value"].as_str().unwrap().parse::<u16>().unwrap();
|
||||
bytes = ssz_encode::<u16>(&value);
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u16>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
"uint32" => {
|
||||
let value: u32 =
|
||||
test_case["value"].as_str().unwrap().parse::<u32>().unwrap();
|
||||
bytes = ssz_encode::<u32>(&value);
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u32>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
"uint64" => {
|
||||
let value: u64 =
|
||||
test_case["value"].as_str().unwrap().parse::<u64>().unwrap();
|
||||
bytes = ssz_encode::<u64>(&value);
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u64>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
assert_eq!(test_vector_bytes, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_vector_uint_random() {
|
||||
let mut file = {
|
||||
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
file_path_buf.push("src/test_vectors/uint_random.yaml");
|
||||
|
||||
File::open(file_path_buf).unwrap()
|
||||
};
|
||||
let mut yaml_str = String::new();
|
||||
file.read_to_string(&mut yaml_str).unwrap();
|
||||
let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
|
||||
let doc = &docs[0];
|
||||
|
||||
// Load test cases
|
||||
let test_cases = doc["test_cases"].clone();
|
||||
|
||||
for test_case in test_cases {
|
||||
// Only the valid cases are checked as parse::<uX>() will fail for all invalid cases
|
||||
if test_case["valid"].as_bool().unwrap() {
|
||||
// Convert test vector 'ssz' encoded yaml to Vec<u8>
|
||||
let ssz = test_case["ssz"].as_str().unwrap().trim_start_matches("0x");
|
||||
let test_vector_bytes = hex::decode(ssz).unwrap();
|
||||
|
||||
// Convert test vector 'value' to ssz encoded bytes
|
||||
let mut bytes: Vec<u8>;
|
||||
match test_case["type"].as_str().unwrap() {
|
||||
"uint8" => {
|
||||
let value: u8 = test_case["value"].as_str().unwrap().parse::<u8>().unwrap();
|
||||
bytes = ssz_encode::<u8>(&value); // check encoding
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u8>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
"uint16" => {
|
||||
let value: u16 =
|
||||
test_case["value"].as_str().unwrap().parse::<u16>().unwrap();
|
||||
bytes = ssz_encode::<u16>(&value);
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u16>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
"uint32" => {
|
||||
let value: u32 =
|
||||
test_case["value"].as_str().unwrap().parse::<u32>().unwrap();
|
||||
bytes = ssz_encode::<u32>(&value);
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u32>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
"uint64" => {
|
||||
let value: u64 =
|
||||
test_case["value"].as_str().unwrap().parse::<u64>().unwrap();
|
||||
bytes = ssz_encode::<u64>(&value);
|
||||
|
||||
// Check decoding
|
||||
let decoded = decode::<u64>(&test_vector_bytes).unwrap();
|
||||
assert_eq!(decoded, value);
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
assert_eq!(test_vector_bytes, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_vector_uint_wrong_length() {
|
||||
let mut file = {
|
||||
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
file_path_buf.push("src/test_vectors/uint_wrong_length.yaml");
|
||||
|
||||
File::open(file_path_buf).unwrap()
|
||||
};
|
||||
let mut yaml_str = String::new();
|
||||
file.read_to_string(&mut yaml_str).unwrap();
|
||||
let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
|
||||
let doc = &docs[0];
|
||||
|
||||
// Load test cases
|
||||
let test_cases = doc["test_cases"].clone();
|
||||
|
||||
for test_case in test_cases {
|
||||
// Convert test vector 'ssz' encoded yaml to Vec<u8>
|
||||
let ssz = test_case["ssz"].as_str().unwrap().trim_start_matches("0x");
|
||||
let test_vector_bytes = hex::decode(ssz).unwrap();
|
||||
|
||||
// Attempt to decode invalid ssz bytes
|
||||
match test_case["type"].as_str().unwrap() {
|
||||
"uint8" => {
|
||||
let decoded = decode::<u8>(&test_vector_bytes);
|
||||
assert!(decoded.is_err());
|
||||
}
|
||||
"uint16" => {
|
||||
let decoded = decode::<u16>(&test_vector_bytes);
|
||||
assert!(decoded.is_err());
|
||||
}
|
||||
"uint32" => {
|
||||
let decoded = decode::<u32>(&test_vector_bytes);
|
||||
assert!(decoded.is_err());
|
||||
}
|
||||
"uint64" => {
|
||||
let decoded = decode::<u64>(&test_vector_bytes);
|
||||
assert!(decoded.is_err());
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1924
eth2/utils/ssz/src/test_vectors/uint_bounds.yaml
Normal file
1924
eth2/utils/ssz/src/test_vectors/uint_bounds.yaml
Normal file
File diff suppressed because it is too large
Load Diff
5124
eth2/utils/ssz/src/test_vectors/uint_random.yaml
Normal file
5124
eth2/utils/ssz/src/test_vectors/uint_random.yaml
Normal file
File diff suppressed because it is too large
Load Diff
6640
eth2/utils/ssz/src/test_vectors/uint_wrong_length.yaml
Normal file
6640
eth2/utils/ssz/src/test_vectors/uint_wrong_length.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ use protos::services::{
|
||||
BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest,
|
||||
};
|
||||
use protos::services_grpc::BeaconBlockServiceClient;
|
||||
use ssz::{ssz_encode, Decodable};
|
||||
use ssz::{decode, ssz_encode};
|
||||
use std::sync::Arc;
|
||||
use types::{BeaconBlock, BeaconBlockBody, Eth1Data, Hash256, Signature, Slot};
|
||||
|
||||
@ -41,10 +41,10 @@ impl BeaconNode for BeaconBlockGrpcClient {
|
||||
if reply.has_block() {
|
||||
let block = reply.get_block();
|
||||
|
||||
let (signature, _) = Signature::ssz_decode(block.get_signature(), 0)
|
||||
let signature = decode::<Signature>(block.get_signature())
|
||||
.map_err(|_| BeaconNodeError::DecodeFailure)?;
|
||||
|
||||
let (randao_reveal, _) = Signature::ssz_decode(block.get_randao_reveal(), 0)
|
||||
let randao_reveal = decode::<Signature>(block.get_randao_reveal())
|
||||
.map_err(|_| BeaconNodeError::DecodeFailure)?;
|
||||
|
||||
// TODO: this conversion is incomplete; fix it.
|
||||
|
Loading…
Reference in New Issue
Block a user