merged master

This commit is contained in:
Darren Langley
2019-05-16 22:45:32 +10:00
240 changed files with 7991 additions and 20470 deletions

View File

@@ -1,14 +1,15 @@
use super::{AggregateSignature, AttestationData, Bitfield};
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// Details an attestation that can be slashable.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
Clone,
@@ -18,6 +19,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@@ -57,4 +59,5 @@ mod tests {
use super::*;
ssz_tests!(Attestation);
cached_tree_hash_tests!(Attestation);
}

View File

@@ -1,14 +1,15 @@
use crate::test_utils::TestRandom;
use crate::{Crosslink, Epoch, Hash256, Slot};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data upon which an attestation is based.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
Clone,
@@ -20,6 +21,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@@ -46,4 +48,5 @@ mod tests {
use super::*;
ssz_tests!(AttestationData);
cached_tree_hash_tests!(AttestationData);
}

View File

@@ -1,20 +1,22 @@
use super::AttestationData;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::Serialize;
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Used for pairing an attestation with a proof-of-custody.
///
/// Spec v0.5.0
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash)]
/// Spec v0.5.1
#[derive(Debug, Clone, PartialEq, Default, Serialize, Encode, Decode, TreeHash, CachedTreeHash)]
pub struct AttestationDataAndCustodyBit {
pub data: AttestationData,
pub custody_bit: bool,
}
impl<T: RngCore> TestRandom<T> for AttestationDataAndCustodyBit {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for AttestationDataAndCustodyBit {
fn random_for_test(rng: &mut impl RngCore) -> Self {
Self {
data: <_>::random_for_test(rng),
custody_bit: <_>::random_for_test(rng),
@@ -27,4 +29,5 @@ mod test {
use super::*;
ssz_tests!(AttestationDataAndCustodyBit);
cached_tree_hash_tests!(AttestationDataAndCustodyBit);
}

View File

@@ -1,13 +1,25 @@
use crate::{test_utils::TestRandom, SlashableAttestation};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Two conflicting attestations.
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct AttesterSlashing {
pub slashable_attestation_1: SlashableAttestation,
pub slashable_attestation_2: SlashableAttestation,
@@ -18,4 +30,5 @@ mod tests {
use super::*;
ssz_tests!(AttesterSlashing);
cached_tree_hash_tests!(AttesterSlashing);
}

View File

@@ -1,15 +1,16 @@
use crate::test_utils::TestRandom;
use crate::*;
use bls::Signature;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// A block of the `BeaconChain`.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@@ -34,7 +36,7 @@ pub struct BeaconBlock {
impl BeaconBlock {
/// Returns an empty block to be used during genesis.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn empty(spec: &ChainSpec) -> BeaconBlock {
BeaconBlock {
slot: spec.genesis_slot,
@@ -57,11 +59,11 @@ impl BeaconBlock {
}
}
/// Returns the `hash_tree_root` of the block.
/// Returns the `tree_hash_root | update` of the block.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..])
Hash256::from_slice(&self.tree_hash_root()[..])
}
/// Returns a full `BeaconBlockHeader` of this block.
@@ -71,20 +73,20 @@ impl BeaconBlock {
///
/// Note: performs a full tree-hash of `self.body`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn block_header(&self) -> BeaconBlockHeader {
BeaconBlockHeader {
slot: self.slot,
previous_block_root: self.previous_block_root,
state_root: self.state_root,
block_body_root: Hash256::from_slice(&self.body.hash_tree_root()[..]),
block_body_root: Hash256::from_slice(&self.body.tree_hash_root()[..]),
signature: self.signature.clone(),
}
}
/// Returns a "temporary" header, where the `state_root` is `spec.zero_hash`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn temporary_block_header(&self, spec: &ChainSpec) -> BeaconBlockHeader {
BeaconBlockHeader {
state_root: spec.zero_hash,
@@ -99,4 +101,5 @@ mod tests {
use super::*;
ssz_tests!(BeaconBlock);
cached_tree_hash_tests!(BeaconBlock);
}

View File

@@ -1,14 +1,26 @@
use crate::test_utils::TestRandom;
use crate::*;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// The body of a `BeaconChain` block, containing operations.
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct BeaconBlockBody {
pub randao_reveal: Signature,
pub eth1_data: Eth1Data,
@@ -25,4 +37,5 @@ mod tests {
use super::*;
ssz_tests!(BeaconBlockBody);
cached_tree_hash_tests!(BeaconBlockBody);
}

View File

@@ -1,15 +1,16 @@
use crate::test_utils::TestRandom;
use crate::*;
use bls::Signature;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::{SignedRoot, TreeHash};
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// A header of a `BeaconBlock`.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@@ -32,16 +34,16 @@ pub struct BeaconBlockHeader {
}
impl BeaconBlockHeader {
/// Returns the `hash_tree_root` of the header.
/// Returns the `tree_hash_root` of the header.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..])
Hash256::from_slice(&self.signed_root()[..])
}
/// Given a `body`, consumes `self` and returns a complete `BeaconBlock`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn into_block(self, body: BeaconBlockBody) -> BeaconBlock {
BeaconBlock {
slot: self.slot,
@@ -58,4 +60,5 @@ mod tests {
use super::*;
ssz_tests!(BeaconBlockHeader);
cached_tree_hash_tests!(BeaconBlockHeader);
}

View File

@@ -1,14 +1,22 @@
use self::epoch_cache::{get_active_validator_indices, EpochCache, Error as EpochCacheError};
use crate::test_utils::TestRandom;
use crate::*;
use cached_tree_hash::{Error as TreeHashCacheError, TreeHashCache};
use hashing::hash;
use int_to_bytes::int_to_bytes32;
use pubkey_cache::PubkeyCache;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::{hash, ssz_encode, TreeHash};
use ssz_derive::{Decode, Encode, TreeHash};
use test_random_derive::TestRandom;
use fixed_len_vec::{typenum::Unsigned, FixedLenVec};
use serde_derive::{Deserialize, Serialize};
use ssz::ssz_encode;
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, TreeHash};
pub use beacon_state_types::*;
mod beacon_state_types;
mod epoch_cache;
mod pubkey_cache;
mod tests;
@@ -40,13 +48,28 @@ pub enum Error {
EpochCacheUninitialized(RelativeEpoch),
RelativeEpochError(RelativeEpochError),
EpochCacheError(EpochCacheError),
TreeHashCacheError(TreeHashCacheError),
}
/// The state of the `BeaconChain` at some slot.
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, TestRandom, Encode, Decode, TreeHash)]
pub struct BeaconState {
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
TestRandom,
Encode,
Decode,
TreeHash,
CachedTreeHash,
)]
pub struct BeaconState<T>
where
T: EthSpec,
{
// Misc
pub slot: Slot,
pub genesis_time: u64,
@@ -58,7 +81,7 @@ pub struct BeaconState {
pub validator_registry_update_epoch: Epoch,
// Randomness and committees
pub latest_randao_mixes: Vec<Hash256>,
pub latest_randao_mixes: FixedLenVec<Hash256, T::LatestRandaoMixesLength>,
pub previous_shuffling_start_shard: u64,
pub current_shuffling_start_shard: u64,
pub previous_shuffling_epoch: Epoch,
@@ -78,11 +101,11 @@ pub struct BeaconState {
pub finalized_root: Hash256,
// Recent state
pub latest_crosslinks: Vec<Crosslink>,
latest_block_roots: Vec<Hash256>,
latest_state_roots: Vec<Hash256>,
latest_active_index_roots: Vec<Hash256>,
latest_slashed_balances: Vec<u64>,
pub latest_crosslinks: FixedLenVec<Crosslink, T::ShardCount>,
pub latest_block_roots: FixedLenVec<Hash256, T::SlotsPerHistoricalRoot>,
latest_state_roots: FixedLenVec<Hash256, T::SlotsPerHistoricalRoot>,
latest_active_index_roots: FixedLenVec<Hash256, T::LatestActiveIndexRootsLength>,
latest_slashed_balances: FixedLenVec<u64, T::LatestSlashedExitLength>,
pub latest_block_header: BeaconBlockHeader,
pub historical_roots: Vec<Hash256>,
@@ -110,16 +133,26 @@ pub struct BeaconState {
#[tree_hash(skip_hashing)]
#[test_random(default)]
pub pubkey_cache: PubkeyCache,
#[serde(skip_serializing, skip_deserializing)]
#[ssz(skip_serializing)]
#[ssz(skip_deserializing)]
#[tree_hash(skip_hashing)]
#[test_random(default)]
pub tree_hash_cache: TreeHashCache,
}
impl BeaconState {
impl<T: EthSpec> BeaconState<T> {
/// Produce the first state of the Beacon Chain.
///
/// This does not fully build a genesis beacon state, it omits processing of initial validator
/// deposits. To obtain a full genesis beacon state, use the `BeaconStateBuilder`.
///
/// Spec v0.5.0
pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState {
/// Spec v0.5.1
pub fn genesis(
genesis_time: u64,
latest_eth1_data: Eth1Data,
spec: &ChainSpec,
) -> BeaconState<T> {
let initial_crosslink = Crosslink {
epoch: spec.genesis_epoch,
crosslink_data_root: spec.zero_hash,
@@ -137,7 +170,10 @@ impl BeaconState {
validator_registry_update_epoch: spec.genesis_epoch,
// Randomness and committees
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize],
latest_randao_mixes: FixedLenVec::from(vec![
spec.zero_hash;
T::LatestRandaoMixesLength::to_usize()
]),
previous_shuffling_start_shard: spec.genesis_start_shard,
current_shuffling_start_shard: spec.genesis_start_shard,
previous_shuffling_epoch: spec.genesis_epoch,
@@ -157,11 +193,22 @@ impl BeaconState {
finalized_root: spec.zero_hash,
// Recent state
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize],
latest_block_roots: vec![spec.zero_hash; spec.slots_per_historical_root],
latest_state_roots: vec![spec.zero_hash; spec.slots_per_historical_root],
latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length],
latest_slashed_balances: vec![0; spec.latest_slashed_exit_length],
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize].into(),
latest_block_roots: FixedLenVec::from(vec![
spec.zero_hash;
T::SlotsPerHistoricalRoot::to_usize()
]),
latest_state_roots: FixedLenVec::from(vec![
spec.zero_hash;
T::SlotsPerHistoricalRoot::to_usize()
]),
latest_active_index_roots: FixedLenVec::from(
vec![spec.zero_hash; T::LatestActiveIndexRootsLength::to_usize()],
),
latest_slashed_balances: FixedLenVec::from(vec![
0;
T::LatestSlashedExitLength::to_usize()
]),
latest_block_header: BeaconBlock::empty(spec).temporary_block_header(spec),
historical_roots: vec![],
@@ -183,17 +230,18 @@ impl BeaconState {
EpochCache::default(),
],
pubkey_cache: PubkeyCache::default(),
tree_hash_cache: TreeHashCache::default(),
}
}
/// Returns the `hash_tree_root` of the state.
/// Returns the `tree_hash_root` of the state.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..])
Hash256::from_slice(&self.tree_hash_root()[..])
}
pub fn historical_batch(&self) -> HistoricalBatch {
pub fn historical_batch(&self) -> HistoricalBatch<T> {
HistoricalBatch {
block_roots: self.latest_block_roots.clone(),
state_roots: self.latest_state_roots.clone(),
@@ -217,7 +265,7 @@ impl BeaconState {
/// The epoch corresponding to `self.slot`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn current_epoch(&self, spec: &ChainSpec) -> Epoch {
self.slot.epoch(spec.slots_per_epoch)
}
@@ -226,14 +274,14 @@ impl BeaconState {
///
/// If the current epoch is the genesis epoch, the genesis_epoch is returned.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn previous_epoch(&self, spec: &ChainSpec) -> Epoch {
self.current_epoch(&spec) - 1
}
/// The epoch following `self.current_epoch()`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn next_epoch(&self, spec: &ChainSpec) -> Epoch {
self.current_epoch(spec) + 1
}
@@ -246,7 +294,7 @@ impl BeaconState {
///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_cached_active_validator_indices(
&self,
relative_epoch: RelativeEpoch,
@@ -261,7 +309,7 @@ impl BeaconState {
///
/// Does not utilize the cache, performs a full iteration over the validator registry.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_active_validator_indices(&self, epoch: Epoch) -> Vec<usize> {
get_active_validator_indices(&self.validator_registry, epoch)
}
@@ -270,7 +318,7 @@ impl BeaconState {
///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_crosslink_committees_at_slot(
&self,
slot: Slot,
@@ -295,7 +343,7 @@ impl BeaconState {
///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_crosslink_committee_for_shard(
&self,
epoch: Epoch,
@@ -321,7 +369,7 @@ impl BeaconState {
///
/// If the state does not contain an index for a beacon proposer at the requested `slot`, then `None` is returned.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_beacon_proposer_index(
&self,
slot: Slot,
@@ -350,15 +398,10 @@ impl BeaconState {
/// Safely obtains the index for latest block roots, given some `slot`.
///
/// Spec v0.5.0
fn get_latest_block_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) {
let i = slot.as_usize() % spec.slots_per_historical_root;
if i >= self.latest_block_roots.len() {
Err(Error::InsufficientStateRoots)
} else {
Ok(i)
}
/// Spec v0.5.1
fn get_latest_block_roots_index(&self, slot: Slot) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + self.latest_block_roots.len() as u64) {
Ok(slot.as_usize() % self.latest_block_roots.len())
} else {
Err(BeaconStateError::SlotOutOfBounds)
}
@@ -366,45 +409,34 @@ impl BeaconState {
/// Return the block root at a recent `slot`.
///
/// Spec v0.5.0
pub fn get_block_root(
&self,
slot: Slot,
spec: &ChainSpec,
) -> Result<&Hash256, BeaconStateError> {
let i = self.get_latest_block_roots_index(slot, spec)?;
/// Spec v0.5.1
pub fn get_block_root(&self, slot: Slot) -> Result<&Hash256, BeaconStateError> {
let i = self.get_latest_block_roots_index(slot)?;
Ok(&self.latest_block_roots[i])
}
/// Sets the block root for some given slot.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_block_root(
&mut self,
slot: Slot,
block_root: Hash256,
spec: &ChainSpec,
) -> Result<(), BeaconStateError> {
let i = self.get_latest_block_roots_index(slot, spec)?;
let i = self.get_latest_block_roots_index(slot)?;
self.latest_block_roots[i] = block_root;
Ok(())
}
/// Safely obtains the index for `latest_randao_mixes`
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_randao_mix_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
let current_epoch = self.current_epoch(spec);
let len = T::LatestRandaoMixesLength::to_u64();
if (current_epoch - (spec.latest_randao_mixes_length as u64) < epoch)
& (epoch <= current_epoch)
{
let i = epoch.as_usize() % spec.latest_randao_mixes_length;
if i < self.latest_randao_mixes.len() {
Ok(i)
} else {
Err(Error::InsufficientRandaoMixes)
}
if (current_epoch - len < epoch) & (epoch <= current_epoch) {
Ok(epoch.as_usize() % len as usize)
} else {
Err(Error::EpochOutOfBounds)
}
@@ -416,14 +448,14 @@ impl BeaconState {
///
/// See `Self::get_randao_mix`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn update_randao_mix(
&mut self,
epoch: Epoch,
signature: &Signature,
spec: &ChainSpec,
) -> Result<(), Error> {
let i = epoch.as_usize() % spec.latest_randao_mixes_length;
let i = epoch.as_usize() % T::LatestRandaoMixesLength::to_usize();
let signature_hash = Hash256::from_slice(&hash(&ssz_encode(signature)));
@@ -434,7 +466,7 @@ impl BeaconState {
/// Return the randao mix at a recent ``epoch``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_randao_mix(&self, epoch: Epoch, spec: &ChainSpec) -> Result<&Hash256, Error> {
let i = self.get_randao_mix_index(epoch, spec)?;
Ok(&self.latest_randao_mixes[i])
@@ -442,7 +474,7 @@ impl BeaconState {
/// Set the randao mix at a recent ``epoch``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_randao_mix(
&mut self,
epoch: Epoch,
@@ -456,21 +488,16 @@ impl BeaconState {
/// Safely obtains the index for `latest_active_index_roots`, given some `epoch`.
///
/// Spec v0.5.0
/// Spec v0.5.1
fn get_active_index_root_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
let current_epoch = self.current_epoch(spec);
if (current_epoch - spec.latest_active_index_roots_length as u64
if (current_epoch - self.latest_active_index_roots.len() as u64
+ spec.activation_exit_delay
< epoch)
& (epoch <= current_epoch + spec.activation_exit_delay)
{
let i = epoch.as_usize() % spec.latest_active_index_roots_length;
if i < self.latest_active_index_roots.len() {
Ok(i)
} else {
Err(Error::InsufficientIndexRoots)
}
Ok(epoch.as_usize() % self.latest_active_index_roots.len())
} else {
Err(Error::EpochOutOfBounds)
}
@@ -478,7 +505,7 @@ impl BeaconState {
/// Return the `active_index_root` at a recent `epoch`.
///
/// Spec v0.5.0
/// Spec v0.5.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)?;
Ok(self.latest_active_index_roots[i])
@@ -486,7 +513,7 @@ impl BeaconState {
/// Set the `active_index_root` at a recent `epoch`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn set_active_index_root(
&mut self,
epoch: Epoch,
@@ -500,23 +527,18 @@ impl BeaconState {
/// Replace `active_index_roots` with clones of `index_root`.
///
/// Spec v0.5.0
pub fn fill_active_index_roots_with(&mut self, index_root: Hash256, spec: &ChainSpec) {
/// Spec v0.5.1
pub fn fill_active_index_roots_with(&mut self, index_root: Hash256) {
self.latest_active_index_roots =
vec![index_root; spec.latest_active_index_roots_length as usize]
vec![index_root; self.latest_active_index_roots.len() as usize].into()
}
/// Safely obtains the index for latest state roots, given some `slot`.
///
/// Spec v0.5.0
fn get_latest_state_roots_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + spec.slots_per_historical_root as u64) {
let i = slot.as_usize() % spec.slots_per_historical_root;
if i >= self.latest_state_roots.len() {
Err(Error::InsufficientStateRoots)
} else {
Ok(i)
}
/// Spec v0.5.1
fn get_latest_state_roots_index(&self, slot: Slot) -> Result<usize, Error> {
if (slot < self.slot) && (self.slot <= slot + self.latest_state_roots.len() as u64) {
Ok(slot.as_usize() % self.latest_state_roots.len())
} else {
Err(BeaconStateError::SlotOutOfBounds)
}
@@ -524,31 +546,26 @@ impl BeaconState {
/// Gets the state root for some slot.
///
/// Spec v0.5.0
pub fn get_state_root(&mut self, slot: Slot, spec: &ChainSpec) -> Result<&Hash256, Error> {
let i = self.get_latest_state_roots_index(slot, spec)?;
/// Spec v0.5.1
pub fn get_state_root(&mut self, slot: Slot) -> Result<&Hash256, Error> {
let i = self.get_latest_state_roots_index(slot)?;
Ok(&self.latest_state_roots[i])
}
/// Sets the latest state root for slot.
///
/// Spec v0.5.0
pub fn set_state_root(
&mut self,
slot: Slot,
state_root: Hash256,
spec: &ChainSpec,
) -> Result<(), Error> {
let i = self.get_latest_state_roots_index(slot, spec)?;
/// Spec v0.5.1
pub fn set_state_root(&mut self, slot: Slot, state_root: Hash256) -> Result<(), Error> {
let i = self.get_latest_state_roots_index(slot)?;
self.latest_state_roots[i] = state_root;
Ok(())
}
/// Safely obtains the index for `latest_slashed_balances`, given some `epoch`.
///
/// Spec v0.5.0
fn get_slashed_balance_index(&self, epoch: Epoch, spec: &ChainSpec) -> Result<usize, Error> {
let i = epoch.as_usize() % spec.latest_slashed_exit_length;
/// Spec v0.5.1
fn get_slashed_balance_index(&self, epoch: Epoch) -> Result<usize, Error> {
let i = epoch.as_usize() % self.latest_slashed_balances.len();
// NOTE: the validity of the epoch is not checked. It is not in the spec but it's probably
// useful to have.
@@ -561,29 +578,24 @@ impl BeaconState {
/// Gets the total slashed balances for some epoch.
///
/// Spec v0.5.0
pub fn get_slashed_balance(&self, epoch: Epoch, spec: &ChainSpec) -> Result<u64, Error> {
let i = self.get_slashed_balance_index(epoch, spec)?;
/// Spec v0.5.1
pub fn get_slashed_balance(&self, epoch: Epoch) -> Result<u64, Error> {
let i = self.get_slashed_balance_index(epoch)?;
Ok(self.latest_slashed_balances[i])
}
/// Sets the total slashed balances for some epoch.
///
/// Spec v0.5.0
pub fn set_slashed_balance(
&mut self,
epoch: Epoch,
balance: u64,
spec: &ChainSpec,
) -> Result<(), Error> {
let i = self.get_slashed_balance_index(epoch, spec)?;
/// Spec v0.5.1
pub fn set_slashed_balance(&mut self, epoch: Epoch, balance: u64) -> Result<(), Error> {
let i = self.get_slashed_balance_index(epoch)?;
self.latest_slashed_balances[i] = balance;
Ok(())
}
/// Generate a seed for the given `epoch`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn generate_seed(&self, epoch: Epoch, spec: &ChainSpec) -> Result<Hash256, Error> {
let mut input = self
.get_randao_mix(epoch - spec.min_seed_lookahead, spec)?
@@ -599,7 +611,7 @@ impl BeaconState {
/// Return the effective balance (also known as "balance at stake") for a validator with the given ``index``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_effective_balance(
&self,
validator_index: usize,
@@ -614,14 +626,14 @@ impl BeaconState {
/// Return the epoch at which an activation or exit triggered in ``epoch`` takes effect.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_delayed_activation_exit_epoch(&self, epoch: Epoch, spec: &ChainSpec) -> Epoch {
epoch + 1 + spec.activation_exit_delay
}
/// Initiate an exit for the validator of the given `index`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn initiate_validator_exit(&mut self, validator_index: usize) {
self.validator_registry[validator_index].initiated_exit = true;
}
@@ -633,7 +645,7 @@ impl BeaconState {
///
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_attestation_duties(
&self,
validator_index: usize,
@@ -649,7 +661,7 @@ impl BeaconState {
/// Return the combined effective balance of an array of validators.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_total_balance(
&self,
validator_indices: &[usize],
@@ -668,6 +680,7 @@ impl BeaconState {
self.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, spec)?;
self.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, spec)?;
self.update_pubkey_cache()?;
self.update_tree_hash_cache()?;
Ok(())
}
@@ -774,6 +787,39 @@ impl BeaconState {
pub fn drop_pubkey_cache(&mut self) {
self.pubkey_cache = PubkeyCache::default()
}
/// Update the tree hash cache, building it for the first time if it is empty.
///
/// Returns the `tree_hash_root` resulting from the update. This root can be considered the
/// canonical root of `self`.
pub fn update_tree_hash_cache(&mut self) -> Result<Hash256, Error> {
if self.tree_hash_cache.is_empty() {
self.tree_hash_cache = TreeHashCache::new(self)?;
} else {
// Move the cache outside of `self` to satisfy the borrow checker.
let mut cache = std::mem::replace(&mut self.tree_hash_cache, TreeHashCache::default());
cache.update(self)?;
// Move the updated cache back into `self`.
self.tree_hash_cache = cache
}
self.cached_tree_hash_root()
}
/// Returns the tree hash root determined by the last execution of `self.update_tree_hash_cache(..)`.
///
/// Note: does _not_ update the cache and may return an outdated root.
///
/// Returns an error if the cache is not initialized or if an error is encountered during the
/// cache update.
pub fn cached_tree_hash_root(&self) -> Result<Hash256, Error> {
self.tree_hash_cache
.tree_hash_root()
.and_then(|b| Ok(Hash256::from_slice(b)))
.map_err(Into::into)
}
}
impl From<RelativeEpochError> for Error {
@@ -787,3 +833,9 @@ impl From<EpochCacheError> for Error {
Error::EpochCacheError(e)
}
}
impl From<TreeHashCacheError> for Error {
fn from(e: TreeHashCacheError) -> Error {
Error::TreeHashCacheError(e)
}
}

View File

@@ -0,0 +1,111 @@
use crate::*;
use fixed_len_vec::typenum::{Unsigned, U1024, U8, U8192};
use serde_derive::{Deserialize, Serialize};
use std::fmt::Debug;
pub trait EthSpec:
'static + Default + Sync + Send + Clone + Debug + PartialEq + serde::de::DeserializeOwned
{
type ShardCount: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type SlotsPerHistoricalRoot: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type LatestRandaoMixesLength: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type LatestActiveIndexRootsLength: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type LatestSlashedExitLength: Unsigned + Clone + Sync + Send + Debug + PartialEq;
fn spec() -> ChainSpec;
/// Returns the `SHARD_COUNT` constant for this specification.
///
/// Spec v0.5.1
fn shard_count() -> usize {
Self::ShardCount::to_usize()
}
/// Returns the `SLOTS_PER_HISTORICAL_ROOT` constant for this specification.
///
/// Spec v0.5.1
fn slots_per_historical_root() -> usize {
Self::SlotsPerHistoricalRoot::to_usize()
}
/// Returns the `LATEST_RANDAO_MIXES_LENGTH` constant for this specification.
///
/// Spec v0.5.1
fn latest_randao_mixes_length() -> usize {
Self::LatestRandaoMixesLength::to_usize()
}
/// Returns the `LATEST_ACTIVE_INDEX_ROOTS` constant for this specification.
///
/// Spec v0.5.1
fn latest_active_index_roots() -> usize {
Self::LatestActiveIndexRootsLength::to_usize()
}
/// Returns the `LATEST_SLASHED_EXIT_LENGTH` constant for this specification.
///
/// Spec v0.5.1
fn latest_slashed_exit_length() -> usize {
Self::LatestSlashedExitLength::to_usize()
}
}
/// Ethereum Foundation specifications.
///
/// Spec v0.5.1
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct FoundationEthSpec;
impl EthSpec for FoundationEthSpec {
type ShardCount = U1024;
type SlotsPerHistoricalRoot = U8192;
type LatestRandaoMixesLength = U8192;
type LatestActiveIndexRootsLength = U8192;
type LatestSlashedExitLength = U8192;
fn spec() -> ChainSpec {
ChainSpec::foundation()
}
}
pub type FoundationBeaconState = BeaconState<FoundationEthSpec>;
/// Ethereum Foundation specifications, modified to be suitable for < 1000 validators.
///
/// Spec v0.5.1
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct FewValidatorsEthSpec;
impl EthSpec for FewValidatorsEthSpec {
type ShardCount = U8;
type SlotsPerHistoricalRoot = U8192;
type LatestRandaoMixesLength = U8192;
type LatestActiveIndexRootsLength = U8192;
type LatestSlashedExitLength = U8192;
fn spec() -> ChainSpec {
ChainSpec::few_validators()
}
}
pub type FewValidatorsBeaconState = BeaconState<FewValidatorsEthSpec>;
/// Specifications suitable for a small-scale (< 1000 validators) lighthouse testnet.
///
/// Spec v0.5.1
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
pub struct LighthouseTestnetEthSpec;
impl EthSpec for LighthouseTestnetEthSpec {
type ShardCount = U8;
type SlotsPerHistoricalRoot = U8192;
type LatestRandaoMixesLength = U8192;
type LatestActiveIndexRootsLength = U8192;
type LatestSlashedExitLength = U8192;
fn spec() -> ChainSpec {
ChainSpec::lighthouse_testnet()
}
}
pub type LighthouseTestnetBeaconState = BeaconState<LighthouseTestnetEthSpec>;

View File

@@ -28,8 +28,8 @@ pub struct EpochCache {
impl EpochCache {
/// Return a new, fully initialized cache.
pub fn initialized(
state: &BeaconState,
pub fn initialized<T: EthSpec>(
state: &BeaconState<T>,
relative_epoch: RelativeEpoch,
spec: &ChainSpec,
) -> Result<EpochCache, Error> {
@@ -138,7 +138,7 @@ impl EpochCache {
/// Returns a list of all `validator_registry` indices where the validator is active at the given
/// `epoch`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> Vec<usize> {
let mut active = Vec::with_capacity(validators.len());
@@ -200,8 +200,8 @@ pub struct EpochCrosslinkCommitteesBuilder {
impl EpochCrosslinkCommitteesBuilder {
/// Instantiates a builder that will build for the `state`'s previous epoch.
pub fn for_previous_epoch(
state: &BeaconState,
pub fn for_previous_epoch<T: EthSpec>(
state: &BeaconState<T>,
active_validator_indices: Vec<usize>,
spec: &ChainSpec,
) -> Self {
@@ -215,8 +215,8 @@ impl EpochCrosslinkCommitteesBuilder {
}
/// Instantiates a builder that will build for the `state`'s next epoch.
pub fn for_current_epoch(
state: &BeaconState,
pub fn for_current_epoch<T: EthSpec>(
state: &BeaconState<T>,
active_validator_indices: Vec<usize>,
spec: &ChainSpec,
) -> Self {
@@ -233,8 +233,8 @@ impl EpochCrosslinkCommitteesBuilder {
///
/// Note: there are two possible epoch builds for the next epoch, one where there is a registry
/// change and one where there is not.
pub fn for_next_epoch(
state: &BeaconState,
pub fn for_next_epoch<T: EthSpec>(
state: &BeaconState<T>,
active_validator_indices: Vec<usize>,
registry_change: bool,
spec: &ChainSpec,
@@ -288,7 +288,7 @@ impl EpochCrosslinkCommitteesBuilder {
self.active_validator_indices,
spec.shuffle_round_count,
&self.shuffling_seed[..],
true,
false,
)
.ok_or_else(|| Error::UnableToShuffle)?
};

View File

@@ -1,11 +1,12 @@
#![cfg(test)]
use super::*;
use crate::beacon_state::FewValidatorsEthSpec;
use crate::test_utils::*;
use swap_or_not_shuffle::shuffle_list;
fn do_sane_cache_test(
state: BeaconState,
fn do_sane_cache_test<T: EthSpec>(
state: BeaconState<T>,
epoch: Epoch,
relative_epoch: RelativeEpoch,
validator_count: usize,
@@ -27,7 +28,7 @@ fn do_sane_cache_test(
active_indices,
spec.shuffle_round_count,
&expected_seed[..],
true,
false,
)
.unwrap();
@@ -64,7 +65,7 @@ fn do_sane_cache_test(
}
}
fn setup_sane_cache_test(validator_count: usize, spec: &ChainSpec) -> BeaconState {
fn setup_sane_cache_test<T: EthSpec>(validator_count: usize, spec: &ChainSpec) -> BeaconState<T> {
let mut builder =
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(validator_count, spec);
@@ -98,10 +99,13 @@ fn setup_sane_cache_test(validator_count: usize, spec: &ChainSpec) -> BeaconStat
#[test]
fn builds_sane_current_epoch_cache() {
let mut spec = ChainSpec::few_validators();
let mut spec = FewValidatorsEthSpec::spec();
spec.shard_count = 4;
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
let state = setup_sane_cache_test(validator_count as usize, &spec);
let state: BeaconState<FewValidatorsEthSpec> =
setup_sane_cache_test(validator_count as usize, &spec);
do_sane_cache_test(
state.clone(),
state.current_epoch(&spec),
@@ -115,10 +119,13 @@ fn builds_sane_current_epoch_cache() {
#[test]
fn builds_sane_previous_epoch_cache() {
let mut spec = ChainSpec::few_validators();
let mut spec = FewValidatorsEthSpec::spec();
spec.shard_count = 2;
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
let state = setup_sane_cache_test(validator_count as usize, &spec);
let state: BeaconState<FewValidatorsEthSpec> =
setup_sane_cache_test(validator_count as usize, &spec);
do_sane_cache_test(
state.clone(),
state.previous_epoch(&spec),
@@ -132,10 +139,13 @@ fn builds_sane_previous_epoch_cache() {
#[test]
fn builds_sane_next_without_update_epoch_cache() {
let mut spec = ChainSpec::few_validators();
let mut spec = FewValidatorsEthSpec::spec();
spec.shard_count = 2;
let validator_count = (spec.shard_count * spec.target_committee_size) + 1;
let mut state = setup_sane_cache_test(validator_count as usize, &spec);
let mut state: BeaconState<FewValidatorsEthSpec> =
setup_sane_cache_test(validator_count as usize, &spec);
state.validator_registry_update_epoch = state.slot.epoch(spec.slots_per_epoch);
do_sane_cache_test(
state.clone(),

View File

@@ -1,16 +1,18 @@
#![cfg(test)]
use super::*;
use crate::beacon_state::FewValidatorsEthSpec;
use crate::test_utils::*;
ssz_tests!(BeaconState);
ssz_tests!(FoundationBeaconState);
cached_tree_hash_tests!(FoundationBeaconState);
/// Test that
///
/// 1. Using the cache before it's built fails.
/// 2. Using the cache after it's build passes.
/// 3. Using the cache after it's dropped fails.
fn test_cache_initialization<'a>(
state: &'a mut BeaconState,
fn test_cache_initialization<'a, T: EthSpec>(
state: &'a mut BeaconState<T>,
relative_epoch: RelativeEpoch,
spec: &ChainSpec,
) {
@@ -44,9 +46,11 @@ fn test_cache_initialization<'a>(
#[test]
fn cache_initialization() {
let spec = ChainSpec::few_validators();
let (mut state, _keypairs) =
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(16, &spec).build();
let spec = FewValidatorsEthSpec::spec();
let builder: TestingBeaconStateBuilder<FewValidatorsEthSpec> =
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(16, &spec);
let (mut state, _keypairs) = builder.build();
state.slot = (spec.genesis_epoch + 1).start_slot(spec.slots_per_epoch);
@@ -55,3 +59,22 @@ fn cache_initialization() {
test_cache_initialization(&mut state, RelativeEpoch::NextWithRegistryChange, &spec);
test_cache_initialization(&mut state, RelativeEpoch::NextWithoutRegistryChange, &spec);
}
#[test]
fn tree_hash_cache() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]);
let mut state: FoundationBeaconState = BeaconState::random_for_test(&mut rng);
let root = state.update_tree_hash_cache().unwrap();
assert_eq!(root.as_bytes(), &state.tree_hash_root()[..]);
state.slot = state.slot + 1;
let root = state.update_tree_hash_cache().unwrap();
assert_eq!(root.as_bytes(), &state.tree_hash_root()[..]);
}

View File

@@ -8,7 +8,7 @@ const GWEI: u64 = 1_000_000_000;
/// Each of the BLS signature domains.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub enum Domain {
BeaconBlock,
Randao,
@@ -20,7 +20,7 @@ pub enum Domain {
/// Holds all the "constants" for a BeaconChain.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(PartialEq, Debug, Clone, Deserialize)]
#[serde(default)]
pub struct ChainSpec {
@@ -70,17 +70,9 @@ pub struct ChainSpec {
pub min_seed_lookahead: Epoch,
pub activation_exit_delay: u64,
pub epochs_per_eth1_voting_period: u64,
pub slots_per_historical_root: usize,
pub min_validator_withdrawability_delay: Epoch,
pub persistent_committee_period: u64,
/*
* State list lengths
*/
pub latest_randao_mixes_length: usize,
pub latest_active_index_roots_length: usize,
pub latest_slashed_exit_length: usize,
/*
* Reward and penalty quotients
*/
@@ -126,7 +118,7 @@ pub struct ChainSpec {
impl ChainSpec {
/// Return the number of committees in one epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_epoch_committee_count(&self, active_validator_count: usize) -> u64 {
std::cmp::max(
1,
@@ -139,7 +131,7 @@ impl ChainSpec {
/// Get the domain number that represents the fork meta and signature domain.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_domain(&self, epoch: Epoch, domain: Domain, fork: &Fork) -> u64 {
let domain_constant = match domain {
Domain::BeaconBlock => self.domain_beacon_block,
@@ -161,8 +153,8 @@ impl ChainSpec {
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
///
/// Spec v0.5.0
pub fn foundation() -> Self {
/// Spec v0.5.1
pub(crate) fn foundation() -> Self {
let genesis_slot = Slot::new(2_u64.pow(32));
let slots_per_epoch = 64;
let genesis_epoch = genesis_slot.epoch(slots_per_epoch);
@@ -213,17 +205,9 @@ impl ChainSpec {
min_seed_lookahead: Epoch::new(1),
activation_exit_delay: 4,
epochs_per_eth1_voting_period: 16,
slots_per_historical_root: 8_192,
min_validator_withdrawability_delay: Epoch::new(256),
persistent_committee_period: 2_048,
/*
* State list lengths
*/
latest_randao_mixes_length: 8_192,
latest_active_index_roots_length: 8_192,
latest_slashed_exit_length: 8_192,
/*
* Reward and penalty quotients
*/
@@ -264,7 +248,7 @@ impl ChainSpec {
/// Returns a `ChainSpec` compatible with the Lighthouse testnet specification.
///
/// Spec v0.4.0
pub fn lighthouse_testnet() -> Self {
pub(crate) fn lighthouse_testnet() -> Self {
/*
* Lighthouse testnet bootnodes
*/
@@ -280,7 +264,7 @@ impl ChainSpec {
}
/// Returns a `ChainSpec` compatible with the specification suitable for 8 validators.
pub fn few_validators() -> Self {
pub(crate) fn few_validators() -> Self {
let genesis_slot = Slot::new(2_u64.pow(32));
let slots_per_epoch = 8;
let genesis_epoch = genesis_slot.epoch(slots_per_epoch);

View File

@@ -1,13 +1,14 @@
use crate::test_utils::TestRandom;
use crate::{Epoch, Hash256};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Specifies the block hash for a shard at an epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
Clone,
@@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct Crosslink {
@@ -31,4 +33,5 @@ mod tests {
use super::*;
ssz_tests!(Crosslink);
cached_tree_hash_tests!(Crosslink);
}

View File

@@ -1,8 +1,20 @@
use crate::*;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use tree_hash_derive::{CachedTreeHash, TreeHash};
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize, Decode, Encode, TreeHash)]
#[derive(
Default,
Clone,
Debug,
PartialEq,
Serialize,
Deserialize,
Decode,
Encode,
TreeHash,
CachedTreeHash,
)]
pub struct CrosslinkCommittee {
pub slot: Slot,
pub shard: Shard,

View File

@@ -1,16 +1,29 @@
use super::{DepositData, Hash256};
use crate::test_utils::TestRandom;
use rand::RngCore;
use crate::*;
use fixed_len_vec::typenum::U32;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// A deposit to potentially become a beacon chain validator.
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct Deposit {
pub proof: Vec<Hash256>,
pub proof: FixedLenVec<Hash256, U32>,
pub index: u64,
pub deposit_data: DepositData,
}
@@ -20,4 +33,5 @@ mod tests {
use super::*;
ssz_tests!(Deposit);
cached_tree_hash_tests!(Deposit);
}

View File

@@ -1,14 +1,26 @@
use super::DepositInput;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Data generated by the deposit contract.
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct DepositData {
pub amount: u64,
pub timestamp: u64,
@@ -20,4 +32,5 @@ mod tests {
use super::*;
ssz_tests!(DepositData);
cached_tree_hash_tests!(DepositData);
}

View File

@@ -1,15 +1,16 @@
use crate::test_utils::TestRandom;
use crate::*;
use bls::{PublicKey, Signature};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::{SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::{SignedRoot, TreeHash};
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data supplied by the user to the deposit contract.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@@ -20,6 +21,7 @@ use test_random_derive::TestRandom;
Decode,
SignedRoot,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct DepositInput {
@@ -32,7 +34,7 @@ pub struct DepositInput {
impl DepositInput {
/// Generate the 'proof_of_posession' signature for a given DepositInput details.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn create_proof_of_possession(
&self,
secret_key: &SecretKey,
@@ -48,7 +50,7 @@ impl DepositInput {
/// Verify that proof-of-possession is valid.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn validate_proof_of_possession(
&self,
epoch: Epoch,
@@ -67,6 +69,7 @@ mod tests {
use super::*;
ssz_tests!(DepositInput);
cached_tree_hash_tests!(DepositInput);
#[test]
fn can_create_and_validate() {

View File

@@ -1,15 +1,26 @@
use super::Hash256;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Contains data obtained from the Eth1 chain.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
Debug,
PartialEq,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct Eth1Data {
pub deposit_root: Hash256,
@@ -21,4 +32,5 @@ mod tests {
use super::*;
ssz_tests!(Eth1Data);
cached_tree_hash_tests!(Eth1Data);
}

View File

@@ -1,15 +1,26 @@
use super::Eth1Data;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// A summation of votes for some `Eth1Data`.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
Debug,
PartialEq,
Clone,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct Eth1DataVote {
pub eth1_data: Eth1Data,
@@ -21,4 +32,5 @@ mod tests {
use super::*;
ssz_tests!(Eth1DataVote);
cached_tree_hash_tests!(Eth1DataVote);
}

View File

@@ -3,16 +3,27 @@ use crate::{
ChainSpec, Epoch,
};
use int_to_bytes::int_to_bytes4;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Specifies a fork of the `BeaconChain`, to prevent replay attacks.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
Debug,
Clone,
PartialEq,
Default,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct Fork {
#[serde(deserialize_with = "fork_from_hex_str")]
@@ -25,7 +36,7 @@ pub struct Fork {
impl Fork {
/// Initialize the `Fork` from the genesis parameters in the `spec`.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn genesis(spec: &ChainSpec) -> Self {
let mut current_version: [u8; 4] = [0; 4];
current_version.copy_from_slice(&int_to_bytes4(spec.genesis_fork_version));
@@ -39,7 +50,7 @@ impl Fork {
/// Return the fork version of the given ``epoch``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn get_fork_version(&self, epoch: Epoch) -> [u8; 4] {
if epoch < self.epoch {
return self.previous_version;
@@ -53,6 +64,7 @@ mod tests {
use super::*;
ssz_tests!(Fork);
cached_tree_hash_tests!(Fork);
fn test_genesis(version: u32, epoch: Epoch) {
let mut spec = ChainSpec::foundation();

View File

@@ -1,22 +1,38 @@
use crate::test_utils::TestRandom;
use crate::Hash256;
use rand::RngCore;
use crate::*;
use fixed_len_vec::FixedLenVec;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Historical block and state roots.
///
/// Spec v0.5.0
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
pub struct HistoricalBatch {
pub block_roots: Vec<Hash256>,
pub state_roots: Vec<Hash256>,
/// Spec v0.5.1
#[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct HistoricalBatch<T: EthSpec> {
pub block_roots: FixedLenVec<Hash256, T::SlotsPerHistoricalRoot>,
pub state_roots: FixedLenVec<Hash256, T::SlotsPerHistoricalRoot>,
}
#[cfg(test)]
mod tests {
use super::*;
ssz_tests!(HistoricalBatch);
pub type FoundationHistoricalBatch = HistoricalBatch<FoundationEthSpec>;
ssz_tests!(FoundationHistoricalBatch);
cached_tree_hash_tests!(FoundationHistoricalBatch);
}

View File

@@ -46,7 +46,7 @@ pub use crate::attester_slashing::AttesterSlashing;
pub use crate::beacon_block::BeaconBlock;
pub use crate::beacon_block_body::BeaconBlockBody;
pub use crate::beacon_block_header::BeaconBlockHeader;
pub use crate::beacon_state::{BeaconState, Error as BeaconStateError};
pub use crate::beacon_state::{Error as BeaconStateError, *};
pub use crate::chain_spec::{ChainSpec, Domain};
pub use crate::crosslink::Crosslink;
pub use crate::crosslink_committee::CrosslinkCommittee;
@@ -85,6 +85,7 @@ pub type AttesterMap = HashMap<(u64, u64), Vec<usize>>;
pub type ProposerMap = HashMap<u64, usize>;
pub use bls::{AggregatePublicKey, AggregateSignature, Keypair, PublicKey, SecretKey, Signature};
pub use fixed_len_vec::{typenum::Unsigned, FixedLenVec};
pub use libp2p::floodsub::{Topic, TopicBuilder, TopicHash};
pub use libp2p::multiaddr;
pub use libp2p::Multiaddr;

View File

@@ -1,14 +1,26 @@
use crate::test_utils::TestRandom;
use crate::{Attestation, AttestationData, Bitfield, Slot};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// An attestation that has been included in the state but not yet fully processed.
///
/// Spec v0.5.0
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct PendingAttestation {
pub aggregation_bitfield: Bitfield,
pub data: AttestationData,
@@ -33,4 +45,5 @@ mod tests {
use super::*;
ssz_tests!(PendingAttestation);
cached_tree_hash_tests!(PendingAttestation);
}

View File

@@ -1,14 +1,26 @@
use super::BeaconBlockHeader;
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Two conflicting proposals from the same proposer (validator).
///
/// Spec v0.5.0
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
)]
pub struct ProposerSlashing {
pub proposer_index: u64,
pub header_1: BeaconBlockHeader,
@@ -20,4 +32,5 @@ mod tests {
use super::*;
ssz_tests!(ProposerSlashing);
cached_tree_hash_tests!(ProposerSlashing);
}

View File

@@ -10,7 +10,7 @@ pub enum Error {
/// Defines the epochs relative to some epoch. Most useful when referring to the committees prior
/// to and following some epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum RelativeEpoch {
/// The prior epoch.
@@ -32,7 +32,7 @@ pub enum RelativeEpoch {
impl RelativeEpoch {
/// Returns the `epoch` that `self` refers to, with respect to the `base` epoch.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn into_epoch(self, base: Epoch) -> Epoch {
match self {
RelativeEpoch::Previous => base - 1,
@@ -51,7 +51,7 @@ impl RelativeEpoch {
/// - `AmbiguiousNextEpoch` whenever `other` is one after `base`, because it's unknowable if
/// there will be a registry change.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn from_epoch(base: Epoch, other: Epoch) -> Result<Self, Error> {
if other == base - 1 {
Ok(RelativeEpoch::Previous)

View File

@@ -1,15 +1,16 @@
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, Bitfield, ChainSpec};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// Details an attestation that can be slashable.
///
/// To be included in an `AttesterSlashing`.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@@ -34,14 +36,14 @@ pub struct SlashableAttestation {
impl SlashableAttestation {
/// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
self.data.slot.epoch(spec.slots_per_epoch) == other.data.slot.epoch(spec.slots_per_epoch)
}
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
///
/// Spec v0.5.0
/// Spec v0.5.1
pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
let source_epoch_1 = self.data.source_epoch;
let source_epoch_2 = other.data.source_epoch;
@@ -132,6 +134,7 @@ mod tests {
}
ssz_tests!(SlashableAttestation);
cached_tree_hash_tests!(SlashableAttestation);
fn create_slashable_attestation(
slot_factor: u64,

View File

@@ -1,20 +1,21 @@
//! The `Slot` and `Epoch` types are defined as newtypes over u64 to enforce type-safety between
//! the two types.
//!
//! `Slot` and `Epoch` have implementations which permit conversion, comparison and math operations
//! between each and `u64`, however specifically not between each other.
//!
//! All math operations on `Slot` and `Epoch` are saturating, they never wrap.
//!
//! It would be easy to define `PartialOrd` and other traits generically across all types which
//! implement `Into<u64>`, however this would allow operations between `Slots` and `Epochs` which
//! may lead to programming errors which are not detected by the compiler.
use crate::slot_height::SlotHeight;
/// The `Slot` and `Epoch` types are defined as newtypes over u64 to enforce type-safety between
/// the two types.
///
/// `Slot` and `Epoch` have implementations which permit conversion, comparison and math operations
/// between each and `u64`, however specifically not between each other.
///
/// All math operations on `Slot` and `Epoch` are saturating, they never wrap.
///
/// It would be easy to define `PartialOrd` and other traits generically across all types which
/// implement `Into<u64>`, however this would allow operations between `Slots` and `Epochs` which
/// may lead to programming errors which are not detected by the compiler.
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use slog;
use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
use ssz::{ssz_encode, Decode, DecodeError, Encode};
use std::cmp::{Ord, Ordering};
use std::fmt;
use std::hash::{Hash, Hasher};
@@ -144,11 +145,13 @@ mod epoch_tests {
#[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);
assert_eq!(
&max_epoch.as_ssz_bytes(),
&[255, 255, 255, 255, 255, 255, 255, 255]
);
assert_eq!(
max_epoch,
Epoch::from_ssz_bytes(&max_epoch.as_ssz_bytes()).unwrap()
);
}
}

View File

@@ -192,30 +192,74 @@ macro_rules! impl_display {
macro_rules! impl_ssz {
($type: ident) => {
impl Encodable for $type {
fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.0);
impl Encode for $type {
fn is_ssz_fixed_len() -> bool {
<u64 as Encode>::is_ssz_fixed_len()
}
fn ssz_fixed_len() -> usize {
<u64 as Encode>::ssz_fixed_len()
}
fn ssz_append(&self, buf: &mut Vec<u8>) {
self.0.ssz_append(buf)
}
}
impl Decodable for $type {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (value, i) = <_>::ssz_decode(bytes, i)?;
impl Decode for $type {
fn is_ssz_fixed_len() -> bool {
<u64 as Decode>::is_ssz_fixed_len()
}
Ok(($type(value), i))
fn ssz_fixed_len() -> usize {
<u64 as Decode>::ssz_fixed_len()
}
fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
Ok($type(u64::from_ssz_bytes(bytes)?))
}
}
impl TreeHash for $type {
fn hash_tree_root(&self) -> Vec<u8> {
let mut result: Vec<u8> = vec![];
result.append(&mut self.0.hash_tree_root());
hash(&result)
impl tree_hash::TreeHash for $type {
fn tree_hash_type() -> tree_hash::TreeHashType {
tree_hash::TreeHashType::Basic
}
fn tree_hash_packed_encoding(&self) -> Vec<u8> {
ssz_encode(self)
}
fn tree_hash_packing_factor() -> usize {
32 / 8
}
fn tree_hash_root(&self) -> Vec<u8> {
int_to_bytes::int_to_bytes32(self.0)
}
}
impl<T: RngCore> TestRandom<T> for $type {
fn random_for_test(rng: &mut T) -> Self {
impl cached_tree_hash::CachedTreeHash for $type {
fn new_tree_hash_cache(
&self,
depth: usize,
) -> Result<cached_tree_hash::TreeHashCache, cached_tree_hash::Error> {
self.0.new_tree_hash_cache(depth)
}
fn tree_hash_cache_schema(&self, depth: usize) -> cached_tree_hash::BTreeSchema {
self.0.tree_hash_cache_schema(depth)
}
fn update_tree_hash_cache(
&self,
cache: &mut cached_tree_hash::TreeHashCache,
) -> Result<(), cached_tree_hash::Error> {
self.0.update_tree_hash_cache(cache)
}
}
impl TestRandom for $type {
fn random_for_test(rng: &mut impl RngCore) -> Self {
$type::from(u64::random_for_test(rng))
}
}
@@ -535,6 +579,7 @@ macro_rules! all_tests {
math_between_tests!($type, $type);
math_tests!($type);
ssz_tests!($type);
cached_tree_hash_tests!($type);
mod u64_tests {
use super::*;

View File

@@ -1,8 +1,9 @@
use crate::slot_epoch::{Epoch, Slot};
use crate::test_utils::TestRandom;
use rand::RngCore;
use serde_derive::Serialize;
use ssz::{hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
use ssz::{ssz_encode, Decode, DecodeError, Encode};
use std::cmp::{Ord, Ordering};
use std::fmt;
use std::hash::{Hash, Hasher};

View File

@@ -18,13 +18,17 @@ pub fn generate_deterministic_keypairs(validator_count: usize) -> Vec<Keypair> {
let keypairs: Vec<Keypair> = (0..validator_count)
.collect::<Vec<usize>>()
.par_iter()
.map(|&i| {
let secret = int_to_bytes48(i as u64 + 1000);
let sk = SecretKey::from_bytes(&secret).unwrap();
let pk = PublicKey::from_secret_key(&sk);
Keypair { sk, pk }
})
.map(|&i| generate_deterministic_keypair(i))
.collect();
keypairs
}
/// Generates a single deterministic keypair, where the secret key is `validator_index`.
///
/// This is used for testing only, and not to be used in production!
pub fn generate_deterministic_keypair(validator_index: usize) -> Keypair {
let secret = int_to_bytes48(validator_index as u64 + 1000);
let sk = SecretKey::from_bytes(&secret).unwrap();
let pk = PublicKey::from_secret_key(&sk);
Keypair { sk, pk }
}

View File

@@ -5,26 +5,26 @@ macro_rules! ssz_tests {
#[test]
pub fn test_ssz_round_trip() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use ssz::{ssz_encode, Decodable};
use ssz::{ssz_encode, Decode};
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = $type::random_for_test(&mut rng);
let bytes = ssz_encode(&original);
let (decoded, _): ($type, usize) = <_>::ssz_decode(&bytes, 0).unwrap();
let decoded = $type::from_ssz_bytes(&bytes).unwrap();
assert_eq!(original, decoded);
}
#[test]
pub fn test_hash_tree_root() {
pub fn test_tree_hash_root() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use ssz::TreeHash;
use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]);
let original = $type::random_for_test(&mut rng);
let result = original.hash_tree_root();
let result = original.tree_hash_root();
assert_eq!(result.len(), 32);
// TODO: Add further tests
@@ -32,3 +32,51 @@ macro_rules! ssz_tests {
}
};
}
#[cfg(test)]
#[macro_export]
macro_rules! cached_tree_hash_tests {
($type: ident) => {
#[test]
pub fn test_cached_tree_hash() {
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
use tree_hash::TreeHash;
let mut rng = XorShiftRng::from_seed([42; 16]);
// Test the original hash
let original = $type::random_for_test(&mut rng);
let mut cache = cached_tree_hash::TreeHashCache::new(&original).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
original.tree_hash_root(),
"Original hash failed."
);
// Test the updated hash
let modified = $type::random_for_test(&mut rng);
cache.update(&modified).unwrap();
assert_eq!(
cache.tree_hash_root().unwrap().to_vec(),
modified.tree_hash_root(),
"Modification hash failed"
);
// Produce a new cache for the modified object and compare it to the updated cache.
let mut modified_cache = cached_tree_hash::TreeHashCache::new(&modified).unwrap();
// Reset the caches.
cache.reset_modifications();
modified_cache.reset_modifications();
// Ensure the modified cache is the same as a newly created cache. This is a sanity
// check to make sure there are no artifacts of the original cache remaining after an
// update.
assert_eq!(
modified_cache, cache,
"The modified cache does not match a new cache."
)
}
};
}

View File

@@ -15,9 +15,13 @@ mod testing_proposer_slashing_builder;
mod testing_transfer_builder;
mod testing_voluntary_exit_builder;
pub use generate_deterministic_keypairs::generate_deterministic_keypair;
pub use generate_deterministic_keypairs::generate_deterministic_keypairs;
pub use keypairs_file::KeypairsFile;
pub use rand::{prng::XorShiftRng, SeedableRng};
pub use rand::{
RngCore,
{prng::XorShiftRng, SeedableRng},
};
pub use serde_utils::{fork_from_hex_str, u8_from_hex_str};
pub use test_random::TestRandom;
pub use testing_attestation_builder::TestingAttestationBuilder;

View File

@@ -1,3 +1,5 @@
use crate::*;
use fixed_len_vec::typenum::Unsigned;
use rand::RngCore;
mod address;
@@ -8,54 +10,68 @@ mod public_key;
mod secret_key;
mod signature;
pub trait TestRandom<T>
where
T: RngCore,
{
fn random_for_test(rng: &mut T) -> Self;
pub trait TestRandom {
fn random_for_test(rng: &mut impl RngCore) -> Self;
}
impl<T: RngCore> TestRandom<T> for bool {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for bool {
fn random_for_test(rng: &mut impl RngCore) -> Self {
(rng.next_u32() % 2) == 1
}
}
impl<T: RngCore> TestRandom<T> for u64 {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for u64 {
fn random_for_test(rng: &mut impl RngCore) -> Self {
rng.next_u64()
}
}
impl<T: RngCore> TestRandom<T> for u32 {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for u32 {
fn random_for_test(rng: &mut impl RngCore) -> Self {
rng.next_u32()
}
}
impl<T: RngCore> TestRandom<T> for usize {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for usize {
fn random_for_test(rng: &mut impl RngCore) -> Self {
rng.next_u32() as usize
}
}
impl<T: RngCore, U> TestRandom<T> for Vec<U>
impl<U> TestRandom for Vec<U>
where
U: TestRandom<T>,
U: TestRandom,
{
fn random_for_test(rng: &mut T) -> Self {
vec![
<U>::random_for_test(rng),
<U>::random_for_test(rng),
<U>::random_for_test(rng),
]
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut output = vec![];
for _ in 0..(usize::random_for_test(rng) % 4) {
output.push(<U>::random_for_test(rng));
}
output
}
}
impl<T, N: Unsigned> TestRandom for FixedLenVec<T, N>
where
T: TestRandom + Default,
{
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut output = vec![];
for _ in 0..(usize::random_for_test(rng) % std::cmp::min(4, N::to_usize())) {
output.push(<T>::random_for_test(rng));
}
output.into()
}
}
macro_rules! impl_test_random_for_u8_array {
($len: expr) => {
impl<T: RngCore> TestRandom<T> for [u8; $len] {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for [u8; $len] {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut bytes = [0; $len];
rng.fill_bytes(&mut bytes);
bytes

View File

@@ -1,9 +1,8 @@
use super::TestRandom;
use super::*;
use crate::Address;
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for Address {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for Address {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut key_bytes = vec![0; 20];
rng.fill_bytes(&mut key_bytes);
Address::from_slice(&key_bytes[..])

View File

@@ -1,9 +1,8 @@
use super::TestRandom;
use super::*;
use bls::{AggregateSignature, Signature};
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for AggregateSignature {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for AggregateSignature {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let signature = Signature::random_for_test(rng);
let mut aggregate_signature = AggregateSignature::new();
aggregate_signature.add(&signature);

View File

@@ -1,9 +1,8 @@
use super::TestRandom;
use super::*;
use crate::Bitfield;
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for Bitfield {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for Bitfield {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut raw_bytes = vec![0; 32];
rng.fill_bytes(&mut raw_bytes);
Bitfield::from_bytes(&raw_bytes)

View File

@@ -1,9 +1,8 @@
use super::TestRandom;
use super::*;
use crate::Hash256;
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for Hash256 {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for Hash256 {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut key_bytes = vec![0; 32];
rng.fill_bytes(&mut key_bytes);
Hash256::from_slice(&key_bytes[..])

View File

@@ -1,9 +1,8 @@
use super::TestRandom;
use super::*;
use bls::{PublicKey, SecretKey};
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for PublicKey {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for PublicKey {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let secret_key = SecretKey::random_for_test(rng);
PublicKey::from_secret_key(&secret_key)
}

View File

@@ -1,9 +1,8 @@
use super::TestRandom;
use super::*;
use bls::SecretKey;
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for SecretKey {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for SecretKey {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let mut key_bytes = vec![0; 48];
rng.fill_bytes(&mut key_bytes);
/*

View File

@@ -1,9 +1,8 @@
use super::TestRandom;
use super::*;
use bls::{SecretKey, Signature};
use rand::RngCore;
impl<T: RngCore> TestRandom<T> for Signature {
fn random_for_test(rng: &mut T) -> Self {
impl TestRandom for Signature {
fn random_for_test(rng: &mut impl RngCore) -> Self {
let secret_key = SecretKey::random_for_test(rng);
let mut message = vec![0; 32];
rng.fill_bytes(&mut message);

View File

@@ -1,6 +1,6 @@
use crate::test_utils::TestingAttestationDataBuilder;
use crate::*;
use ssz::TreeHash;
use tree_hash::TreeHash;
/// Builds an attestation to be used for testing purposes.
///
@@ -12,8 +12,8 @@ pub struct TestingAttestationBuilder {
impl TestingAttestationBuilder {
/// Create a new attestation builder.
pub fn new(
state: &BeaconState,
pub fn new<T: EthSpec>(
state: &BeaconState<T>,
committee: &[usize],
slot: Slot,
shard: u64,
@@ -74,7 +74,7 @@ impl TestingAttestationBuilder {
data: self.attestation.data.clone(),
custody_bit: false,
}
.hash_tree_root();
.tree_hash_root();
let domain = spec.get_domain(
self.attestation.data.slot.epoch(spec.slots_per_epoch),

View File

@@ -10,7 +10,12 @@ pub struct TestingAttestationDataBuilder {
impl TestingAttestationDataBuilder {
/// Configures a new `AttestationData` which attests to all of the same parameters as the
/// state.
pub fn new(state: &BeaconState, shard: u64, slot: Slot, spec: &ChainSpec) -> Self {
pub fn new<T: EthSpec>(
state: &BeaconState<T>,
shard: u64,
slot: Slot,
spec: &ChainSpec,
) -> Self {
let current_epoch = state.current_epoch(spec);
let previous_epoch = state.previous_epoch(spec);
@@ -25,22 +30,22 @@ impl TestingAttestationDataBuilder {
let target_root = if is_previous_epoch {
*state
.get_block_root(previous_epoch.start_slot(spec.slots_per_epoch), spec)
.get_block_root(previous_epoch.start_slot(spec.slots_per_epoch))
.unwrap()
} else {
*state
.get_block_root(current_epoch.start_slot(spec.slots_per_epoch), spec)
.get_block_root(current_epoch.start_slot(spec.slots_per_epoch))
.unwrap()
};
let source_root = *state
.get_block_root(source_epoch.start_slot(spec.slots_per_epoch), spec)
.get_block_root(source_epoch.start_slot(spec.slots_per_epoch))
.unwrap();
let data = AttestationData {
// LMD GHOST vote
slot,
beacon_block_root: *state.get_block_root(slot, spec).unwrap(),
beacon_block_root: *state.get_block_root(slot).unwrap(),
// FFG Vote
source_epoch,

View File

@@ -1,5 +1,5 @@
use crate::*;
use ssz::TreeHash;
use tree_hash::TreeHash;
/// Builds an `AttesterSlashing`.
///
@@ -66,7 +66,7 @@ impl TestingAttesterSlashingBuilder {
data: attestation.data.clone(),
custody_bit: false,
};
let message = attestation_data_and_custody_bit.hash_tree_root();
let message = attestation_data_and_custody_bit.tree_hash_root();
for (i, validator_index) in validator_indices.iter().enumerate() {
attestation.custody_bitfield.set(i, false);

View File

@@ -6,7 +6,7 @@ use crate::{
*,
};
use rayon::prelude::*;
use ssz::{SignedRoot, TreeHash};
use tree_hash::{SignedRoot, TreeHash};
/// Builds a beacon block to be used for testing purposes.
///
@@ -43,7 +43,7 @@ impl TestingBeaconBlockBuilder {
/// Modifying the block's slot after signing may invalidate the signature.
pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) {
let epoch = self.block.slot.epoch(spec.slots_per_epoch);
let message = epoch.hash_tree_root();
let message = epoch.tree_hash_root();
let domain = spec.get_domain(epoch, Domain::Randao, fork);
self.block.body.randao_reveal = Signature::new(&message, domain, sk);
}
@@ -87,9 +87,9 @@ impl TestingBeaconBlockBuilder {
///
/// Note: the signed messages of the split committees will be identical -- it would be possible
/// to aggregate these split attestations.
pub fn insert_attestations(
pub fn insert_attestations<T: EthSpec>(
&mut self,
state: &BeaconState,
state: &BeaconState<T>,
secret_keys: &[&SecretKey],
num_attestations: usize,
spec: &ChainSpec,
@@ -176,11 +176,11 @@ impl TestingBeaconBlockBuilder {
}
/// Insert a `Valid` deposit into the state.
pub fn insert_deposit(
pub fn insert_deposit<T: EthSpec>(
&mut self,
amount: u64,
index: u64,
state: &BeaconState,
state: &BeaconState<T>,
spec: &ChainSpec,
) {
let keypair = Keypair::random();
@@ -198,9 +198,9 @@ impl TestingBeaconBlockBuilder {
}
/// Insert a `Valid` exit into the state.
pub fn insert_exit(
pub fn insert_exit<T: EthSpec>(
&mut self,
state: &BeaconState,
state: &BeaconState<T>,
validator_index: u64,
secret_key: &SecretKey,
spec: &ChainSpec,
@@ -219,9 +219,9 @@ impl TestingBeaconBlockBuilder {
///
/// Note: this will set the validator to be withdrawable by directly modifying the state
/// validator registry. This _may_ cause problems historic hashes, etc.
pub fn insert_transfer(
pub fn insert_transfer<T: EthSpec>(
&mut self,
state: &BeaconState,
state: &BeaconState<T>,
from: u64,
to: u64,
amount: u64,

View File

@@ -25,12 +25,12 @@ pub fn keypairs_path() -> PathBuf {
///
/// This struct should **never be used for production purposes.**
#[derive(Clone)]
pub struct TestingBeaconStateBuilder {
state: BeaconState,
pub struct TestingBeaconStateBuilder<T: EthSpec> {
state: BeaconState<T>,
keypairs: Vec<Keypair>,
}
impl TestingBeaconStateBuilder {
impl<T: EthSpec> TestingBeaconStateBuilder<T> {
/// Attempts to load validators from a file in `$HOME/.lighthouse/keypairs.raw_keypairs`. If
/// the file is unavailable, it generates the keys at runtime.
///
@@ -154,7 +154,7 @@ impl TestingBeaconStateBuilder {
}
/// Consume the builder and return the `BeaconState` and the keypairs for each validator.
pub fn build(self) -> (BeaconState, Vec<Keypair>) {
pub fn build(self) -> (BeaconState<T>, Vec<Keypair>) {
(self.state, self.keypairs)
}

View File

@@ -12,7 +12,7 @@ impl TestingDepositBuilder {
/// Instantiates a new builder.
pub fn new(pubkey: PublicKey, amount: u64) -> Self {
let deposit = Deposit {
proof: vec![],
proof: vec![].into(),
index: 0,
deposit_data: DepositData {
amount,

View File

@@ -16,7 +16,12 @@ impl TestingPendingAttestationBuilder {
///
/// * The aggregation and custody bitfields will all be empty, they need to be set with
/// `Self::add_committee_participation`.
pub fn new(state: &BeaconState, shard: u64, slot: Slot, spec: &ChainSpec) -> Self {
pub fn new<T: EthSpec>(
state: &BeaconState<T>,
shard: u64,
slot: Slot,
spec: &ChainSpec,
) -> Self {
let data_builder = TestingAttestationDataBuilder::new(state, shard, slot, spec);
let pending_attestation = PendingAttestation {

View File

@@ -1,5 +1,5 @@
use crate::*;
use ssz::SignedRoot;
use tree_hash::SignedRoot;
/// Builds a `ProposerSlashing`.
///

View File

@@ -1,5 +1,5 @@
use crate::*;
use ssz::SignedRoot;
use tree_hash::SignedRoot;
/// Builds a transfer to be used for testing purposes.
///

View File

@@ -1,5 +1,5 @@
use crate::*;
use ssz::SignedRoot;
use tree_hash::SignedRoot;
/// Builds an exit to be used for testing purposes.
///

View File

@@ -2,15 +2,16 @@ use super::Slot;
use crate::test_utils::TestRandom;
use bls::{PublicKey, Signature};
use derivative::Derivative;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// The data submitted to the deposit contract.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
Clone,
@@ -19,6 +20,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
Derivative,
@@ -41,4 +43,5 @@ mod tests {
use super::*;
ssz_tests!(Transfer);
cached_tree_hash_tests!(Transfer);
}

View File

@@ -1,13 +1,25 @@
use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKey};
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::{CachedTreeHash, TreeHash};
/// Information about a `BeaconChain` validator.
///
/// Spec v0.5.0
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)]
/// Spec v0.5.1
#[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
Encode,
Decode,
TestRandom,
TreeHash,
CachedTreeHash,
)]
pub struct Validator {
pub pubkey: PublicKey,
pub withdrawal_credentials: Hash256,
@@ -110,4 +122,5 @@ mod tests {
}
ssz_tests!(Validator);
cached_tree_hash_tests!(Validator);
}

View File

@@ -1,14 +1,15 @@
use crate::{test_utils::TestRandom, Epoch};
use bls::Signature;
use rand::RngCore;
use serde_derive::{Deserialize, Serialize};
use ssz::TreeHash;
use ssz_derive::{Decode, Encode, SignedRoot, TreeHash};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash::TreeHash;
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
/// An exit voluntarily submitted a validator who wishes to withdraw.
///
/// Spec v0.5.0
/// Spec v0.5.1
#[derive(
Debug,
PartialEq,
@@ -18,6 +19,7 @@ use test_random_derive::TestRandom;
Encode,
Decode,
TreeHash,
CachedTreeHash,
TestRandom,
SignedRoot,
)]
@@ -33,4 +35,5 @@ mod tests {
use super::*;
ssz_tests!(VoluntaryExit);
cached_tree_hash_tests!(VoluntaryExit);
}