Merge branch 'v0.8.3' into interop-v0.8.3
This commit is contained in:
@@ -17,11 +17,9 @@ pub fn get_attesting_indices<T: EthSpec>(
|
||||
target_relative_epoch,
|
||||
)?;
|
||||
|
||||
/* TODO(freeze): re-enable this?
|
||||
if bitlist.len() > committee.committee.len() {
|
||||
if bitlist.len() != committee.committee.len() {
|
||||
return Err(BeaconStateError::InvalidBitfield);
|
||||
}
|
||||
*/
|
||||
|
||||
Ok(committee
|
||||
.committee
|
||||
|
||||
@@ -3,7 +3,7 @@ use types::*;
|
||||
|
||||
/// Return the compact committee root at `relative_epoch`.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
/// Spec v0.8.3
|
||||
pub fn get_compact_committees_root<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
relative_epoch: RelativeEpoch,
|
||||
@@ -11,28 +11,13 @@ pub fn get_compact_committees_root<T: EthSpec>(
|
||||
) -> Result<Hash256, BeaconStateError> {
|
||||
let mut committees =
|
||||
FixedVector::<_, T::ShardCount>::from_elem(CompactCommittee::<T>::default());
|
||||
// FIXME: this is a spec bug, whereby the start shard for the epoch after the next epoch
|
||||
// is mistakenly used. The start shard from the cache SHOULD work.
|
||||
// Waiting on a release to fix https://github.com/ethereum/eth2.0-specs/issues/1315
|
||||
let start_shard = if relative_epoch == RelativeEpoch::Next {
|
||||
state.next_epoch_start_shard(spec)?
|
||||
} else {
|
||||
state.get_epoch_start_shard(relative_epoch)?
|
||||
};
|
||||
let start_shard = state.get_epoch_start_shard(relative_epoch)?;
|
||||
|
||||
for committee_number in 0..state.get_committee_count(relative_epoch)? {
|
||||
let shard = (start_shard + committee_number) % T::ShardCount::to_u64();
|
||||
// FIXME: this is a partial workaround for the above, but it only works in the case
|
||||
// where there's a committee for every shard in every epoch. It works for the minimal
|
||||
// tests but not the mainnet ones.
|
||||
let fake_shard = if relative_epoch == RelativeEpoch::Next {
|
||||
(shard + 1) % T::ShardCount::to_u64()
|
||||
} else {
|
||||
shard
|
||||
};
|
||||
|
||||
for &index in state
|
||||
.get_crosslink_committee_for_shard(fake_shard, relative_epoch)?
|
||||
.get_crosslink_committee_for_shard(shard, relative_epoch)?
|
||||
.committee
|
||||
{
|
||||
let validator = state
|
||||
|
||||
@@ -11,6 +11,8 @@ pub fn get_indexed_attestation<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attestation: &Attestation<T>,
|
||||
) -> Result<IndexedAttestation<T>> {
|
||||
// Note: we rely on both calls to `get_attesting_indices` to check the bitfield lengths
|
||||
// against the committee length
|
||||
let attesting_indices =
|
||||
get_attesting_indices(state, &attestation.data, &attestation.aggregation_bits)?;
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use crate::common::get_compact_committees_root;
|
||||
use apply_rewards::process_rewards_and_penalties;
|
||||
use errors::EpochProcessingError as Error;
|
||||
use process_slashings::process_slashings;
|
||||
use registry_updates::process_registry_updates;
|
||||
use std::collections::HashMap;
|
||||
use tree_hash::TreeHash;
|
||||
use types::*;
|
||||
@@ -17,6 +14,10 @@ pub mod tests;
|
||||
pub mod validator_statuses;
|
||||
pub mod winning_root;
|
||||
|
||||
pub use apply_rewards::process_rewards_and_penalties;
|
||||
pub use process_slashings::process_slashings;
|
||||
pub use registry_updates::process_registry_updates;
|
||||
|
||||
/// Maps a shard to a winning root.
|
||||
///
|
||||
/// It is generated during crosslink processing and later used to reward/penalize validators.
|
||||
@@ -218,45 +219,29 @@ pub fn process_final_updates<T: EthSpec>(
|
||||
}
|
||||
}
|
||||
|
||||
// Update start shard.
|
||||
state.start_shard = state.next_epoch_start_shard(spec)?;
|
||||
|
||||
// This is a hack to allow us to update index roots and slashed balances for the next epoch.
|
||||
//
|
||||
// The indentation here is to make it obvious where the weird stuff happens.
|
||||
{
|
||||
state.slot += 1;
|
||||
|
||||
// Set active index root
|
||||
let index_epoch = next_epoch + spec.activation_exit_delay;
|
||||
let indices_list = VariableList::<usize, T::ValidatorRegistryLimit>::from(
|
||||
state.get_active_validator_indices(index_epoch),
|
||||
);
|
||||
state.set_active_index_root(
|
||||
index_epoch,
|
||||
Hash256::from_slice(&indices_list.tree_hash_root()),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
// Reset slashings
|
||||
state.set_slashings(next_epoch, 0)?;
|
||||
|
||||
// Set randao mix
|
||||
state.set_randao_mix(next_epoch, *state.get_randao_mix(current_epoch)?)?;
|
||||
|
||||
state.slot -= 1;
|
||||
}
|
||||
// Set active index root
|
||||
let index_epoch = next_epoch + spec.activation_exit_delay;
|
||||
let indices_list = VariableList::<usize, T::ValidatorRegistryLimit>::from(
|
||||
state.get_active_validator_indices(index_epoch),
|
||||
);
|
||||
state.set_active_index_root(
|
||||
index_epoch,
|
||||
Hash256::from_slice(&indices_list.tree_hash_root()),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
// Set committees root
|
||||
// Note: we do this out-of-order w.r.t. to the spec, because we don't want the slot to be
|
||||
// incremented. It's safe because the updates to slashings and the RANDAO mix (above) don't
|
||||
// affect this.
|
||||
state.set_compact_committee_root(
|
||||
next_epoch,
|
||||
get_compact_committees_root(state, RelativeEpoch::Next, spec)?,
|
||||
spec,
|
||||
)?;
|
||||
|
||||
// Reset slashings
|
||||
state.set_slashings(next_epoch, 0)?;
|
||||
|
||||
// Set randao mix
|
||||
state.set_randao_mix(next_epoch, *state.get_randao_mix(current_epoch)?)?;
|
||||
|
||||
// Set historical root accumulator
|
||||
if next_epoch.as_u64() % (T::SlotsPerHistoricalRoot::to_u64() / T::slots_per_epoch()) == 0 {
|
||||
let historical_batch = state.historical_batch();
|
||||
@@ -265,6 +250,9 @@ pub fn process_final_updates<T: EthSpec>(
|
||||
.push(Hash256::from_slice(&historical_batch.tree_hash_root()))?;
|
||||
}
|
||||
|
||||
// Update start shard.
|
||||
state.start_shard = state.get_epoch_start_shard(RelativeEpoch::Next)?;
|
||||
|
||||
// Rotate current/previous epoch attestations
|
||||
state.previous_epoch_attestations =
|
||||
std::mem::replace(&mut state.current_epoch_attestations, VariableList::empty());
|
||||
|
||||
@@ -4,25 +4,13 @@ use crate::{Checkpoint, Crosslink, Hash256};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash::TreeHash;
|
||||
use tree_hash_derive::{SignedRoot, TreeHash};
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
/// The data upon which an attestation is based.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Hash,
|
||||
Encode,
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
SignedRoot,
|
||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Encode, Decode, TreeHash, TestRandom,
|
||||
)]
|
||||
pub struct AttestationData {
|
||||
// LMD GHOST vote
|
||||
|
||||
@@ -60,6 +60,22 @@ pub enum Error {
|
||||
SszTypesError(ssz_types::Error),
|
||||
}
|
||||
|
||||
/// Control whether an epoch-indexed field can be indexed at the next epoch or not.
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
enum AllowNextEpoch {
|
||||
True,
|
||||
False,
|
||||
}
|
||||
|
||||
impl AllowNextEpoch {
|
||||
fn upper_bound_of(self, current_epoch: Epoch) -> Epoch {
|
||||
match self {
|
||||
AllowNextEpoch::True => current_epoch + 1,
|
||||
AllowNextEpoch::False => current_epoch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The state of the `BeaconChain` at some slot.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
@@ -108,12 +124,12 @@ where
|
||||
pub start_shard: u64,
|
||||
pub randao_mixes: FixedVector<Hash256, T::EpochsPerHistoricalVector>,
|
||||
#[compare_fields(as_slice)]
|
||||
active_index_roots: FixedVector<Hash256, T::EpochsPerHistoricalVector>,
|
||||
pub active_index_roots: FixedVector<Hash256, T::EpochsPerHistoricalVector>,
|
||||
#[compare_fields(as_slice)]
|
||||
compact_committees_roots: FixedVector<Hash256, T::EpochsPerHistoricalVector>,
|
||||
pub compact_committees_roots: FixedVector<Hash256, T::EpochsPerHistoricalVector>,
|
||||
|
||||
// Slashings
|
||||
slashings: FixedVector<u64, T::EpochsPerSlashingsVector>,
|
||||
pub slashings: FixedVector<u64, T::EpochsPerSlashingsVector>,
|
||||
|
||||
// Attestations
|
||||
pub previous_epoch_attestations: VariableList<PendingAttestation<T>, T::MaxPendingAttestations>,
|
||||
@@ -282,14 +298,6 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
Ok(cache.epoch_start_shard())
|
||||
}
|
||||
|
||||
pub fn next_epoch_start_shard(&self, spec: &ChainSpec) -> Result<u64, Error> {
|
||||
let cache = self.cache(RelativeEpoch::Current)?;
|
||||
let active_validator_count = cache.active_validator_count();
|
||||
let shard_delta = T::get_shard_delta(active_validator_count, spec.target_committee_size);
|
||||
|
||||
Ok((self.start_shard + shard_delta) % T::ShardCount::to_u64())
|
||||
}
|
||||
|
||||
/// Get the slot of an attestation.
|
||||
///
|
||||
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
|
||||
@@ -463,12 +471,16 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
|
||||
/// Safely obtains the index for `randao_mixes`
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
fn get_randao_mix_index(&self, epoch: Epoch) -> Result<usize, Error> {
|
||||
/// Spec v0.8.1
|
||||
fn get_randao_mix_index(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
allow_next_epoch: AllowNextEpoch,
|
||||
) -> Result<usize, Error> {
|
||||
let current_epoch = self.current_epoch();
|
||||
let len = T::EpochsPerHistoricalVector::to_u64();
|
||||
|
||||
if epoch + len > current_epoch && epoch <= current_epoch {
|
||||
if current_epoch < epoch + len && epoch <= allow_next_epoch.upper_bound_of(current_epoch) {
|
||||
Ok(epoch.as_usize() % len as usize)
|
||||
} else {
|
||||
Err(Error::EpochOutOfBounds)
|
||||
@@ -496,7 +508,7 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
pub fn get_randao_mix(&self, epoch: Epoch) -> Result<&Hash256, Error> {
|
||||
let i = self.get_randao_mix_index(epoch)?;
|
||||
let i = self.get_randao_mix_index(epoch, AllowNextEpoch::False)?;
|
||||
Ok(&self.randao_mixes[i])
|
||||
}
|
||||
|
||||
@@ -504,21 +516,29 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
pub fn set_randao_mix(&mut self, epoch: Epoch, mix: Hash256) -> Result<(), Error> {
|
||||
let i = self.get_randao_mix_index(epoch)?;
|
||||
let i = self.get_randao_mix_index(epoch, AllowNextEpoch::True)?;
|
||||
self.randao_mixes[i] = mix;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Safely obtains the index for `active_index_roots`, given some `epoch`.
|
||||
///
|
||||
/// If `allow_next_epoch` is `True`, then we allow an _extra_ one epoch of lookahead.
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
fn get_active_index_root_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
|
||||
fn get_active_index_root_index(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
spec: &ChainSpec,
|
||||
allow_next_epoch: AllowNextEpoch,
|
||||
) -> Result<usize, Error> {
|
||||
let current_epoch = self.current_epoch();
|
||||
|
||||
let lookahead = spec.activation_exit_delay;
|
||||
let lookback = self.active_index_roots.len() as u64 - lookahead;
|
||||
let epoch_upper_bound = allow_next_epoch.upper_bound_of(current_epoch) + lookahead;
|
||||
|
||||
if epoch + lookback > current_epoch && current_epoch + lookahead >= epoch {
|
||||
if current_epoch < epoch + lookback && epoch <= epoch_upper_bound {
|
||||
Ok(epoch.as_usize() % self.active_index_roots.len())
|
||||
} else {
|
||||
Err(Error::EpochOutOfBounds)
|
||||
@@ -529,7 +549,7 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
///
|
||||
/// Spec v0.8.1
|
||||
pub fn get_active_index_root(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> {
|
||||
let i = self.get_active_index_root_index(epoch, spec)?;
|
||||
let i = self.get_active_index_root_index(epoch, spec, AllowNextEpoch::False)?;
|
||||
Ok(self.active_index_roots[i])
|
||||
}
|
||||
|
||||
@@ -542,7 +562,7 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
index_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let i = self.get_active_index_root_index(epoch, spec)?;
|
||||
let i = self.get_active_index_root_index(epoch, spec, AllowNextEpoch::True)?;
|
||||
self.active_index_roots[i] = index_root;
|
||||
Ok(())
|
||||
}
|
||||
@@ -556,19 +576,17 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
|
||||
/// Safely obtains the index for `compact_committees_roots`, given some `epoch`.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
/// Spec v0.8.1
|
||||
fn get_compact_committee_root_index(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
spec: &ChainSpec,
|
||||
allow_next_epoch: AllowNextEpoch,
|
||||
) -> Result<usize, Error> {
|
||||
let current_epoch = self.current_epoch();
|
||||
let len = T::EpochsPerHistoricalVector::to_u64();
|
||||
|
||||
let lookahead = spec.activation_exit_delay;
|
||||
let lookback = self.compact_committees_roots.len() as u64 - lookahead;
|
||||
|
||||
if epoch + lookback > current_epoch && current_epoch + lookahead >= epoch {
|
||||
Ok(epoch.as_usize() % self.compact_committees_roots.len())
|
||||
if current_epoch < epoch + len && epoch <= allow_next_epoch.upper_bound_of(current_epoch) {
|
||||
Ok(epoch.as_usize() % len as usize)
|
||||
} else {
|
||||
Err(Error::EpochOutOfBounds)
|
||||
}
|
||||
@@ -576,26 +594,21 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
|
||||
/// Return the `compact_committee_root` at a recent `epoch`.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
pub fn get_compact_committee_root(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Hash256, Error> {
|
||||
let i = self.get_compact_committee_root_index(epoch, spec)?;
|
||||
/// Spec v0.8.1
|
||||
pub fn get_compact_committee_root(&self, epoch: Epoch) -> Result<Hash256, Error> {
|
||||
let i = self.get_compact_committee_root_index(epoch, AllowNextEpoch::False)?;
|
||||
Ok(self.compact_committees_roots[i])
|
||||
}
|
||||
|
||||
/// Set the `compact_committee_root` at a recent `epoch`.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
/// Spec v0.8.1
|
||||
pub fn set_compact_committee_root(
|
||||
&mut self,
|
||||
epoch: Epoch,
|
||||
index_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let i = self.get_compact_committee_root_index(epoch, spec)?;
|
||||
let i = self.get_compact_committee_root_index(epoch, AllowNextEpoch::True)?;
|
||||
self.compact_committees_roots[i] = index_root;
|
||||
Ok(())
|
||||
}
|
||||
@@ -646,14 +659,19 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
|
||||
/// Safely obtain the index for `slashings`, given some `epoch`.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
fn get_slashings_index(&self, epoch: Epoch) -> Result<usize, Error> {
|
||||
/// Spec v0.8.1
|
||||
fn get_slashings_index(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
allow_next_epoch: AllowNextEpoch,
|
||||
) -> Result<usize, Error> {
|
||||
// We allow the slashings vector to be accessed at any cached epoch at or before
|
||||
// the current epoch.
|
||||
if epoch <= self.current_epoch()
|
||||
&& epoch + T::EpochsPerSlashingsVector::to_u64() >= self.current_epoch() + 1
|
||||
// the current epoch, or the next epoch if `AllowNextEpoch::True` is passed.
|
||||
let current_epoch = self.current_epoch();
|
||||
if current_epoch < epoch + T::EpochsPerSlashingsVector::to_u64()
|
||||
&& epoch <= allow_next_epoch.upper_bound_of(current_epoch)
|
||||
{
|
||||
Ok((epoch.as_u64() % T::EpochsPerSlashingsVector::to_u64()) as usize)
|
||||
Ok(epoch.as_usize() % T::EpochsPerSlashingsVector::to_usize())
|
||||
} else {
|
||||
Err(Error::EpochOutOfBounds)
|
||||
}
|
||||
@@ -668,17 +686,17 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
|
||||
/// Get the total slashed balances for some epoch.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
/// Spec v0.8.1
|
||||
pub fn get_slashings(&self, epoch: Epoch) -> Result<u64, Error> {
|
||||
let i = self.get_slashings_index(epoch)?;
|
||||
let i = self.get_slashings_index(epoch, AllowNextEpoch::False)?;
|
||||
Ok(self.slashings[i])
|
||||
}
|
||||
|
||||
/// Set the total slashed balances for some epoch.
|
||||
///
|
||||
/// Spec v0.8.0
|
||||
/// Spec v0.8.1
|
||||
pub fn set_slashings(&mut self, epoch: Epoch, value: u64) -> Result<(), Error> {
|
||||
let i = self.get_slashings_index(epoch)?;
|
||||
let i = self.get_slashings_index(epoch, AllowNextEpoch::True)?;
|
||||
self.slashings[i] = value;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -90,11 +90,11 @@ fn test_active_index<T: EthSpec>(state_slot: Slot) {
|
||||
|
||||
// Test the start and end of the range.
|
||||
assert_eq!(
|
||||
state.get_active_index_root_index(*range.start(), &spec),
|
||||
state.get_active_index_root_index(*range.start(), &spec, AllowNextEpoch::False),
|
||||
Ok(modulo(*range.start()))
|
||||
);
|
||||
assert_eq!(
|
||||
state.get_active_index_root_index(*range.end(), &spec),
|
||||
state.get_active_index_root_index(*range.end(), &spec, AllowNextEpoch::False),
|
||||
Ok(modulo(*range.end()))
|
||||
);
|
||||
|
||||
@@ -102,12 +102,12 @@ fn test_active_index<T: EthSpec>(state_slot: Slot) {
|
||||
if state.current_epoch() > 0 {
|
||||
// Test is invalid on epoch zero, cannot subtract from zero.
|
||||
assert_eq!(
|
||||
state.get_active_index_root_index(*range.start() - 1, &spec),
|
||||
state.get_active_index_root_index(*range.start() - 1, &spec, AllowNextEpoch::False),
|
||||
Err(Error::EpochOutOfBounds)
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
state.get_active_index_root_index(*range.end() + 1, &spec),
|
||||
state.get_active_index_root_index(*range.end() + 1, &spec, AllowNextEpoch::False),
|
||||
Err(Error::EpochOutOfBounds)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ use crate::{Epoch, Hash256};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash::TreeHash;
|
||||
use tree_hash_derive::{SignedRoot, TreeHash};
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
/// Casper FFG checkpoint, used in attestations.
|
||||
///
|
||||
@@ -22,7 +21,6 @@ use tree_hash_derive::{SignedRoot, TreeHash};
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
SignedRoot,
|
||||
)]
|
||||
pub struct Checkpoint {
|
||||
pub epoch: Epoch,
|
||||
|
||||
@@ -5,7 +5,8 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
milagro_bls = { git = "https://github.com/sigp/milagro_bls", tag = "v0.10.0" }
|
||||
# FIXME: update sigp repo
|
||||
milagro_bls = { git = "https://github.com/michaelsproul/milagro_bls", branch = "little-endian-v0.10" }
|
||||
eth2_hashing = { path = "../eth2_hashing" }
|
||||
hex = "0.3"
|
||||
rand = "^0.5"
|
||||
|
||||
@@ -220,13 +220,26 @@ where
|
||||
|
||||
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
|
||||
if bytes.is_empty() {
|
||||
Ok(FixedVector::from(vec![]))
|
||||
Err(ssz::DecodeError::InvalidByteLength {
|
||||
len: 0,
|
||||
expected: 1,
|
||||
})
|
||||
} else if T::is_ssz_fixed_len() {
|
||||
bytes
|
||||
.chunks(T::ssz_fixed_len())
|
||||
.map(|chunk| T::from_ssz_bytes(chunk))
|
||||
.collect::<Result<Vec<T>, _>>()
|
||||
.and_then(|vec| Ok(vec.into()))
|
||||
.and_then(|vec| {
|
||||
if vec.len() == N::to_usize() {
|
||||
Ok(vec.into())
|
||||
} else {
|
||||
Err(ssz::DecodeError::BytesInvalid(format!(
|
||||
"wrong number of vec elements, got: {}, expected: {}",
|
||||
vec.len(),
|
||||
N::to_usize()
|
||||
)))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ssz::decode_list_of_variable_length_items(bytes).and_then(|vec| Ok(vec.into()))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use ethereum_types::H256;
|
||||
use ethereum_types::{H256, U128, U256};
|
||||
|
||||
macro_rules! impl_for_bitsize {
|
||||
($type: ident, $bit_size: expr) => {
|
||||
@@ -73,6 +73,46 @@ macro_rules! impl_for_u8_array {
|
||||
impl_for_u8_array!(4);
|
||||
impl_for_u8_array!(32);
|
||||
|
||||
impl TreeHash for U128 {
|
||||
fn tree_hash_type() -> TreeHashType {
|
||||
TreeHashType::Basic
|
||||
}
|
||||
|
||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||
let mut result = vec![0; 16];
|
||||
self.to_little_endian(&mut result);
|
||||
result
|
||||
}
|
||||
|
||||
fn tree_hash_packing_factor() -> usize {
|
||||
2
|
||||
}
|
||||
|
||||
fn tree_hash_root(&self) -> Vec<u8> {
|
||||
merkle_root(&self.tree_hash_packed_encoding(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeHash for U256 {
|
||||
fn tree_hash_type() -> TreeHashType {
|
||||
TreeHashType::Basic
|
||||
}
|
||||
|
||||
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
|
||||
let mut result = vec![0; 32];
|
||||
self.to_little_endian(&mut result);
|
||||
result
|
||||
}
|
||||
|
||||
fn tree_hash_packing_factor() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn tree_hash_root(&self) -> Vec<u8> {
|
||||
merkle_root(&self.tree_hash_packed_encoding(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl TreeHash for H256 {
|
||||
fn tree_hash_type() -> TreeHashType {
|
||||
TreeHashType::Vector
|
||||
|
||||
Reference in New Issue
Block a user