Merge pull request #325 from sigp/yaml-test-downloads

Yaml Tests for state transitions and SSZ
This commit is contained in:
Paul Hauner 2019-04-02 13:50:38 +11:00 committed by GitHub
commit 0fd509ee82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 14453 additions and 1046 deletions

View File

@ -4,6 +4,7 @@ members = [
"eth2/block_proposer",
"eth2/fork_choice",
"eth2/state_processing",
"eth2/state_processing/yaml_utils",
"eth2/types",
"eth2/utils/bls",
"eth2/utils/boolean-bitfield",

View File

@ -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))

View File

@ -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))

View File

@ -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),
},
}

View File

@ -5,7 +5,7 @@ use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty};
use protos::services_grpc::ValidatorService;
use slog::{debug, info, warn, Logger};
use ssz::Decodable;
use ssz::decode;
use std::sync::Arc;
use types::{Epoch, RelativeEpoch};
@ -75,8 +75,8 @@ impl ValidatorService for ValidatorServiceInstance {
for validator_pk in validators.get_public_keys() {
let mut active_validator = ActiveValidator::new();
let public_key = match PublicKey::ssz_decode(validator_pk, 0) {
Ok((v, _index)) => v,
let public_key = match decode::<PublicKey>(validator_pk) {
Ok(v) => v,
Err(_) => {
let log_clone = self.log.clone();
let f = sink

View File

@ -14,6 +14,7 @@ env_logger = "0.6.0"
serde = "1.0"
serde_derive = "1.0"
serde_yaml = "0.8"
yaml-utils = { path = "yaml_utils" }
[dependencies]
bls = { path = "../utils/bls" }

View File

@ -1,708 +0,0 @@
title: Sanity tests -- small config -- 32 validators
summary: Basic sanity checks from phase 0 spec pythonization using a small state configuration and 32 validators.
All tests are run with `verify_signatures` as set to False.
Tests generated via https://github.com/ethereum/research/blob/master/spec_pythonizer/sanity_check.py
test_suite: beacon_state
fork: phase0-0.5.0
test_cases:
- name: test_empty_block_transition
config:
SHARD_COUNT: 8
TARGET_COMMITTEE_SIZE: 4
MAX_BALANCE_CHURN_QUOTIENT: 32
MAX_INDICES_PER_SLASHABLE_VOTE: 4096
MAX_EXIT_DEQUEUES_PER_EPOCH: 4
SHUFFLE_ROUND_COUNT: 90
DEPOSIT_CONTRACT_TREE_DEPTH: 32
MIN_DEPOSIT_AMOUNT: 1000000000
MAX_DEPOSIT_AMOUNT: 32000000000
FORK_CHOICE_BALANCE_INCREMENT: 1000000000
EJECTION_BALANCE: 16000000000
GENESIS_FORK_VERSION: 0
GENESIS_SLOT: 4294967296
GENESIS_EPOCH: 536870912
GENESIS_START_SHARD: 0
BLS_WITHDRAWAL_PREFIX_BYTE: '0x00'
SECONDS_PER_SLOT: 6
MIN_ATTESTATION_INCLUSION_DELAY: 2
SLOTS_PER_EPOCH: 8
MIN_SEED_LOOKAHEAD: 1
ACTIVATION_EXIT_DELAY: 4
EPOCHS_PER_ETH1_VOTING_PERIOD: 16
SLOTS_PER_HISTORICAL_ROOT: 64
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
PERSISTENT_COMMITTEE_PERIOD: 2048
LATEST_RANDAO_MIXES_LENGTH: 64
LATEST_ACTIVE_INDEX_ROOTS_LENGTH: 64
LATEST_SLASHED_EXIT_LENGTH: 64
BASE_REWARD_QUOTIENT: 32
WHISTLEBLOWER_REWARD_QUOTIENT: 512
ATTESTATION_INCLUSION_REWARD_QUOTIENT: 8
INACTIVITY_PENALTY_QUOTIENT: 16777216
MIN_PENALTY_QUOTIENT: 32
MAX_PROPOSER_SLASHINGS: 16
MAX_ATTESTER_SLASHINGS: 1
MAX_ATTESTATIONS: 128
MAX_DEPOSITS: 16
MAX_VOLUNTARY_EXITS: 16
MAX_TRANSFERS: 16
DOMAIN_BEACON_BLOCK: 0
DOMAIN_RANDAO: 1
DOMAIN_ATTESTATION: 2
DOMAIN_DEPOSIT: 3
DOMAIN_VOLUNTARY_EXIT: 4
DOMAIN_TRANSFER: 5
verify_signatures: false
initial_state:
slot: 4294967296
genesis_time: 0
fork:
previous_version: '0x00000000'
current_version: '0x00000000'
epoch: 536870912
validator_registry:
- pubkey: '0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000001'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000002'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000003'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000004'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000005'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000006'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000007'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa85ae765588126f5e860d019c0e26235f567a9c0c0b2d8ff30f3e8d436b1082596e5e7462d20f5be3764fd473e57f9cf'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000008'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x99cdf3807146e68e041314ca93e1fee0991224ec2a74beb2866816fd0826ce7b6263ee31e953a86d1b72cc2215a57793'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000009'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000a'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x80fd75ebcc0a21649e3177bcce15426da0e4f25d6828fbf4038d4d7ed3bd4421de3ef61d70f794687b12b2d571971a55'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000b'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8345dd80ffef0eaec8920e39ebb7f5e9ae9c1d6179e9129b705923df7830c67f3690cbc48649d4079eadf5397339580c'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000c'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x851f8a0b82a6d86202a61cbc3b0f3db7d19650b914587bde4715ccd372e1e40cab95517779d840416e1679c84a6db24e'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000d'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x99bef05aaba1ea467fcbc9c420f5e3153c9d2b5f9bf2c7e2e7f6946f854043627b45b008607b9a9108bb96f3c1c089d3'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000e'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8d9e19b3f4c7c233a6112e5397309f9812a4f61f754f11dd3dcb8b07d55a7b1dfea65f19a1488a14fef9a41495083582'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000000f'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa73eb991aa22cdb794da6fcde55a427f0a4df5a4a70de23a988b5e5fc8c4d844f66d990273267a54dd21579b7ba6a086'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000010'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb098f178f84fc753a76bb63709e9be91eec3ff5f7f3a5f4836f34fe8a1a6d6c5578d8fd820573cef3a01e2bfef3eaf3a'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000011'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x9252a4ac3529f8b2b6e8189b95a60b8865f07f9a9b73f98d5df708511d3f68632c4c7d1e2b03e6b1d1e2c01839752ada'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000012'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb271205227c7aa27f45f20b3ba380dfea8b51efae91fd32e552774c99e2a1237aa59c0c43f52aad99bba3783ea2f36a4'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000013'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa272e9d1d50a4aea7d8f0583948090d0888be5777f2846800b8281139cd4aa9eee05f89b069857a3e77ccfaae1615f9c'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000014'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x9780e853f8ce7eda772c6691d25e220ca1d2ab0db51a7824b700620f7ac94c06639e91c98bb6abd78128f0ec845df8ef'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000015'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xab48aa2cc6f4a0bb63b5d67be54ac3aed10326dda304c5aeb9e942b40d6e7610478377680ab90e092ef1895e62786008'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000016'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8c8b694b04d98a749a0763c72fc020ef61b2bb3f63ebb182cb2e568f6a8b9ca3ae013ae78317599e7e7ba2a528ec754a'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000017'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x9717182463fbe215168e6762abcbb55c5c65290f2b5a2af616f8a6f50d625b46164178a11622d21913efdfa4b800648d'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000018'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xacb58c81ae0cae2e9d4d446b730922239923c345744eee58efaadb36e9a0925545b18a987acf0bad469035b291e37269'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000019'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x81ccc19e3b938ec2405099e90022a4218baa5082a3ca0974b24be0bc8b07e5fffaed64bef0d02c4dbfb6a307829afc5c'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001a'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xab83dfefb120fab7665a607d749ef1765fbb3cc0ba5827a20a135402c09d987c701ddb5b60f0f5495026817e8ab6ea2e'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001b'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb6ad11e5d15f77c1143b1697344911b9c590110fdd8dd09df2e58bfd757269169deefe8be3544d4e049fb3776fb0bcfb'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001c'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0x8515e7f61ca0470e165a44d247a23f17f24bf6e37185467bedb7981c1003ea70bbec875703f793dd8d11e56afa7f74ba'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001d'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xad84464b3966ec5bede84aa487facfca7823af383715078da03b387cc2f5d5597cdd7d025aa07db00a38b953bdeb6e3f'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001e'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xb29043a7273d0a2dbc2b747dcf6a5eccbd7ccb44b2d72e985537b117929bc3fd3a99001481327788ad040b4077c47c0d'
withdrawal_credentials: '0x000000000000000000000000000000000000000000000000000000000000001f'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
- pubkey: '0xa72841987e4f219d54f2b6a9eac5fe6e78704644753c3579e776a3691bc123743f8c63770ed0f72a71e9e964dbf58f43'
withdrawal_credentials: '0x0000000000000000000000000000000000000000000000000000000000000020'
activation_epoch: 536870912
exit_epoch: 18446744073709551615
withdrawable_epoch: 18446744073709551615
initiated_exit: false
slashed: false
validator_balances:
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
- 32000000000
validator_registry_update_epoch: 536870912
latest_randao_mixes:
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
previous_shuffling_start_shard: 0
current_shuffling_start_shard: 0
previous_shuffling_epoch: 536870912
current_shuffling_epoch: 536870912
previous_shuffling_seed: '0x0000000000000000000000000000000000000000000000000000000000000000'
current_shuffling_seed: '0x7a81d831e99dc63f9f10d4abce84c26473d4c2f65ec4acf9000684059473b072'
previous_epoch_attestations: []
current_epoch_attestations: []
previous_justified_epoch: 536870912
current_justified_epoch: 536870912
previous_justified_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
current_justified_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
justification_bitfield: 0
finalized_epoch: 536870912
finalized_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_crosslinks:
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
- epoch: 536870912
crosslink_data_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_block_roots:
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_state_roots:
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
- '0x0000000000000000000000000000000000000000000000000000000000000000'
latest_active_index_roots:
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
- '0x429a7560eb31fa5d1192496997a78ffc590e70f5b39220abff4420298061501a'
latest_slashed_balances:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
latest_block_header:
slot: 4294967296
previous_block_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
state_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
block_body_root: '0x13f2001ff0ee4a528b3c43f63d70a997aefca990ed8eada2223ee6ec3807f7cc'
signature: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
historical_roots: []
latest_eth1_data:
deposit_root: '0x826d25bfcb9161aabc799844c5176f7b3444dc5288856f65e0b8060560488912'
block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000'
eth1_data_votes: []
deposit_index: 32
blocks:
- slot: 4294967297
previous_block_root: '0x2befbd4b4fe8c91f3059082c8048e3376a9b7fb309e93044fac32b7cc8849773'
state_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
body:
randao_reveal: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
eth1_data:
deposit_root: '0x0000000000000000000000000000000000000000000000000000000000000000'
block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000'
proposer_slashings: []
attester_slashings: []
attestations: []
deposits: []
voluntary_exits: []
transfers: []
signature: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
expected_state:
slot: 4294967297

View File

@ -1,5 +1,7 @@
use serde_derive::Deserialize;
use types::*;
#[allow(unused_imports)]
use yaml_utils;
#[derive(Debug, Deserialize)]
pub struct TestCase {
@ -23,9 +25,10 @@ fn yaml() {
use serde_yaml;
use std::{fs::File, io::prelude::*, path::PathBuf};
// Test sanity-check_small-config_32-vals.yaml
let mut file = {
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
file_path_buf.push("specs/example.yml");
file_path_buf.push("yaml_utils/specs/sanity-check_small-config_32-vals.yaml");
File::open(file_path_buf).unwrap()
};
@ -34,7 +37,23 @@ fn yaml() {
file.read_to_string(&mut yaml_str).unwrap();
let yaml_str = yaml_str.to_lowercase();
yaml_str = yaml_str.to_lowercase();
let _doc: TestDoc = serde_yaml::from_str(&yaml_str.as_str()).unwrap();
// Test sanity-check_default-config_100-vals.yaml
file = {
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
file_path_buf.push("yaml_utils/specs/sanity-check_default-config_100-vals.yaml");
File::open(file_path_buf).unwrap()
};
yaml_str = String::new();
file.read_to_string(&mut yaml_str).unwrap();
yaml_str = yaml_str.to_lowercase();
let _doc: TestDoc = serde_yaml::from_str(&yaml_str.as_str()).unwrap();
}

View File

@ -0,0 +1,15 @@
[package]
name = "yaml-utils"
version = "0.1.0"
authors = ["Kirk Baird <baird.k@outlook.com>"]
edition = "2018"
[build-dependencies]
reqwest = "0.9"
tempdir = "0.3"
[dependencies]
[lib]
name = "yaml_utils"
path = "src/lib.rs"

View File

@ -0,0 +1,28 @@
extern crate reqwest;
extern crate tempdir;
use std::fs::File;
use std::io::copy;
fn main() {
// These test files are not to be stored in the lighthouse repo as they are quite large (32MB).
// They will be downloaded at build time by yaml-utils crate (in build.rs)
let git_path = "https://raw.githubusercontent.com/ethereum/eth2.0-tests/master/state/";
let test_names = vec![
"sanity-check_default-config_100-vals.yaml",
"sanity-check_small-config_32-vals.yaml",
];
for test in test_names {
let mut target = String::from(git_path);
target.push_str(test);
let mut response = reqwest::get(target.as_str()).unwrap();
let mut dest = {
let mut file_name = String::from("specs/");
file_name.push_str(test);
File::create(file_name).unwrap()
};
copy(&mut response, &mut dest).unwrap();
}
}

View File

@ -0,0 +1 @@
*.yaml

View File

@ -0,0 +1 @@
// This is a place holder such that yaml-utils is now a crate hence build.rs will be run when 'cargo test' is called

View File

@ -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);
}
}

View File

@ -11,7 +11,7 @@ macro_rules! ssz_tests {
let original = $type::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _) = $type::ssz_decode(&bytes, 0).unwrap();
let (decoded, _): ($type, usize) = <_>::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}

View File

@ -1,6 +1,8 @@
use serde::de::Error;
use serde::{Deserialize, Deserializer};
pub const FORK_BYTES_LEN: usize = 4;
pub fn u8_from_hex_str<'de, D>(deserializer: D) -> Result<u8, D::Error>
where
D: Deserializer<'de>,
@ -10,14 +12,18 @@ where
u8::from_str_radix(&s.as_str()[2..], 16).map_err(D::Error::custom)
}
pub fn fork_from_hex_str<'de, D>(deserializer: D) -> Result<[u8; 4], D::Error>
pub fn fork_from_hex_str<'de, D>(deserializer: D) -> Result<[u8; FORK_BYTES_LEN], D::Error>
where
D: Deserializer<'de>,
{
let s: String = Deserialize::deserialize(deserializer)?;
let mut array = [0 as u8; 4];
let mut array = [0 as u8; FORK_BYTES_LEN];
let decoded: Vec<u8> = hex::decode(&s.as_str()[2..]).map_err(D::Error::custom)?;
if decoded.len() > FORK_BYTES_LEN {
return Err(D::Error::custom("Fork length too long"));
}
for (i, item) in array.iter_mut().enumerate() {
if i > decoded.len() {
break;

View File

@ -1,30 +1,39 @@
use super::{AggregatePublicKey, Signature};
use super::{AggregatePublicKey, Signature, BLS_AGG_SIG_BYTE_SIZE};
use bls_aggregates::{
AggregatePublicKey as RawAggregatePublicKey, AggregateSignature as RawAggregateSignature,
};
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,
};
use serde_hex::{encode as hex_encode, HexVisitor};
use ssz::{decode, hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};
/// A BLS aggregate signature.
///
/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ
/// serialization).
#[derive(Debug, PartialEq, Clone, Default, Eq)]
pub struct AggregateSignature(RawAggregateSignature);
pub struct AggregateSignature {
aggregate_signature: RawAggregateSignature,
is_empty: bool,
}
impl AggregateSignature {
/// Instantiate a new AggregateSignature.
///
/// is_empty is false
/// AggregateSiganture is point at infinity
pub fn new() -> Self {
AggregateSignature(RawAggregateSignature::new())
Self {
aggregate_signature: RawAggregateSignature::new(),
is_empty: false,
}
}
/// Add (aggregate) a signature to the `AggregateSignature`.
pub fn add(&mut self, signature: &Signature) {
self.0.add(signature.as_raw())
if !self.is_empty {
self.aggregate_signature.add(signature.as_raw())
}
}
/// Verify the `AggregateSignature` against an `AggregatePublicKey`.
@ -37,7 +46,11 @@ impl AggregateSignature {
domain: u64,
aggregate_public_key: &AggregatePublicKey,
) -> bool {
self.0.verify(msg, domain, aggregate_public_key.as_raw())
if self.is_empty {
return false;
}
self.aggregate_signature
.verify(msg, domain, aggregate_public_key.as_raw())
}
/// Verify this AggregateSignature against multiple AggregatePublickeys with multiple Messages.
@ -50,6 +63,9 @@ impl AggregateSignature {
domain: u64,
aggregate_public_keys: &[&AggregatePublicKey],
) -> bool {
if self.is_empty {
return false;
}
let aggregate_public_keys: Vec<&RawAggregatePublicKey> =
aggregate_public_keys.iter().map(|pk| pk.as_raw()).collect();
@ -59,50 +75,93 @@ impl AggregateSignature {
msg.extend_from_slice(message);
}
self.0
self.aggregate_signature
.verify_multiple(&msg[..], domain, &aggregate_public_keys[..])
}
/// Return AggregateSiganture as bytes
pub fn as_bytes(&self) -> Vec<u8> {
if self.is_empty {
return vec![0; BLS_AGG_SIG_BYTE_SIZE];
}
self.aggregate_signature.as_bytes()
}
/// Convert bytes to AggregateSiganture
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
for byte in bytes {
if *byte != 0 {
let sig =
RawAggregateSignature::from_bytes(&bytes).map_err(|_| DecodeError::Invalid)?;
return Ok(Self {
aggregate_signature: sig,
is_empty: false,
});
}
}
Ok(Self::empty_signature())
}
/// Returns if the AggregateSiganture `is_empty`
pub fn is_empty(&self) -> bool {
self.is_empty
}
/// Creates a new AggregateSignature
///
/// aggregate_signature set to the point infinity
/// is_empty set to true
pub fn empty_signature() -> Self {
Self {
aggregate_signature: RawAggregateSignature::new(),
is_empty: true,
}
}
}
impl Encodable for AggregateSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.0.as_bytes());
s.append_encoded_raw(&self.as_bytes());
}
}
impl Decodable for AggregateSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
let raw_sig =
RawAggregateSignature::from_bytes(&sig_bytes).map_err(|_| DecodeError::TooShort)?;
Ok((AggregateSignature(raw_sig), i))
if bytes.len() - i < BLS_AGG_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let agg_sig = AggregateSignature::from_bytes(&bytes[i..(i + BLS_AGG_SIG_BYTE_SIZE)])
.map_err(|_| DecodeError::Invalid)?;
Ok((agg_sig, i + BLS_AGG_SIG_BYTE_SIZE))
}
}
impl Serialize for AggregateSignature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&hex_encode(ssz_encode(self)))
serializer.serialize_str(&hex_encode(self.as_bytes()))
}
}
impl<'de> Deserialize<'de> for AggregateSignature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
let (obj, _) = <_>::ssz_decode(&bytes[..], 0)
let bytes = deserializer.deserialize_str(HexVisitor)?;
let agg_sig = decode(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(obj)
Ok(agg_sig)
}
}
impl TreeHash for AggregateSignature {
fn hash_tree_root(&self) -> Vec<u8> {
hash(&self.0.as_bytes())
hash(&self.as_bytes())
}
}
@ -110,7 +169,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() {
@ -120,7 +179,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);
}

View File

@ -1,12 +1,8 @@
use super::{fake_signature::FakeSignature, AggregatePublicKey};
use super::{fake_signature::FakeSignature, AggregatePublicKey, BLS_AGG_SIG_BYTE_SIZE};
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,
};
const SIGNATURE_LENGTH: usize = 48;
use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
/// A BLS aggregate signature.
///
@ -26,7 +22,7 @@ impl FakeAggregateSignature {
/// Creates a new all-zero's signature
pub fn zero() -> Self {
Self {
bytes: vec![0; SIGNATURE_LENGTH],
bytes: vec![0; BLS_AGG_SIG_BYTE_SIZE],
}
}
@ -58,14 +54,21 @@ impl FakeAggregateSignature {
impl Encodable for FakeAggregateSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.bytes);
s.append_encoded_raw(&self.bytes);
}
}
impl Decodable for FakeAggregateSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
Ok((FakeAggregateSignature { bytes: sig_bytes }, i))
if bytes.len() - i < BLS_AGG_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
Ok((
FakeAggregateSignature {
bytes: bytes[i..(i + BLS_AGG_SIG_BYTE_SIZE)].to_vec(),
},
i + BLS_AGG_SIG_BYTE_SIZE,
))
}
}

View File

@ -1,13 +1,9 @@
use super::serde_vistors::HexVisitor;
use super::{PublicKey, SecretKey};
use super::{PublicKey, SecretKey, BLS_SIG_BYTE_SIZE};
use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use ssz::{
decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
};
const SIGNATURE_LENGTH: usize = 48;
use serde_hex::HexVisitor;
use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
/// A single BLS signature.
///
@ -27,7 +23,7 @@ impl FakeSignature {
/// Creates a new all-zero's signature
pub fn zero() -> Self {
Self {
bytes: vec![0; SIGNATURE_LENGTH],
bytes: vec![0; BLS_SIG_BYTE_SIZE],
}
}
@ -59,14 +55,21 @@ impl FakeSignature {
impl Encodable for FakeSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.bytes);
s.append_encoded_raw(&self.bytes);
}
}
impl Decodable for FakeSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
Ok((FakeSignature { bytes: sig_bytes }, i))
if bytes.len() - i < BLS_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
Ok((
FakeSignature {
bytes: bytes[i..(i + BLS_SIG_BYTE_SIZE)].to_vec(),
},
i + BLS_SIG_BYTE_SIZE,
))
}
}

View File

@ -5,7 +5,6 @@ mod aggregate_public_key;
mod keypair;
mod public_key;
mod secret_key;
mod serde_vistors;
#[cfg(not(debug_assertions))]
mod aggregate_signature;
@ -31,6 +30,9 @@ pub use crate::public_key::PublicKey;
pub use crate::secret_key::SecretKey;
pub const BLS_AGG_SIG_BYTE_SIZE: usize = 96;
pub const BLS_SIG_BYTE_SIZE: usize = 96;
pub const BLS_SECRET_KEY_BYTE_SIZE: usize = 48;
pub const BLS_PUBLIC_KEY_BYTE_SIZE: usize = 48;
use hashing::hash;
use ssz::ssz_encode;

View File

@ -1,11 +1,9 @@
use super::SecretKey;
use super::{SecretKey, BLS_PUBLIC_KEY_BYTE_SIZE};
use bls_aggregates::PublicKey as RawPublicKey;
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,
};
use serde_hex::{encode as hex_encode, HexVisitor};
use ssz::{decode, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
use std::default;
use std::hash::{Hash, Hasher};
@ -63,15 +61,18 @@ impl default::Default for PublicKey {
impl Encodable for PublicKey {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.0.as_bytes());
s.append_encoded_raw(&self.0.as_bytes());
}
}
impl Decodable for PublicKey {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
let raw_sig = RawPublicKey::from_bytes(&sig_bytes).map_err(|_| DecodeError::TooShort)?;
Ok((PublicKey(raw_sig), i))
if bytes.len() - i < BLS_PUBLIC_KEY_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let raw_sig = RawPublicKey::from_bytes(&bytes[i..(i + BLS_PUBLIC_KEY_BYTE_SIZE)])
.map_err(|_| DecodeError::TooShort)?;
Ok((PublicKey(raw_sig), i + BLS_PUBLIC_KEY_BYTE_SIZE))
}
}
@ -89,10 +90,10 @@ impl<'de> Deserialize<'de> for PublicKey {
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
let obj = PublicKey::from_bytes(&bytes[..])
let bytes = deserializer.deserialize_str(HexVisitor)?;
let pubkey = decode(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid pubkey ({:?})", e)))?;
Ok(obj)
Ok(pubkey)
}
}

View File

@ -1,9 +1,10 @@
use super::serde_vistors::HexVisitor;
use super::BLS_SECRET_KEY_BYTE_SIZE;
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, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
/// A single BLS signature.
///
@ -32,15 +33,18 @@ impl SecretKey {
impl Encodable for SecretKey {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.0.as_bytes());
s.append_encoded_raw(&self.0.as_bytes());
}
}
impl Decodable for SecretKey {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
let raw_sig = RawSecretKey::from_bytes(&sig_bytes).map_err(|_| DecodeError::TooShort)?;
Ok((SecretKey(raw_sig), i))
if bytes.len() - i < BLS_SECRET_KEY_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let raw_sig = RawSecretKey::from_bytes(&bytes[i..(i + BLS_SECRET_KEY_BYTE_SIZE)])
.map_err(|_| DecodeError::TooShort)?;
Ok((SecretKey(raw_sig), i + BLS_SECRET_KEY_BYTE_SIZE))
}
}
@ -59,9 +63,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)
}
}

View File

@ -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)))?)
}
}

View File

@ -1,12 +1,10 @@
use super::serde_vistors::HexVisitor;
use super::{PublicKey, SecretKey};
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 ssz::{
decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
};
use serde_hex::HexVisitor;
use ssz::{decode, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
/// A single BLS signature.
///
@ -63,7 +61,7 @@ impl Signature {
/// Returns a new empty signature.
pub fn empty_signature() -> Self {
// Set RawSignature = infinity
let mut empty: Vec<u8> = vec![0; 96];
let mut empty: Vec<u8> = vec![0; BLS_SIG_BYTE_SIZE];
empty[0] += u8::pow(2, 6) + u8::pow(2, 7);
Signature {
signature: RawSignature::from_bytes(&empty).unwrap(),
@ -102,15 +100,17 @@ impl Signature {
impl Encodable for Signature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.as_bytes());
s.append_encoded_raw(&self.as_bytes());
}
}
impl Decodable for Signature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
let signature = Signature::from_bytes(&sig_bytes)?;
Ok((signature, i))
if bytes.len() - i < BLS_SIG_BYTE_SIZE {
return Err(DecodeError::TooShort);
}
let signature = Signature::from_bytes(&bytes[i..(i + BLS_SIG_BYTE_SIZE)])?;
Ok((signature, i + BLS_SIG_BYTE_SIZE))
}
}
@ -121,6 +121,7 @@ impl TreeHash for Signature {
}
impl Serialize for Signature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
@ -130,14 +131,15 @@ impl Serialize for Signature {
}
impl<'de> Deserialize<'de> for Signature {
/// Serde serialization is compliant the Ethereum YAML test format.
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(HexVisitor)?;
let (pubkey, _) = <_>::ssz_decode(&bytes[..], 0)
let signature = decode(&bytes[..])
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(pubkey)
Ok(signature)
}
}
@ -154,7 +156,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);
}
@ -165,7 +167,7 @@ mod tests {
let sig_as_bytes: Vec<u8> = sig.as_raw().as_bytes();
assert_eq!(sig_as_bytes.len(), 96);
assert_eq!(sig_as_bytes.len(), BLS_SIG_BYTE_SIZE);
for (i, one_byte) in sig_as_bytes.iter().enumerate() {
if i == 0 {
assert_eq!(*one_byte, u8::pow(2, 6) + u8::pow(2, 7));

View File

@ -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() {
@ -186,7 +186,7 @@ impl Serialize for BooleanBitfield {
where
S: Serializer,
{
serializer.serialize_str(&encode(&ssz::ssz_encode(self)))
serializer.serialize_str(&encode(&self.to_bytes()))
}
}
@ -197,9 +197,7 @@ impl<'de> Deserialize<'de> for BooleanBitfield {
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
let (bitfield, _) = <_>::ssz_decode(&bytes[..], 0)
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(bitfield)
Ok(BooleanBitfield::from_bytes(&bytes))
}
}
@ -212,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() {
@ -380,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 {
@ -401,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);
}
@ -416,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);
}

View File

@ -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::*;

View File

@ -8,3 +8,5 @@ edition = "2018"
bytes = "0.4.9"
ethereum-types = "0.5"
hashing = { path = "../hashing" }
hex = "0.3"
yaml-rust = "0.4"

View File

@ -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 = []

View File

@ -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"

View File

@ -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());
}
});

View File

@ -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());
}
});

View File

@ -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);
});

View File

@ -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());
}
});

View File

@ -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());
}
});

View File

@ -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]]));
});

View File

@ -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());
}
});

View File

@ -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]]));
});

View File

@ -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());
}
});

View File

@ -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],

View File

@ -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());
}
});

View File

@ -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);
});

View File

@ -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());
}
});

View File

@ -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],

View File

@ -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);
});

View File

@ -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);
});

View File

@ -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);
});

View File

@ -3,7 +3,6 @@
extern crate ethereum_types;
extern crate ssz;
use ethereum_types::{Address, H256};
use ssz::SszStream;
// Fuzz ssz_encode()

View File

@ -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);
});

View File

@ -13,16 +13,23 @@ 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`.
/// Check on totality for underflowing the length of bytes and overflow checks done per container
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 +72,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 +89,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 +97,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 +139,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 +179,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));
}
}

View File

@ -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]);
}
}

View File

@ -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]);
}
}

View File

@ -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]

View File

@ -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,
};
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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, Signature, Slot};
@ -42,8 +42,7 @@ impl BeaconNode for BeaconBlockGrpcClient {
let block = reply.get_block();
let ssz = block.get_ssz();
let (block, _i) =
BeaconBlock::ssz_decode(&ssz, 0).map_err(|_| BeaconNodeError::DecodeFailure)?;
let block = decode::<BeaconBlock>(&ssz).map_err(|_| BeaconNodeError::DecodeFailure)?;
Ok(Some(block))
} else {